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
Problem / motivation
For a server tool whose
_meta.ui.visibilityincludes both"model"and"app", the server can receivetools/callrequests 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/callrequest to its Host, which may proxy that request to the MCP server.Existing mechanisms answer related but different questions:
_meta.ui.visibilitycontrols 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.io.modelcontextprotocol/clientInfoidentifies the MCP client/Host; it does not distinguish whether that Host's model/agent or embedded App initiated the request.ui/initializeappInfoidentifies the View to the Host, but it is not propagated to the MCP server on eachtools/call._metamarker 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:
{ "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
_metaentry, for example:{ "_meta": { "io.modelcontextprotocol/ui": { "initiator": "app" } } }Normative behavior could be:
tools/call.initiator: "app"for model/agent-originated calls."model".The smallest interoperable shape may only need an App-origin boolean/enum. Optional
appInfoand/orresourceUricould be considered separately if their interoperability value outweighs privacy and cardinality concerns.Alternatives considered
clientInfo/appInfo:clientInfoidentifies the Host, whileappInfoidentifies the View only within the Apps initialization boundary. Neither currently expresses per-invocation origin to the server._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
appInfoorresourceUriare included, the specification should give explicit privacy, disclosure, and logging guidance.Open questions
_metaconventions?app,model,user,host, orunknown?appInfoand/orresourceUribe included, optional, or intentionally excluded?_meta.ui.visibilityenforcement without conflating the two?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
_metadocumentation