Skip to content

@mcp-ui/server createUIResource() does not output annotations in an MCP spec-compliant way #98

@aharvard

Description

@aharvard

Issue

createUIResource() does not output annotations at the right level in the embedded resource object according to the MCP specification.

import { createUIResource } from "@mcp-ui/server";

createUIResource({
  uri: "ui://instance-1",
  content: {
    type: "externalUrl",
    iframeUrl: "http://localhost:3000/",
  },
  encoding: "text",
  resourceProps: {
    annotations: {
      audience: ["user"],
    },
  },
})

// The above code currently yields the following JSON:
// {
//   "type": "resource",
//   "resource": {
//     "uri": "ui://instance-1",
//     "mimeType": "text/uri-list",
//     "text": "http://localhost:3000/",
//     "annotations": {
//       "audience": ["user"]
//     },
//   }
// }

Why is this important?

Setting the audience to user should direct clients not to pass the resource along to the LLM. This helps create a cleaner chat experience, where the model won't summarize the URL or rawHTML. In the case of rawHTML, it serves as an additional layer of security by preventing prompt injection.

Expected

If an embedded resource has the annotations property, it should be set at the same level as the resource and type properties, according to https://modelcontextprotocol.io/specification/2025-06-18/schema#embeddedresource

interface EmbeddedResource {
  _meta?: { [key: string]: unknown };
  annotations?: Annotations;
  resource: TextResourceContents | BlobResourceContents;
  type: “resource”;
}
{
  "type": "resource",
  "resource": {
    "uri": "ui://instance-1",
    "mimeType": "text/uri-list",
    "text": "http://localhost:3000/",
  },
  "annotations": {
    "audience": ["user"]
  }
}

Note

_meta is allowed to exist at any level in resource objects. Currently, createUIResource() adds _meta as a child property of the resource object. I think this is fine, but I'd be in favor of consistency if we want to lift _meta up to be alongside annotations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions