· 6 min read ·

The Missing Permission Layer in Claude Code's MCP Plugin System

Source: hackernews

Browser extensions spent years earning their reputation before the ecosystem developed meaningful norms. Chrome’s permission dialogs, Manifest V3 restrictions, and the Web Store review process all came out of hard-won lessons: when you give third-party code access to your browser session, the scope of that access matters, and users need a clear way to understand it. A finding about the Vercel plugin for Claude Code, documented recently and rising quickly on Hacker News with 267 points and over a hundred comments, suggests the emerging MCP plugin ecosystem is about to learn the same lesson.

The finding: the Vercel plugin for Claude Code includes telemetry that reads user prompts. Not just metadata about deployment commands or project names, but actual prompt content from coding sessions, sent back to Vercel’s servers.

How Claude Code Plugins Work

Claude Code’s plugin system is built on the Model Context Protocol, an open standard Anthropic published in late 2024 for connecting language models to external tools and data sources. An MCP server is a process that speaks a defined JSON-RPC protocol, exposing tools, resources, and prompt templates that Claude can invoke during a session.

When you add a plugin to Claude Code, via claude mcp add or by editing your configuration directly, you are telling the client to spawn or connect to an MCP server process. From that point on, the MCP server participates in your sessions. When Claude decides to invoke one of the plugin’s tools, it sends a tools/call request containing the tool name, arguments, and, depending on implementation, contextual information from the active conversation.

That contextual information is where the problem lives. MCP servers are not sandboxed from the session in the way browser extensions are sandboxed from other tabs. When Claude calls a Vercel tool to check deployment status, the request that reaches the Vercel MCP server can carry ambient conversation context: what the user was working on, what they asked, what the model is trying to accomplish.

The MCP specification, as currently written, defines what tools and resources servers can expose, not what data flows to those servers when tools are invoked. For an open protocol at this stage of development, that prioritization is understandable. For commercial plugins with telemetry ambitions, it creates an obvious gap.

Two Ways a Plugin Can See Your Prompts

Precision matters when describing the technical threat model, because prompt visibility covers meaningfully different scenarios.

The first is passive context collection. When Claude sends a tools/call to a plugin, the JSON payload can include conversation context the model assembled as part of reasoning about what tool to use and how. The server receives this as part of the invocation and can log or forward it, no additional instrumentation required. A minimal example of what that invocation might look like:

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "vercel_deploy",
    "arguments": {
      "project": "my-app",
      "environment": "production"
    },
    "_meta": {
      "progressToken": 1
    }
  }
}

The arguments themselves are scoped. But the server process receives the full TCP stream from the Claude Code client, and depending on how the client constructs its requests, additional context can accompany tool calls.

The second mechanism is active extraction. An MCP server could define a tool whose purpose, from Claude’s perspective, is to retrieve useful information, but whose implementation logs whatever the model sends when calling it. The model, reasoning from the tool’s description, supplies context. The server logs it.

In both cases, no permission prompt appears at install time, no runtime notification fires when prompt data leaves the local process, and no audit trail captures what each plugin server transmitted. The server process runs with the same operating system permissions as Claude Code itself. Its outbound network requests are completely unmonitored by the client. Installing an MCP plugin and trusting it with your session is closer, from a security standpoint, to running an arbitrary binary under your user account than to installing a browser extension.

The Disclosure Problem

Vercel almost certainly added this telemetry for reasons familiar from any analytics discussion: understanding how developers use the product, improving suggestions, debugging issues. These are standard justifications and not inherently unreasonable ones.

Users who installed the Vercel plugin, however, had no way to know prompt content was being transmitted. If the plugin’s documentation said “this plugin sends conversation context to Vercel for product analytics,” users could make an informed choice. Some would accept that tradeoff, some would opt out, and the variation in response would itself be useful signal about how sensitive developers consider this data. Disclosure changes the dynamic from extraction to informed consent.

The fact that this was discovered through traffic inspection rather than documentation follows a pattern that has damaged trust repeatedly in adjacent ecosystems. It is the same mechanism behind the 2018 wave of browser extension scandals, the recurring mobile analytics SDK controversies, and the data broker disclosures that periodically surface about seemingly innocuous apps. The telemetry itself is rarely the core issue. The absence of disclosure is.

What the Browser Extension Ecosystem Learned

The browser extension ecosystem converged, slowly and imperfectly, on a manifest-based permission declaration. Chrome extensions must declare host permissions, API access, and data usage in their manifest.json. Since Chrome 88, the Chrome Web Store has enforced that extensions with access to user data must post privacy policies and comply with data use disclosures. Firefox’s extension review process includes a manual review pass for extensions requesting broad permissions.

None of these mechanisms are perfect. Malicious extensions still appear in the Web Store. But the direction of travel has been consistent: more transparency at install time, more granular permission declarations, more review scrutiny for sensitive access. The permission model exists not to prevent all abuse but to make abuse detectable and to ensure users understand what they consented to.

The MCP ecosystem has none of this yet. The initialize handshake between a Claude Code client and an MCP server includes a capabilities exchange, but capabilities describe what protocol features the server supports (resource subscriptions, prompt templates, logging), not what user data the server collects or transmits. There is no equivalent of the manifest permission array, no standardized privacy disclosure field, and no official channel through which a plugin’s data practices are reviewed.

What a Better Model Requires

The MCP specification could adopt a privacy manifest section in the server’s initialize response. Something like:

{
  "protocolVersion": "2024-11-05",
  "capabilities": { ... },
  "serverInfo": {
    "name": "vercel",
    "version": "1.0.0"
  },
  "privacy": {
    "dataCollected": ["tool_invocations", "conversation_context"],
    "dataSharedWith": ["vercel.com"],
    "privacyPolicyUrl": "https://vercel.com/legal/privacy"
  }
}

This would not prevent a server from lying. But it would give Claude Code clients the raw material to surface a disclosure to users at install or first-use time. It would make discrepancies between declared and observed behavior auditable. It would establish a norm that server authors are expected to document their data practices, and create a baseline against which the community can hold them accountable.

Anthropy has the leverage to make this stick. Claude Code is the dominant MCP client today. Requiring a privacy manifest for plugins distributed through any official channel, or displayed via claude mcp add, would establish the expectation across the ecosystem. The community and vendors would follow because the client enforces it.

Separately, Claude Code itself could surface active MCP connections during a session alongside a simplified log of outbound requests those servers make. Browser DevTools has had a Network panel for two decades. Applying that principle to MCP server traffic is primarily a product decision, not an engineering challenge.

The Ecosystem Implication

Vercel is not uniquely culpable here. They are the first prominent case to get documented and shared widely. Every SaaS platform, every developer tooling vendor, and every analytics company building a Claude Code plugin faces the same telemetry temptation. The incentive structure that produced this outcome will produce more instances of it as the ecosystem grows.

The MCP server registry already lists dozens of servers across databases, development tools, cloud platforms, and productivity apps. Many of those are backed by commercial entities with their own analytics interests. Without a disclosure standard, users installing any of them are extending implicit trust with no documented scope.

The patterns established now will shape what the MCP ecosystem looks like at maturity. The browser extension ecosystem took roughly a decade of incidents, regulatory pressure, and community backlash to develop norms that most people find acceptable. The MCP ecosystem does not need to take the same path. The prior art exists. The question is whether the community builds the infrastructure proactively or waits for the incidents to accumulate into a bigger problem.

Vercel’s implementation was caught because someone installed it, watched the traffic, and wrote up what they found. The more durable fix is to build disclosure into the stack from the start, so that kind of manual investigation confirms what users already know rather than surfacing what they were never told.

Was this interesting?