modelcontextprotocol / modelcontextprotocol/ext-apps

Standardize provenance for app-initiated server tool calls

Open
#738 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.9k
Forks
387
Avg merge
3h 21m
Merged PRs (30d)
6

Description

Problem / motivation

For a server tool whose _meta.ui.visibility includes both "model" and "app", the server can receive tools/call requests initiated by either the model/agent or an embedded MCP App. Today those requests are indistinguishable at the server boundary.

A standardized, per-invocation provenance signal would help with observability, UX analytics, debugging, rate limiting, and policy decisions. It should be treated as provenance asserted by the MCP client/host, not as an authentication or authorization primitive.

Current spec behavior

The stable MCP Apps specification allows a View to send the core tools/call request to its Host, which may proxy that request to the MCP server.

Existing mechanisms answer related but different questions:

  • _meta.ui.visibility controls whether a tool may be called by the model and/or App; it does not identify who initiated a particular call to a dual-visible tool.
  • MCP 2026-07-28 per-request io.modelcontextprotocol/clientInfo identifies the MCP client/Host; it does not distinguish whether that Host's model/agent or embedded App initiated the request.
  • Apps ui/initialize appInfo identifies the View to the Host, but it is not propagated to the MCP server on each tools/call.
  • A custom App-supplied _meta marker is non-interoperable, may be dropped by Hosts or gateways, can collide with other conventions, and should not be considered authoritative.

As a result, proxying preserves the call parameters but carries no normative per-call origin signal.

Concrete example

Both paths collapse to the same server request:

Agent -> Host -> Server
App   -> Host -> Server
{
  "method": "tools/call",
  "params": {
    "name": "refresh_dashboard",
    "arguments": { "accountId": "123" }
  }
}

The server cannot tell whether the Host emitted this request because the agent selected the tool or because a user clicked a control in the embedded App.

Proposal: host-attested metadata

Define an official Apps-owned request _meta entry, for example:

{
  "_meta": {
    "io.modelcontextprotocol/ui": {
      "initiator": "app"
    }
  }
}

Normative behavior could be:

  • The Host MUST add or overwrite this value when proxying a View-originated tools/call.
  • The Host MUST NOT set initiator: "app" for model/agent-originated calls.
  • Downstream proxies and gateways SHOULD preserve the standardized entry.
  • Absence means unknown, not implicitly "model".
  • The View should not be responsible for self-declaring this marker.

The smallest interoperable shape may only need an App-origin boolean/enum. Optional appInfo and/or resourceUri could be considered separately if their interoperability value outweighs privacy and cardinality concerns.

Alternatives considered

  • clientInfo / appInfo: clientInfo identifies the Host, while appInfo identifies the View only within the Apps initialization boundary. Neither currently expresses per-invocation origin to the server.
  • Separate connections: A Host could use a distinct MCP connection for App traffic, but that complicates session/state sharing and still lacks a portable semantic signal across gateways.
  • OpenTelemetry baggage: Useful inside a deployment, but it is not an interoperable MCP protocol contract and may not survive all transports or proxies.
  • Custom vendor _meta: Feasible for closed ecosystems, but merely relocates the custom semantics. Hosts may drop it, namespaces may diverge, and App-authored values are not authoritative.

Security and trust considerations

“Host-attested” means asserted by the MCP client/Host; it is not cryptographically verified. A server must not use this field for authorization unless it separately trusts and authenticates the Host making the assertion.

Hosts should overwrite any spoofed App-provided value when proxying the request. Provenance should remain low-cardinality. If identity-bearing fields such as appInfo or resourceUri are included, the specification should give explicit privacy, disclosure, and logging guidance.

Open questions

  • What namespace and shape best fit current Apps and core _meta conventions?
  • Is an App-only boolean sufficient, or should the field be a broader enum such as app, model, user, host, or unknown?
  • Should appInfo and/or resourceUri be included, optional, or intentionally excluded?
  • What preservation requirements should apply through gateways and nested proxies?
  • How should provenance relate to _meta.ui.visibility enforcement without conflating the two?
  • Should the design align only with modern per-request metadata conventions, or also define legacy compatibility behavior?

The goal is to standardize the smallest interoperable shape; the options above are intended to invite maintainers to choose the least disruptive protocol contract.

Related specifications and issues

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the stable MCP Apps specification and the current MCP request _meta documentation linked in the issue, then compare the model- and View-originated tools/call paths described here. Done means maintainers agree on the smallest provenance shape, namespace, trust semantics, and preservation requirements, with the specification updated accordingly.

Written by the indexing model from the issue text.

Assessment

Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.