can1357/oh-my-pi · error
mcp:// URL requires a resource URI: mcp://<resource-uri>
Error message
mcp:// URL requires a resource URI: mcp://<resource-uri>
What it means
The mcp:// scheme wraps an MCP resource URI in the URL authority/path (mcp://<resource-uri>). extractResourceUri reconstructs the wrapped URI from host+pathname+search+hash; if every part is empty — i.e. the caller passed the bare URL 'mcp://' — there is no resource URI to look up, so it throws with the expected usage form.
Source
Thrown at packages/coding-agent/src/internal-urls/mcp-protocol.ts:38
return { literalChars, expressionCount };
}
function extractResourceUri(url: InternalUrl): string {
const scheme = url.protocol.replace(/:$/, "").toLowerCase();
if (scheme !== "mcp") {
// Server-advertised native URI (hierarchical or opaque). Preserve the
// input byte-for-byte: `resolveTargetServer` matches by exact string
// equality, so e.g. `catalog://root/` must keep its trailing slash.
return url.rawHref ?? url.href;
}
// Legacy `mcp://<resource-uri>` wrapper: reconstruct the wrapped URI and
// elide a bare trailing `/` that URL parsing adds to host-only forms.
const host = url.rawHost || url.hostname;
const rawPathname = url.rawPathname ?? url.pathname;
const hasPath = rawPathname && rawPathname !== "/";
const uri = `${host}${hasPath ? rawPathname : ""}${url.search}${url.hash}`.trim();
if (!uri) {
throw new Error("mcp:// URL requires a resource URI: mcp://<resource-uri>");
}
return uri;
}
function resolveTargetServer(mcpManager: MCPManager, uri: string): string | undefined {
const servers = mcpManager.getConnectedServers();
for (const name of servers) {
const serverResources = mcpManager.getServerResources(name);
if (serverResources?.resources.some(r => r.uri === uri)) {
return name;
}
}
let bestTemplateMatch:
| {
serverName: string;
literalChars: number;
expressionCount: number;View on GitHub (pinned to 9690622007)
Solutions
- Include the wrapped resource URI in the URL, e.g. mcp://catalog://root or mcp://server/path/resource, matching a URI advertised by a connected MCP server.
- Look up the exact resource URI via MCPManager.getServerResources(name) and embed it verbatim in the mcp:// URL.
- Fix the code that emptied the URL before resolution — keep the full original href.
Example fix
// before
resolve("mcp://");
// after
resolve("mcp://catalog://root/data"); Defensive patterns
Strategy: validation
Validate before calling
const rest = url.slice('mcp://'.length);
if (!rest || rest === '/') throw new Error('mcp:// URL must embed a resource URI: mcp://<resource-uri>'); Try / catch
try { resource = await handler.resolve(url, ctx); } catch (e) { if (String(e.message).includes('requires a resource URI')) { /* prompt for / look up a valid resource URI */ } else throw e; } Prevention
- Copy resource URIs verbatim from MCPManager.getServerResources(name) listings.
- Never build mcp:// URLs from templates without verifying the URI placeholder was filled.
- Preserve the full href — don't trim content after the scheme.
When it happens
Trigger: Resolving the literal URL 'mcp://' via the internal-URL router's mcp handler; stripping the wrapped URI during URL parsing so hostname and pathname are both empty; template/placeholder not filled in before resolution.
Common situations: Copy-pasted links where the resource part was lost; code that trims everything after the scheme; agents emitting the scheme without a URI when the MCP resource list was empty.
Related errors
- Provider delete URL must not embed an account credential
- ${destination} returned an invalid upload URL
- Destination option endpoint must be an absolute URL
- Destination option endpoint must use HTTP or HTTPS
- Destination option ${optionName} must be an absolute HTTP UR
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/25a4aca87375eea2.
Report an issue: GitHub.