{"slug": "what-a-real-mcp-and-a2a-conformance-scan-actually-checks", "title": "What a Real MCP and A2A Conformance Scan Actually Checks", "summary": "Agent Protocol Inspector reports a three-state result — not_detected, indicated, or confirmed — for each MCP and A2A protocol it scans, requiring servers to pass specific per-protocol checks rather than a single boolean. The scanner probes the MCP 2026-07-28 stateless server/discover call first and falls back to the legacy initialize handshake, and it follows the full RFC 9728 auth discovery chain, flagging DCR-only servers with a deprecation note because Client ID Metadata Documents are now the current client-registration mechanism. The 2026-07-28 MCP revision put Roots, Sampling, and Logging on a deprecation track with removal no earlier than 2027-07-28 and shortened the runway for the HTTP+SSE transport (protocol version 2024-11-05), deprecated since March 2025.", "body_md": "# What a Real MCP and A2A Conformance Scan Actually Checks\n\nInside the MCP and A2A conformance checks that go beyond detection: server/discover vs the legacy initialize handshake, RFC 9728 auth metadata, CIMD vs DCR, and agent-card spec-lint rules.\n\n\"Does this URL support MCP?\" is the easy question. A `200` response from a Streamable HTTP endpoint answers it in one request. The harder, more useful question is whether that endpoint actually implements the spec correctly enough to be worth depending on — and that requires checking a lot more than whether it answers at all.\n\nAgent Protocol Inspector reports a three-state result for every protocol it checks: **`not_detected`**, **` indicated`** (some signal, not fully validated), or **` confirmed`** (found and validated). Getting to `confirmed` means passing a specific set of checks per protocol, each producing its own evidence — not a single boolean.\n\n## MCP: Two Eras, One Scanner\n\nThe Model Context Protocol's **2026-07-28** revision replaced the original stateful design with a fully stateless core, and a real conformance scan has to speak both.\n\n**Legacy (pre-2026-07-28).** A client sends a JSON-RPC `initialize` request with its `protocolVersion` and `clientInfo`; the server responds with its own `serverInfo`, negotiated `protocolVersion`, and a `Mcp-Session-Id` header that scopes every subsequent call.\n\n**Modern (2026-07-28+).** The stateful handshake is gone. Every request carries its protocol version via `_meta`, and a new mandatory `server/discover` call advertises supported versions and capabilities up front, with no session to establish first. This revision also put **Roots**, **Sampling**, and **Logging** on a deprecation track (removal no earlier than 2027-07-28) and shortened the runway for the dedicated HTTP+SSE transport (protocol version 2024-11-05), which has been deprecated since March 2025.\n\nA scanner that only speaks one era silently misreports every server on the other one as broken. Agent Protocol Inspector probes `server/discover` first and falls back to the legacy `initialize` handshake — both paths produce a real `confirmed` result with the era recorded, not just a pass/fail.\n\nBeyond the handshake itself, the scan checks things that only show up on a second look:\n\n- **Tool list stability** — calling`tools/list` twice and comparing ordering. A tool list that reorders between identical calls is a real integration hazard for any client that indexes tools positionally.\n- **Cache metadata presence** — whether the server declares a TTL and scope for its tool list, missing on servers that never considered client-side caching.\n- **Extensions** — non-core capability extensions the server advertises beyond the baseline spec.\n\n## MCP Authentication: Beyond \"Requires OAuth\"\n\nAn MCP server behind auth answers with a `401` or `403` and a `WWW-Authenticate` header. From there, the scan follows the actual discovery chain a real client would have to implement:\n\n1. Parse `resource_metadata` out of the challenge, or check`/.well-known/oauth-protected-resource` directly (RFC 9728).\n2. Read the declared `authorization_servers[0]` as the issuer.\n3. Check the issuer's `/.well-known/openid-configuration` and`/.well-known/oauth-authorization-server` (RFC 8414) independently — not one as a fallback for the other, since an issuer can genuinely serve both.\n4. Classify the client-registration mechanism: **Client ID Metadata Documents** (`client_id_metadata_document_supported: true` ) versus**Dynamic Client Registration** (a bare`registration_endpoint` , RFC 7591). DCR-only gets flagged with a specific deprecation note, since CIMD is the current mechanism.\n\nThat step-3 independence turned out to matter in practice — we cover exactly how, and what it looks like on real MCP servers, in a [dedicated post on detecting OpenID Connect vs. bare OAuth 2.0](https://contextiq.trango-compute.com/blog/mcp-server-openid-connect-oauth2-detection).\n\n## A2A: Spec-Lint, Not Just Card-Parsing\n\nFetching an Agent Card successfully only means the JSON parsed. A `confirmed` A2A result also runs the card through a set of spec-hygiene checks:\n\n- **Required fields** —`protocolVersion` ,`version` ,`url` ,`description` all present.\n- **Skill quality** — at least one skill declared, and every skill has a description. A routing agent selects which agent to delegate to based on skill descriptions; a skill with no description is invisible to that routing logic even though it technically exists.\n- **Input/output modes declared** —`defaultInputModes` and`defaultOutputModes` present, since a client can't negotiate content types with an agent that never states what it accepts.\n- **Security scheme declared** — flagged when a production-shaped agent has no`securitySchemes` at all.\n- **Legacy path warning** — a card served only from`/.well-known/agent.json` (the pre-0.3.0 path) rather than the current`agent-card.json` .\n- **Embedded secrets** — the card's raw JSON is checked against a credential-pattern regex. An agent card is a public document by definition; a stray API key or bearer token baked into one is a real, surprisingly common leak class.\n- **OIDC URL resolution** — if the card declares an`openIdConnectUrl` in its security schemes, the scan actually fetches it and confirms it resolves to a document with an`issuer` or`authorization_endpoint` — a declared-but-dead discovery URL is worse than not declaring one, since a client will trust it until it tries to use it.\n\nTwo of these rules exist specifically because of false positives caught during validation against real targets, not theoretical ones: an early \"agent-card\" keyword and later a \"schema\" keyword were both dropped from unrelated matching logic after they fired on ordinary API-documentation language that had nothing to do with the capability being checked. Every rule that ships has been checked against a real card, not just written from the spec text.\n\n## Why the Distinction Matters\n\nA `confirmed` badge that only means \"an endpoint returned 200\" isn't something you can build a decision on. The warnings and lint layer is what turns \"this looks like MCP\" into \"this is a spec-conformant MCP server with declared, resolvable authentication metadata\" — the difference between a detection and something you can actually route production traffic to.\n\nRun [Agent Protocol Inspector](https://contextiq.trango-compute.com/agent-readiness-detector) against your own MCP server or A2A agent before you tell anyone else it's ready — the warnings it surfaces are the same gaps a real integrating client would hit first.\n\nFollow Trango Compute on LinkedIn\n\nWe post updates on new tools, context engineering patterns, and LLM cost research.\n\n[Follow on LinkedIn](https://www.linkedin.com/company/trango-compute)", "url": "https://wpnews.pro/news/what-a-real-mcp-and-a2a-conformance-scan-actually-checks", "canonical_source": "https://contextiq.trango-compute.com/blog/mcp-a2a-protocol-conformance-scan-explained", "published_at": "2026-09-18 00:00:00+00:00", "updated_at": "2026-09-28 15:19:50.046992+00:00", "lang": "en", "topics": ["agent-protocols", "ai-agents", "ai-tools", "developer-tools"], "entities": ["Agent Protocol Inspector", "Model Context Protocol", "A2A", "Client ID Metadata Documents", "Dynamic Client Registration", "RFC 9728", "RFC 8414", "RFC 7591"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/what-a-real-mcp-and-a2a-conformance-scan-actually-checks", "markdown": "https://wpnews.pro/news/what-a-real-mcp-and-a2a-conformance-scan-actually-checks.md", "text": "https://wpnews.pro/news/what-a-real-mcp-and-a2a-conformance-scan-actually-checks.txt", "jsonld": "https://wpnews.pro/news/what-a-real-mcp-and-a2a-conformance-scan-actually-checks.jsonld"}}