vercel/ai · error · Error

Unsupported MCP App resource URI: ${uri}

Error message

Unsupported MCP App resource URI: ${uri}

What it means

Thrown by readMCPAppResource when the given URI does not start with the 'ui://' scheme. Only ui:// URIs are treated as MCP App resources; anything else is rejected before a resources/read request is made.

Source

Thrown at packages/mcp/src/tool/mcp-apps.ts:278

  const meta = getResourceUiMeta(content._meta);

  return { uri, mimeType: MCP_APP_MIME_TYPE, html, meta };
}

/**
 * Reads a `ui://` resource from an MCP server and normalizes it for rendering.
 */
export async function readMCPAppResource({
  client,
  uri,
  options,
}: {
  client: Pick<MCPClient, 'readResource'>;
  uri: string;
  options?: RequestOptions;
}): Promise<MCPAppResource> {
  if (!uri.startsWith('ui://')) {
    throw new Error(`Unsupported MCP App resource URI: ${uri}`);
  }

  return getMCPAppResourceFromReadResult({
    uri,
    resource: await client.readResource({ uri, options }),
  });
}

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Only pass URIs extracted via getMCPAppResourceUris or from tool _meta ui resourceUri fields, which are ui:// by spec.
  2. Check the URI string for typos in the scheme (must be exactly 'ui://').
  3. If you need a non-app resource, use client.readResource directly instead of readMCPAppResource.

Example fix

// before
await readMCPAppResource({ client, uri: 'https://example.com/widget.html' });
// after
await readMCPAppResource({ client, uri: 'ui://widget/gauge.html' });
Defensive patterns

Strategy: validation

Validate before calling

if (!uri.startsWith('ui://')) {
  throw new Error(`Expected ui:// MCP App resource URI, got: ${uri}`);
}

Type guard

function isMCPAppUri(uri: string): boolean {
  return uri.startsWith('ui://');
}

Try / catch

try {
  const app = await readMCPAppResource({ client, uri });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unsupported MCP App resource URI')) {
    // fall back to client.readResource for non-app resources
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a file://, https://, or other non-ui:// URI (e.g. a tool output resource URI or a typo like 'ui:/') to readMCPAppResource or resource().

Common situations: Developer accidentally reads a regular MCP resource as an app; a tool annotation returns an ordinary resource URI; typo in the scheme; mixing up MCP Apps resources with standard MCP resources.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/d1b101be0e058e14. Report an issue: GitHub.