can1357/oh-my-pi · error

No MCP server has resource "${uri}". Available resources: $

Error message

No MCP server has resource "${uri}".

Available resources:
${formatAvailableResources(mcpManager)}

What it means

After extracting the wrapped resource URI from the mcp:// URL, the handler searches all connected servers' discovered resources (literal URIs, then URI templates, refreshed once via ensureServerResources). If no server advertises a matching resource or template, it throws with the requested URI and a formatted list of every resource actually available so the caller can self-correct.

Source

Thrown at packages/coding-agent/src/internal-urls/mcp-protocol.ts:133

 */
export class McpProtocolHandler implements ProtocolHandler {
	readonly scheme = "mcp";
	readonly immutable = true;

	async resolve(url: InternalUrl): Promise<InternalResource> {
		const mcpManager = MCPManager.instance();
		if (!mcpManager) {
			throw new Error("No MCP manager available. MCP servers may not be configured.");
		}

		const uri = extractResourceUri(url);
		let targetServer = resolveTargetServer(mcpManager, uri);
		if (!targetServer) {
			await Promise.allSettled(mcpManager.getConnectedServers().map(name => mcpManager.ensureServerResources(name)));
			targetServer = resolveTargetServer(mcpManager, uri);
		}
		if (!targetServer) {
			throw new Error(
				`No MCP server has resource "${uri}".\n\nAvailable resources:\n${formatAvailableResources(mcpManager)}`,
			);
		}

		let result: MCPResourceReadResult | undefined;
		try {
			result = await mcpManager.readServerResource(targetServer, uri);
		} catch (error) {
			const message = error instanceof Error ? error.message : String(error);
			throw new Error(`MCP resource read error: ${message}`);
		}

		if (!result) {
			throw new Error(`Server "${targetServer}" returned no content for "${uri}".`);
		}

		const textParts: string[] = [];
		for (const item of result.contents) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Copy a URI exactly from the 'Available resources' list embedded in the error message (match is exact string equality for literal URIs).
  2. Reconnect/refresh the MCP server so ensureServerResources picks up newly added resources, then retry.
  3. If the resource is server-generated, run the producing tool/flow first so it appears in the resource list.
  4. If it should be a dynamic resource, check the server's uriTemplate and build a URI matching that template.

Example fix

// before
read("mcp://notes/roapmap");            // typo — no such resource
// after (URI taken verbatim from the error's Available resources list)
read("mcp://notes/roadmap");
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await handler.resolve(parseInternalUrl(input));
} catch (e) {
  if (e instanceof Error && e.message.startsWith("No MCP server has resource")) {
    const available = e.message.split("Available resources:\n")[1] ?? "(none)";
    console.warn(`Unknown MCP resource; available:\n${available}`);
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Resolving an mcp:// URL whose inner URI does not exactly match any resource URI and does not match any server's URI template — a typo'd URI, a resource that was removed/renamed on the server, or a server that exposes the resource only after a tool call the client never made.

Common situations: Hard-coded mcp:// links from old session notes pointing at resources the server no longer lists; referencing a resource before the server finishes discovery; wrong server connected (URI exists on a server that isn't in config); template parameters filled incorrectly so no template matches.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/6b06742920da92c9. Report an issue: GitHub.