Skip to content

Support MCP-UI / MCP Apps #19

@thekid

Description

@thekid

When accessing ui://{name}, the server should return the following from resource/read:

{
  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?: {};           // Request camera access
          microphone?: {};       // Request microphone access
          geolocation?: {};      // Request geolocation access
          clipboardWrite?: {};   // Request clipboard write access
        };
        domain?: string;
        prefersBorder?: boolean;
      };
    };
  }];
}

Tools are associated with UI resources through the _meta.ui field, which contains a reference to the resource URI.

Implementation idea

First low-level idea which we might build upon with an App annotation:

use io\modelcontextprotocol\server\{Implementation, Resource, Meta, Tool};

#[Implementation]
class Greeting {

  /** Greeting app */
  #[Resource('ui://greeting/app', 'text/html;profile=mcp-app')]
  public function app() {
    return [
      '_meta' => ['ui' => ['csp' => ['resourceDomains' => ['http://localhost:8080']]]],
      'text'  => <<<'HTML'
        <html>
        <head>
          <title>Greeting card</title>
        </head>
        <body>
          <h1>Hello!</h1>
          <p>This is the first XP MCP app</p>
        </body>
        </html>
       HTML
    ];
  }

  /** Greeting card */
  #[Tool(meta: ['ui' => ['resourceUri' => 'ui://greeting/app']])]
  public function card() {
    return 'App launching...';
  }
}

Testing

See also

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions