⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

SEP: Duplicate placement of McpUiResourceMeta in the resource metadata and the resource read value leads to confusion. #269

@matteo8p

Description

@matteo8p

Issue

Currently the spec requires you to place the CSP, permissions, etc information in two separate places:

  1. The resource metadata _meta.ui?.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions