{"record":{"id":"1585d23570a8d032","repo":"vercel/ai","slug":"invalid-mcp-app-resource-uri-json-stringify-res","errorCode":null,"errorMessage":"Invalid MCP App resource URI: ${JSON.stringify(resourceUri)}","messagePattern":"Invalid MCP App resource URI: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/tool/mcp-apps.ts","lineNumber":150,"sourceCode":"        (v): v is MCPAppToolVisibility => v === 'model' || v === 'app',\n      )\n    : undefined;\n}\n\n/**\n * Reads and validates MCP Apps metadata from a tool definition.\n */\nexport function getMCPAppToolMeta(\n  tool: MCPAppToolLike,\n): MCPAppToolMeta | undefined {\n  const uiMeta = getToolUiMeta(tool._meta);\n  const resourceUri =\n    uiMeta?.resourceUri ?? tool._meta?.[MCP_APP_LEGACY_RESOURCE_URI_META_KEY];\n  const visibility = parseVisibility(uiMeta?.visibility);\n\n  if (resourceUri !== undefined) {\n    if (typeof resourceUri !== 'string' || !resourceUri.startsWith('ui://')) {\n      throw new Error(\n        `Invalid MCP App resource URI: ${JSON.stringify(resourceUri)}`,\n      );\n    }\n  } else if (uiMeta == null) {\n    return undefined;\n  }\n\n  return {\n    ...uiMeta,\n    ...(resourceUri != null ? { resourceUri } : {}),\n    ...(visibility != null ? { visibility } : {}),\n  };\n}\n\n/**\n * Returns the `ui://` app resource URI attached to a tool, if present.\n */\nexport function getMCPAppResourceUri(tool: MCPAppToolLike): string | undefined {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/mcp/src/tool/mcp-apps.ts#L132-L168","documentation":"Thrown by getMCPAppToolMeta when an MCP App tool declares a resourceUri (via ui metadata or the legacy _meta key) that is not a string or does not start with the required 'ui://' scheme. MCP Apps must point their UI resource at a ui:// URI, so the SDK validates the shape eagerly when reading tool metadata.","triggerScenarios":"Registering/reading an MCP tool whose ui.resourceUri (or legacy _meta uiResourceUri) is a non-string value, an http(s):// URL, or a malformed URI without the ui:// prefix; servers built against older or hand-rolled MCP App conventions.","commonSituations":"MCP servers migrated from pre-standard drafts that used different resource URI schemes; hand-written tool manifests with copy-pasted https:// links to HTML files; JSON configs where resourceUri is accidentally an object (hence JSON.stringify in the message).","solutions":["Change the tool's ui.resourceUri to a string beginning with 'ui://'.","Serve the app HTML via the MCP server's resources/read (registered under the matching ui:// URI) rather than a plain HTTP URL.","Remove resourceUri entirely if the tool has no MCP App UI, so metadata is treated as undefined.","Update the MCP server to the current MCP Apps spec naming (ui metadata) and re-verify the emitted _meta."],"exampleFix":"// before\n{ _meta: { ui: { resourceUri: 'https://example.com/app.html' } } }\n// after\n{ _meta: { ui: { resourceUri: 'ui://my-server/app.html' } } }","handlingStrategy":"validation","validationCode":"function isValidAppResourceUri(uri) {\n  return typeof uri === 'string' && uri.startsWith('ui://');\n}\nconst uiMeta = tool._meta?.ui;\nconst resourceUri = uiMeta?.resourceUri;\nif (resourceUri !== undefined && !isValidAppResourceUri(resourceUri)) {\n  throw new Error(`Fix tool manifest: resourceUri must be a 'ui://' string, got ${JSON.stringify(resourceUri)}`);\n}","typeGuard":"function isValidAppResourceUri(uri: unknown): uri is string {\n  return typeof uri === 'string' && uri.startsWith('ui://');\n}","tryCatchPattern":"let meta;\ntry {\n  meta = getMCPAppToolMeta(tool);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Invalid MCP App resource URI')) {\n    console.error('Tool manifest violates MCP Apps spec:', e.message);\n    meta = undefined; // treat as non-app tool or surface a config error\n  } else { throw e; }\n}","preventionTips":["Always use 'ui://'-scheme resource URIs in MCP App tool metadata.","Serve app HTML through MCP resources/read, not plain https:// links.","Validate tool manifests with a schema check when building MCP servers.","Migrate legacy _meta keys to the current ui metadata naming."],"tags":["mcp","validation","uri","mcp-apps"],"backgroundTag":"invalid-resource-uri","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}