Documentation
¶
Overview ¶
Package verify implements behavior probes for MCP servers introduced in SDK v1.4.0–v1.6.0. Each probe is a self-contained check that drives a target server with a single malformed/edge-case request and reports pass/fail plus a fix suggestion.
Probes are designed for reuse by the conformance suite (Tier-3 follow-up) and for unit-testing in isolation: each probe takes a Target value and produces a ProbeResult — no global state, no shared transport, no hidden CLI coupling.
Index ¶
- Variables
- func AllPassed(results []ProbeResult) bool
- func IsHTTPProbe(name string) bool
- type ProbeResult
- func ProbeContentType(ctx context.Context, t Target) ProbeResult
- func ProbeCrossOrigin(ctx context.Context, t Target) ProbeResult
- func ProbeDNSRebind(ctx context.Context, t Target) ProbeResult
- func ProbeMCPMethodHeaders(ctx context.Context, t Target) ProbeResult
- func ProbeOriginHeader(ctx context.Context, t Target) ProbeResult
- func ProbeSetErrorContent(ctx context.Context, t Target) ProbeResult
- func Run(ctx context.Context, name string, target Target) ProbeResult
- func RunAll(ctx context.Context, target Target) []ProbeResult
- type Target
Constants ¶
This section is empty.
Variables ¶
var AllProbes = []string{
"cross-origin",
"dns-rebind",
"content-type",
"origin-header",
"mcp-method-headers",
"seterror-content",
}
AllProbes is the canonical list of probe names in display order. Drives the --probe flag's allowed values, the --json output ordering, and the conformance suite's iteration plan.
Functions ¶
func AllPassed ¶
func AllPassed(results []ProbeResult) bool
AllPassed returns true when every probe in results passed. An empty slice counts as failure — callers that pass an empty list want exit 1.
func IsHTTPProbe ¶
IsHTTPProbe reports whether a probe needs a URL target rather than a stdio command. The CLI dispatcher uses this to validate the supplied target shape before invoking probes.
Types ¶
type ProbeResult ¶
type ProbeResult struct {
Name string `json:"name"`
Pass bool `json:"pass"`
Error string `json:"error,omitempty"`
Fix string `json:"fix,omitempty"`
}
ProbeResult is the typed outcome of a single behavior probe. The shape is fixed by the task spec — Tier-3 conformance suite re-uses these fields verbatim.
Name — probe identifier matching the --probe flag value Pass — true when the server's behavior matches the expected contract Error — concrete failure detail when Pass=false (empty on pass) Fix — human-readable suggestion the user can apply (empty on pass)
func ProbeContentType ¶
func ProbeContentType(ctx context.Context, t Target) ProbeResult
ProbeContentType sends a POST with text/plain to confirm the server rejects non-JSON payloads. The streamable-HTTP spec (§2.1) requires Content-Type application/json; SDK servers respond with 415 Unsupported Media Type or 400 Bad Request when the payload doesn't match.
func ProbeCrossOrigin ¶
func ProbeCrossOrigin(ctx context.Context, t Target) ProbeResult
ProbeCrossOrigin sends a streamable-HTTP POST with an Origin header pointing at a foreign domain. Per SDK v1.4.1 (PR #842) and the CrossOriginProtection middleware shipped with go-sdk, compliant servers reject such requests with 403 Forbidden.
func ProbeDNSRebind ¶
func ProbeDNSRebind(ctx context.Context, t Target) ProbeResult
ProbeDNSRebind sends a request to a 127.0.0.1 origin with a non-localhost Host header — the canonical DNS-rebinding attack shape. SDK v1.4.0 (PR #760) added DisableLocalhostProtection=false default; compliant streamable-HTTP servers reject with 403/421.
func ProbeMCPMethodHeaders ¶
func ProbeMCPMethodHeaders(ctx context.Context, t Target) ProbeResult
ProbeMCPMethodHeaders verifies SEP-2243 MCP-Method/MCP-Name advisory headers reach the server when the client sets them. The probe doesn't check that the SERVER returns the headers (servers ignore unknown headers per spec) — instead it sends a tools/call request with the headers AND records what the server received via a custom HTTP client that captures the outbound request.
This is fundamentally a CLIENT-side check (does mcp-tui's --mcp-method-headers feature set them on the wire?), but framed as a "verify" probe so it shares the dispatcher with the security probes.
func ProbeOriginHeader ¶
func ProbeOriginHeader(ctx context.Context, t Target) ProbeResult
ProbeOriginHeader confirms Origin enforcement applies to POST but NOT to GET/HEAD requests on the same endpoint. Streamable-HTTP allows GET-without-Origin for the listening stream; tightening it would break CORS preflight and proxy probes.
The probe sends two requests:
- GET without Origin — expected: 2xx, 405 Method Not Allowed, or any non-403 (server may simply not support GET, that's fine — what we care about is "GET without Origin is NOT rejected with 403").
- POST without Origin — expected: 4xx (rejection on the POST path).
func ProbeSetErrorContent ¶
func ProbeSetErrorContent(ctx context.Context, t Target) ProbeResult
ProbeSetErrorContent invokes a tool and confirms isError:true responses carry their Content payload. SDK v1.6.0 (PR #864) reaffirmed that the CallToolResult.Content slice MUST be preserved when IsError is true — without it, the LLM can't see what went wrong and self-correct.
The probe connects via mcp.Service over stdio, calls the configured tool, and asserts:
- The call returned IsError=true (the tool is genuinely a "fails by design" tool — if it succeeds, the probe is misconfigured).
- The result has at least one Content entry with non-empty Text.
If the user's target tool doesn't naturally fail, the probe reports inconclusive (Pass=false with a Fix that explains the misconfig).
type Target ¶
type Target struct {
// URL is the streamable-HTTP endpoint for HTTP-class probes (cross-origin,
// dns-rebind, content-type, origin-header, mcp-method-headers).
URL string
// Command + Args are the stdio command for the seterror-content probe
// (and any future stdio probe). Treated as already-validated — the CLI
// dispatcher runs config.ValidateCommand before constructing the Target.
Command string
Args []string
// ToolName overrides which tool the seterror-content probe will call.
// Empty defaults to "everything"-style "echo" — left configurable so
// users can point at their own server's known-isError-true tool.
ToolName string
// ToolArgs is the JSON-shaped argument map for the seterror probe's
// tool call. Default empty object {} works for trivial tools.
ToolArgs map[string]any
// HTTPClient lets tests inject a custom client (e.g. one that allows
// connections to httptest server addresses). Nil → http.DefaultClient
// with a short per-probe timeout.
HTTPClient *http.Client
}
Target carries everything a probe needs to drive a remote server. For HTTP probes only URL is consulted; for the stdio-only seterror-content probe, Command/Args take over. Both are populated from the same CLI argument (`mcp-tui verify <url|cmd>`).