Skip to content

Proposal: Agent Identity Verification and Authorization Framework #105

@skamansam

Description

@skamansam

Sorry if this sounds like AI slop. I am currently undergoing chemotherapy and am having a hard time assembling ideas correctly in my head so I had Claude help me write this. (IMHO, this is apropo, considering the topic)

Summary

The current WebMCP spec doesn't provide a way for mcp tools to identify, verify, or authorize agents performing the tool calls. The ModelContextClient interface contains only requestUserInteraction. There isn't a way to make sure custom browsers like the ones google and bing use to gather data (or more nefarious actors) can't call the mcp and pass that data off as their own. It should be more than trivial to gather mcp results from sites that don't want it. This creates a significant trust gap that could undermine adoption and enable abuse by well-resourced actors.

Apps that have a backend can work around some of this by verifying agents against their own API. But a huge chunk of the modern web is pure client-side — static sites, SPAs, PWAs, browser extensions, JAMstack apps — and those have no server to fall back on. For them, the browser API is the only enforcement point, and right now it gives them nothing.

I'd like to open a discussion about adding agent identification, classification, and third-party token verification to the spec.

Problem

WebMCP makes web applications de facto MCP servers. But unlike traditional server-to-server APIs, there is currently:

  1. No way for a tool to know who's calling it. The execute callback gets input parameters and a ModelContextClient, but the client carries zero identity information. A search engine crawler, a browser-native assistant, a screen reader, and an actual human's agent session all look the same.

  2. No enforceable consent mechanism. requestUserInteraction depends on the agent's runtime to actually show the interaction to a user. A server-side agent like a search crawler has no user present and can just resolve the callback instantly without anyone seeing anything. That makes it a polite suggestion, not a security boundary.

  3. No way to set access policies. A site can't say "let assistive technologies in, let authenticated user agents in, but require a commercial agreement for search crawlers." Without identity, there's no basis for authorization.

The better a site implements WebMCP tools, the more structured and extractable its content becomes — and the site has zero control over who's extracting it or what they do with it. That's especially concerning when you realize the browser vendors most likely to implement WebMCP (Google, Microsoft) also run the largest AI platforms and search engines.

It's worth calling out that web apps exist on a spectrum. If you have a backend, you can work around some of this by deferring verification to your own API (see §3 below). But a huge and growing portion of the web doesn't have that luxury — static sites, SPAs, JAMstack, browser extensions, PWAs — they have no server to call back to. For those apps, the browser API is the only enforcement point. If the spec doesn't build identity and verification into ModelContextClient, pure client-side apps are just left completely unprotected.

Proposed Direction

I'm not trying to propose a complete solution here, but I want to put forward a few complementary ideas to get the discussion going:

1. Agent Identity Properties on ModelContextClient

Add self-reported identity information to ModelContextClient:

interface ModelContextClient {
  readonly attribute DOMString agentType;
  readonly attribute DOMString agentName;
  readonly attribute DOMString agentOrigin;
  Promise<any> requestUserInteraction(UserInteractionCallback callback);
};
  • agentType: A standardized classification. Values like "user_session", "browser_agent", "search_crawler", "assistive_technology", "automated_agent", etc. The spec could define an enum or a registry.
  • agentName: A human-readable identifier (e.g., "googlebot", "claude", "jaws").
  • agentOrigin: Where the agent comes from (e.g., "google.com", "anthropic.com").

Think of this as a structured User-Agent string, but part of the API contract instead of an optional header.

2. Third-Party Verification Tokens

Self-reported identity on its own isn't enough — User-Agent spoofing is trivial and everyone knows it. The spec should support cryptographically verifiable identity through third-party attestation:

dictionary AgentVerification {
  DOMString token;
  DOMString issuer;
  DOMString issuerKeyUrl;
};

partial interface ModelContextClient {
  readonly attribute AgentVerification? verification;
};
  • token: A signed token (like a JWT) attesting to the agent's identity and type.
  • issuer: The verification authority that issued the token.
  • issuerKeyUrl: Where the tool provider can grab the issuer's public key to verify the token.

This is the same trust model as TLS certificates — you don't trust the agent's word, you trust that a verification authority checked them out. Sites pick which issuers they trust, just like browsers maintain trusted CA lists.

3. Server-Side Verification (for apps that have a backend)

If your app has a backend, you can defer verification to your own server. The spec doesn't need to mandate this, but it should explicitly acknowledge and support the pattern:

execute: async (input, client) => {
  const authResult = await fetch("/api/verify-agent", {
    method: "POST",
    body: JSON.stringify({
      token: client.verification?.token,
      agentType: client.agentType,
      agentName: client.agentName
    })
  });

  if (!authResult.ok) {
    return { error: "unauthorized", message: "Agent not authorized for this tool" };
  }

  return await performToolAction(input);
}

This is the strongest enforcement model because the authorization decision happens on your own infrastructure, where the agent can't tamper with it. If you have a backend, you should use this.

But not every app has a backend. A big portion of the modern web runs without a traditional server — static sites on CDNs, client-side-only tools, browser extensions, PWAs that work offline. These apps can't phone home to verify anything. Their execute callback is the only code they control, and if the identity and verification info on ModelContextClient is unreliable or missing, they have zero recourse.

4. Browser-Level Enforcement for Pure Client-Side Apps

This is where the spec needs to do the most work. For apps with no backend, identity and verification have to be meaningful without a server round-trip. That means:

  • The browser itself needs to populate ModelContextClient properties honestly. If the browser says agentType: "user_session", that should be trustworthy because the browser set it, not the agent. Same idea as same-origin policy — the app doesn't verify it, the platform guarantees it.

  • Tokens should be verifiable client-side. If we go with a token-based model (see §2), tokens should be verifiable using a public key fetched from the issuer. Web Crypto API already supports everything needed for this — crypto.subtle.verify() with RSA or ECDSA works fine.

  • The spec should define a declarative policy mechanism so pure client-side apps can express access rules without writing custom verification code:

navigator.modelContext.provideContext({
  tools: [myTool],
  policy: {
    allowAgentTypes: ["user_session", "browser_agent", "assistive_technology"],
    denyAgentTypes: ["search_crawler"],
    requireVerification: true
  }
});

