· Paul Crossland
An MCP Fetch Crosses Five Evidence Planes
Portable plugins and gateway detection expose five evidence planes between an installed MCP tool and the web data it returns.
An agent can retrieve a page successfully while every control surface tells a different story. The plugin manager says a fetch tool was installed. The client says it invoked the tool. A network dashboard may show no recognizable MCP traffic. The tool server authorized a call. The browser worker returned one partial record.
Each observation describes a different part of a distributed fetch.
Two fresh releases make this gap operational rather than theoretical. On August 14, Cloudflare described MCP traffic detection and security controls that use protocol signals on inspected network paths while explicitly documenting blind spots such as local stdio servers, off-network connections, traffic excluded from inspection, and older or nonconforming clients. On August 12, GitHub announced Agent Plugins 1.0 support across its agent clients, making one package able to carry skills and MCP server configuration into VS Code, Copilot CLI, the Copilot app, and compatible clients.
The practical thesis is: as plugins make MCP-backed fetch tools portable across clients, operators must reconcile package intent, client invocation, network transport, server authorization, and backend fetch evidence, because absence from any one plane does not prove that no retrieval happened.
This is not guidance for hiding tool traffic, avoiding inspection, or reaching content after a denial. Unknown servers, unapproved transports, login boundaries, challenges, rate limits, and source-policy decisions should stop or narrow a run. The purpose of cross-plane evidence is to find unmanaged or incomplete execution and keep permitted retrieval auditable.
The repeated angle to avoid
Recent Better Fetch posts already cover agent control points, session evidence, human-to-agent handoffs, browser fidelity tiers, route graphs, and browser-visible MCP state. The repeated article would merely say that MCP calls need more logs or approvals.
The new surplus is a reconciliation model. Portable packaging expands where a fetch tool can be declared, while protocol-aware gateways expose one transport class. Neither proves which configuration loaded, whether a local process ran, whether the server authorized a handler, or which browser evidence supported the returned fact. One universal mcp_request_count cannot close those gaps.
Source map
Fresh primary evidence from the last seven days:
| Source | Date | Contribution |
|---|---|---|
| How Cloudflare detects MCP traffic and helps secure it | 2026-08-14 | Separates client, managed-network, and server control points; documents protocol-header detection and its visibility limits; distinguishes unknown servers from direct use outside an approved path. |
| Agent Plugins 1.0 in VS Code, Copilot CLI, and the Copilot app | 2026-08-12 | Shows portable distribution of skills and MCP configurations across clients, marketplaces, and organization policy surfaces. |
Older background comes from the Agent Plugins 1.0 specification, which defines local stdio and remote HTTP entries, and the stateless MCP 2026-07-28 specification. The web-retrieval synthesis is to follow one fact from installed package to browser or HTTP evidence instead of treating the tool response as the whole fetch record.
Five planes, five different claims
A fetch exposed through MCP crosses at least these evidence planes:
| Plane | What it can establish | What it cannot establish alone |
|---|---|---|
| Package | Plugin identity, version, source, declared skill, and declared MCP transport | That a client loaded it, that its runtime configuration was unchanged, or that a call occurred |
| Client | Agent run, selected server and tool, approved arguments, transport chosen, and local process launch | What a managed gateway observed, whether the server completed the handler, or whether returned web data is complete |
| Network | User or device, destination, timing, inspected protocol signals, route, and approved-path classification | Local stdio activity, off-path traffic, model intent, handler execution, or backend browser evidence |
| Tool server | Authenticated principal, tool schema, authorization verdict, rate limit, handler timing, and result envelope | Which plugin package initiated the call or whether every downstream page supplied valid evidence |
| Fetch backend | HTTP or browser mode, redirects, sessions, policy outcomes, rendered artifacts, extraction provenance, and completeness | Whether the client was allowed to request the task unless upstream identity and scope survive the handoff |
Cloudflare's fresh write-up explains why network inference is conditional. A conforming remote HTTP request can expose MCP-Protocol-Version; the newer stateless shape also exposes method and tool-name headers. Those are useful positive signals. Their absence is not a reliable negative signal: an initial legacy request, local stdio server, nonconforming client, excluded connection, or off-network path may not produce visible headers on an inspected gateway.
Portable plugins widen that distinction. A package can declare a local command or a remote endpoint. Two compatible clients can install the same package but support different transports, apply different organization settings, or produce different client telemetry. Package presence therefore proves deployable capability, not execution. Network presence proves an observed remote transaction, not the complete tool inventory.
Join the planes before judging the data
Use separate identifiers, then carry a correlation chain through the approved path:
plugin_install_id, package digest, version, marketplace or repository, and policy verdict;agent_run_id, client name and version, principal, task scope, and approval state;mcp_call_id, server identity, tool name, protocol version, declared and effective transport, and argument-schema hash;network_span_id, managed-path class, destination class, protocol-detection result, inspection eligibility, and timing;tool_execution_id, authenticated principal, authorization decision, handler version, rate-limit outcome, and result-schema hash;fetch_job_id, fetch mode, browser or HTTP runtime, session class, region, source-policy outcome, evidence artifacts, and extraction verdict.
Do not put credentials, complete tool arguments, cookies, authenticated URLs, or private response bodies in broad telemetry. Store schema hashes, bounded redacted summaries, artifact references, and policy outcomes. Sensitive request and response inspection requires an explicit purpose, access policy, and retention limit.
Correlation must survive fan-out. One tool call may fetch many URLs, and one record may combine several fields. Give each important field a provenance pointer to its source response, DOM region, structured payload, or screenshot assertion. A successful MCP response proves that the protocol exchange completed, not that every field met the data product's evidence contract.
Failure modes hidden by a single dashboard
Cross-plane reconciliation separates incidents that otherwise look identical:
- Installed but never loaded. The package inventory contains the plugin, but client policy rejects its version or marketplace. There should be no call or fetch job.
- Local execution with no network MCP signal. The client launches a permitted stdio server, which later performs an ordinary HTTPS fetch. A gateway may see web traffic without recognizing an MCP transaction.
- Remote call outside the approved route. Client and server records exist, but the expected managed-path span does not. Quarantine the run and investigate configuration; do not assume the data is publishable because the handler succeeded.
- Network-positive, server-negative. The gateway classifies a request, but the server denies authorization, rejects the schema, or never invokes the handler. No backend retry should turn that policy result into a fetch.
- Tool-success, evidence-partial. The handler returns a valid result envelope even though a browser frame detached, an API response failed, or a required field remained incomplete. Protocol success must not become extraction success.
- Orphan backend job. A browser job exists without an attributable tool execution and task scope. Stop publication even if its pages rendered correctly.
These classifications prevent false confidence and stop retry systems from treating authorization, observability, and page failures as one transient error.
An owned-fixture reconciliation test
Test the chain on owned services or partner-approved environments:
- Publish a test plugin with one permitted local stdio server and one permitted remote HTTP server. Record its digest and declared transports.
- Install it in every supported client. Confirm package policy, component discovery, and effective transport are reported separately.
- Invoke a read-only fixture tool through each transport. Assert that the local call has client and server evidence without requiring a network MCP classification, while the remote call has the expected managed-path span.
- Deny one call at client policy and another at server authorization. Verify that neither creates a backend fetch job.
- Return a controlled partial page: navigation succeeds, but one required fixture field never becomes ready. Require
evidence_partialeven though MCP and handler execution succeed. - Remove one correlation identifier at a time. Confirm that orphan calls and jobs are quarantined rather than joined by timestamp guesses.
- Use an approved isolated test path that does not traverse the managed gateway. Verify that policy records the route mismatch and no result reaches publication.
- Repeat after client, plugin, gateway policy, MCP server, browser, or extractor upgrades. Compare the chain, not only final tool output.
The operator decision rule
Start incident review with the earliest plane whose expected evidence is missing. If package policy rejected the component, do not debug the network. If client invocation exists but an expected remote span does not, investigate transport and route configuration. If the network saw a call but the server did not authorize it, preserve the denial. If the server completed but no attributable fetch job exists, suppress the result. If the fetch job exists but required evidence is partial, quarantine affected fields regardless of MCP success.
Most importantly, never interpret missing gateway visibility as permission to continue or as proof that nothing ran. Treat it as an evidence state whose meaning depends on the declared transport and managed-path contract.
MCP is making browser-grade retrieval easier to distribute and invoke. That convenience moves the reliability boundary outward: from one fetch service to packages, clients, networks, tool servers, and backend workers. A trustworthy system should be able to trace the returned fact across all five planes—or say exactly where the evidence stops.