modelcontextprotocol / modelcontextprotocol/ext-apps
SEP: Duplicate placement of `McpUiResourceMeta` in the resource metadata and the resource read value leads to confusion.
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 387
- Avg merge
- 3h 21m
- Merged PRs (30d)
- 6
Description
Issue
Currently the spec requires you to place the CSP, permissions, etc information in two separate places:
- The resource metadata
_meta.ui?. - The contents of the resource.
Example: I have to add the _meta.ui info here:
registerAppResource(server,
resourceUri,
resourceUri,
{
mimeType: RESOURCE_MIME_TYPE,
_meta: {
ui: {
csp: {
connectDomains: ["https://xxx"],
resourceDomains: [
"https://xxx",
"https://fonts.googleapis.com",
"https://fonts.gstatic.com",
],
},
},
},
},
async (): Promise<ReadResourceResult> => {
const html = await fs.readFile(path.join(DIST_DIR, "cocktail-recipe-widget.html"), "utf-8");
return {
contents: [{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html }],
};
},
);
and here:
// resources/read response for UI resource
{
contents: [{
uri: string; // Matching UI resource URI
mimeType: "text/html;profile=mcp-app"; // MUST be "text/html;profile=mcp-app"
text?: string; // HTML content as string
blob?: string; // OR base64-encoded HTML
_meta?: {
ui?: {
csp?: {
connectDomains?: string[]; // Origins for network requests (fetch/XHR/WebSocket).
resourceDomains?: string[]; // Origins for static resources (scripts, images, styles, fonts).
frameDomains?: string[]; // Origins for nested iframes (frame-src directive).
baseUriDomains?: string[]; // Allowed base URIs for the document (base-uri directive).
};
permissions?: {
camera?: boolean; // Request camera access
microphone?: boolean; // Request microphone access
geolocation?: boolean; // Request geolocation access
clipboardWrite?: boolean; // Request clipboard write access
};
domain?: string;
prefersBorder?: boolean;
};
};
}];
}
Why it's a problem
There is redundancy in having to add the same exact information in two separate places. As a client implementor, I don't know which one to check. Do I check the resource meta? Do I check the resource result? I don't know.
As a server implementor, it was difficult for me to realize that I had to add it in two separate places. I was confused why my CSP wasn't getting used even though I put it in the resource meta, only to realize the client I'm using is checking it in the resource content.
Solution
Ideally, we have a single source of truth for where to put the meta. I think we should standardize it to be read in the resource read content. That's where most clients today have it implemented.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing the resource metadata _meta.ui with the _meta.ui object in the resources/read response, including the McpUiResourceMeta placement described in the issue. Trace which location clients and servers currently use, then define and document one authoritative location and update the protocol examples so the two sides agree.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100