With a declarative policy, the browser enforces access rules before execute even gets called. That's critical for pure client-side apps because it moves enforcement out of JavaScript (which the agent's runtime controls) and into the browser platform (which it doesn't — at least for legitimate browser-based agents).

This won't stop a headless crawler from ignoring the policy entirely. But it establishes a normative expectation that compliant agents have to honor, and gives browser vendors clear requirements for their own built-in agents.

Use Cases This Enables

Apps with backends:

  • A recipe site lets assistive technologies and authenticated user agents use its tools freely, but requires search crawlers to present a commercial licensing token — verified against its own API.
  • A SaaS app lets its own browser agent call tools, but blocks third-party agents that haven't been vetted — enforced server-side with full token validation.
  • A news site exposes tools for personalization and navigation to user-facing agents, but blocks automated agents that would scrape article content without attribution or payment.

Pure client-side apps (no backend):

  • A static-site calculator or converter registers WebMCP tools so agents can use it, but uses declarative policy to block search crawlers from indexing its results as their own.
  • A client-side code playground (think JSFiddle or CodePen) hosted on a CDN exposes tools for running and sharing snippets, and relies on browser-enforced agentType checks since there's no server to verify tokens against.
  • A browser extension that provides WebMCP tools needs to tell the difference between a user's chosen agent and an unauthorized third-party agent, entirely in client-side code.
  • A PWA with offline capabilities registers tools that should only be accessible to user-session agents, not crawlers — and needs to enforce this even when offline with no network access at all.

Both:

  • An open-source project exposes tools freely to all verified agent types, but wants to track usage by agent classification for analytics.

Open Questions

These don't need answers before the discussion starts, but they're worth flagging:

  1. Who runs the verification authorities? W3C? An independent consortium? Multiple competing authorities like the CA ecosystem? A federated model where sites pick which issuers they trust?
  2. Should agent identity be mandatory or optional? If optional, sites can still refuse to serve unverified agents, and market pressure drives adoption. If mandatory, it's stronger but harder to get consensus on.
  3. How does this interact with requestUserInteraction? Should a verified "user_session" agent get different treatment from a verified "search_crawler" when it comes to user interaction requirements?
  4. What happens when an agent lies about what it is? Is that purely a legal/policy problem, or should the spec define error handling for verification failures?
  5. Should WebMCP inherit MCP's authorization spec directly? The server-side MCP spec already has OAuth 2.1, CIMD, and step-up authorization. Should WebMCP adopt these as-is, or does the browser context need a different approach? (See Prior Art section below.)
  6. How much should the browser enforce for pure client-side apps? Apps with backends can verify tokens server-side, but client-only apps depend entirely on the browser for enforcement. Should the spec mandate that browsers populate ModelContextClient properties truthfully for their own built-in agents? Should it define a declarative policy model that the browser enforces before invoking execute? How far can browser-level enforcement realistically go when the agent is external — like a server-side crawler rendering the page headlessly?
  7. Should client-side token verification be a first-class feature? If tokens are JWTs signed with asymmetric keys, pure client-side apps could verify them using Web Crypto without any server. Should the spec define a standard verification flow that works entirely in the browser?

Prior Art and Existing Standards

None of this requires inventing new crypto or novel trust architectures. The building blocks already exist in battle-tested standards. The problem is that none of them have been brought into WebMCP, even though "regular" MCP already uses several of them.

It's worth noting that most of these standards were designed for server-to-server communication. Adapting them for WebMCP means thinking about the fact that a lot of web apps are pure client-side and can't lean on a backend for verification. I've noted where each standard could work for client-only enforcement and where it falls short.

MCP's Own Authorization Spec (OAuth 2.1 + CIMD)

The server-side Model Context Protocol — the spec WebMCP takes its name from — already has a mature authorization layer. The MCP authorization specification uses OAuth 2.1 as its foundation and classifies MCP servers as OAuth Resource Servers. SEP-991 introduced Client ID Metadata Documents (CIMD) as the default way for clients to identify themselves.

CIMD creates a decentralized trust model based on DNS: a client publishes a metadata document at a URL it controls (e.g., https://claude.anthropic.com/.well-known/mcp-client.json), and servers verify the client's identity by fetching and validating that document. No centralized registration needed, but you still get verifiable identity.

The MCP spec also supports:

  • Step-up authorization — servers can request additional scopes incrementally instead of asking for everything upfront.
  • Resource Indicators (RFC 8707) — tokens are bound to their intended audience, so a malicious server can't reuse a token somewhere else.
  • PKCE (RFC 7636) — lets public clients (which can't store secrets) use authorization flows securely.

WebMCP dropped all of this when it brought MCP into the browser. The entire authorization layer just got left behind. This proposal is basically asking: why doesn't WebMCP inherit the auth model that MCP itself already requires?

Client-side feasibility: CIMD is interesting for WebMCP because it's DNS-based and doesn't need a real-time server round-trip — the metadata document can be fetched and cached. But the OAuth 2.1 token flows that MCP uses do need a server-side authorization endpoint, which works for apps with backends but not for pure client-side stuff. A WebMCP adaptation could use CIMD for agent identity while swapping in a client-side-verifiable token format instead of the OAuth access token.

Privacy Pass / Private Access Tokens (IETF RFCs 9576, 9577, 9578)

Privacy Pass is an IETF standard for creating and redeeming anonymous, unlinkable tokens that attest to client properties. It defines four roles that map pretty cleanly onto WebMCP:

Privacy Pass Role WebMCP Equivalent
Origin Website registering WebMCP tools
Client AI agent calling tools
Attester Entity verifying the agent's identity/classification
Issuer Entity producing cryptographic tokens

Two properties make it well-suited here:

  1. Unlinkability — a redeemed token can't be traced back to when it was issued, so the agent's (and user's) privacy is protected while the site can still verify legitimacy.
  2. Federated attestation — different attesters can coexist and sites choose which ones they trust. No single verification authority gets to be the gatekeeper.

This isn't theoretical. Apple already ships it as Private Access Tokens in Safari, using the device's secure enclave for attestation. Cloudflare uses it across millions of websites for bot management. It's production infrastructure.

For WebMCP, this could work like: the tool's execute callback challenges the agent for a token → the agent contacts a trusted attester to prove its identity → the attester facilitates token issuance → the agent presents the token → the site verifies it and decides whether to proceed.

Client-side feasibility: Privacy Pass tokens can be verified with public keys, which means a pure client-side app could verify them without a server round-trip. Web Crypto API has everything you need. This makes Privacy Pass one of the most promising models for protecting pure client-side WebMCP apps.

OAuth 2.0 Client Credentials Grant (RFC 6749, Section 4.4)

The Client Credentials flow is the standard for machine-to-machine authentication — an application authenticates with its own credentials instead of on behalf of a user. Pretty much every major API platform uses it.

The pattern is straightforward: the agent registers with the service, gets a client_id and client_secret, exchanges them for an access token, and includes it in requests. The service can then enforce per-client policies — rate limits, scope restrictions, usage tracking, commercial terms.

The catch for WebMCP is that Client Credentials assumes the client can securely store a secret, which a browser-based agent can't. But that's already a solved problem through PKCE (RFC 7636), which the MCP spec already mandates. PKCE lets public clients use authorization flows securely without a long-lived secret.

Client-side feasibility: OAuth flows need a token endpoint (a server) to issue and validate tokens, so they work well for apps with backends but not so much for pure client-side apps. A client-only app would need to rely on either browser-level enforcement of agent identity or a token format like signed JWTs that can be verified locally. OAuth is the model for backend-capable apps; Privacy Pass or similar approaches fill the gap for client-only use.

Web Environment Integrity (Cautionary Tale)

Google's Web Environment Integrity (WEI) proposal from 2023 is a good example of what happens when attestation goes in the wrong direction. WEI would have let websites require browsers to prove they were "legitimate" through a third-party attestation server — almost certainly run by Google. Mozilla called it harmful, Vivaldi called it dangerous, and the community saw it as DRM for the web. Google killed it in November 2023.

The key difference from what I'm proposing here: WEI was designed to let servers gatekeep users' access to the web, with browser vendors as the monopoly attesters. This is the reverse — it's about letting site owners verify and authorize agents before exposing their tools. The power flows toward the site owner, not the browser vendor. The site decides which attesters to trust and which agents to serve. No single company gets veto power over who can use the web.

That said, WEI's failure is a reminder of what matters:

  • Federated attesters, not a single authority
  • Verification should be optional (sites opt in), not mandatory (users get locked out)
  • Clear separation between "identifying an agent" and "controlling access to the web"

Summary of How These Map to This Proposal

Proposed Capability Existing Standard Status Pure Client-Side Feasible?
Agent self-reported identity MCP CIMD (DNS-based client metadata) Deployed in MCP spec since Nov 2025 ✅ Yes (cacheable, no server needed)
Cryptographic agent verification Privacy Pass (RFCs 9576, 9577, 9578) IETF standard, deployed by Apple and Cloudflare ✅ Yes (public key verification via Web Crypto)
Machine-to-machine auth OAuth 2.0 Client Credentials (RFC 6749) Universal industry standard ❌ No (requires token endpoint)
Public client auth without secrets PKCE (RFC 7636) Mandated by MCP spec, widely deployed ❌ No (requires authorization server)
Server-side token validation OAuth 2.0 Resource Server model (RFC 9728) Already defined for MCP servers ❌ No (requires backend)
Incremental permissions OAuth step-up authorization In MCP spec since Nov 2025 ❌ No (requires authorization server)
Declarative access policy No existing standard Needs to be defined ✅ Yes (browser-enforced)

None of this requires novel invention. It's integration of proven standards into a new API surface. But the table makes one thing clear: a lot of the existing standards assume you have a server. For pure client-side apps, the most viable building blocks are CIMD for identity, Privacy Pass for verification, and a new declarative policy mechanism for browser-level enforcement. That last one is where WebMCP may need to go beyond what existing standards provide.

Motivation

We've seen this before. RSS made content easy to syndicate, and aggregators captured the value while publishers bore the cost. The current spec, without any identity or authorization mechanisms, risks repeating that pattern at a much larger scale. The companies with the most incentive and capability to extract value from WebMCP tools — the big search engines and AI platforms — are the same ones building the browsers and the agent runtimes.

The impact falls hardest on smaller developers and pure client-side apps. A big SaaS company can build server-side verification and negotiate commercial terms with AI platforms. An indie developer shipping a static site can't. If the spec only supports auth patterns that require a backend, it creates a two-tier system where only well-resourced apps can protect themselves. Browser-level enforcement — declarative policies, trustworthy ModelContextClient properties, client-side-verifiable tokens — is what makes this protection accessible to the whole web, not just the companies that can afford an API team.

Adding identity and verification while the spec is still in early draft is way easier than retrofitting it later. I think this is foundational infrastructure, not an optional add-on, and I'd love to hear how others think we should approach it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions