diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 71fe2fbbf..b90018a26 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -9,6 +9,7 @@ - Fixed the Advisor cost in the status line following the active session across conversation boundaries: a handoff no longer credits the replacement session with the conversation it replaced, a fork carries only the same conversation's finalized spend, and resuming or switching to an existing session restores that session's spend from its persisted Advisor transcripts instead of restarting `(adv)` at zero. Session transitions now also cancel in-flight Advisor maintenance, credential recovery, and retry backoff before swapping conversations, preventing stale Advisor work from blocking `/new`, switch, fork, branch, or handoff ([#6883](https://github.com/can1357/oh-my-pi/pull/6883) by [@paolomazzitti](https://github.com/paolomazzitti)). - Fixed legacy pi extensions importing `parseArgs` or `CONFIG_DIR_NAME` from the `@earendil-works/pi-coding-agent` package root failing Bun's static export check during validation, which blocked installs such as `omp install npm:pi-cursor-sdk` ([#6907](https://github.com/can1357/oh-my-pi/pull/6907) by [@Gy-Hu](https://github.com/Gy-Hu)). - Fixed ACP clients (e.g. Zed) not learning about a model change that happens from inside the agent loop — prewalk hand-offs, retry-fallback, model cycling — so the client's model picker/status bar kept showing the session's starting model even though the active model had actually switched. `AgentSession` now emits a `model_changed` event from its single model-mutation choke point, and the ACP surface's lifetime subscription re-pushes `config_option_update` on it. The same event now also keeps the TUI status line and collab guests' footer state in sync, and a failed session switch that rolls back to the previous model emits a corrective event so subscribers don't keep advertising the never-committed target. +- Fixed the assistant-facing available-resource summary omitting parameterized MCP resource templates, so a failed `mcp://` read now lists templates alongside concrete resources ([#6911](https://github.com/can1357/oh-my-pi/issues/6911)). ## [17.1.8] - 2026-07-28 diff --git a/packages/coding-agent/src/internal-urls/mcp-protocol.ts b/packages/coding-agent/src/internal-urls/mcp-protocol.ts index 2dbc72f13..82a38f391 100644 --- a/packages/coding-agent/src/internal-urls/mcp-protocol.ts +++ b/packages/coding-agent/src/internal-urls/mcp-protocol.ts @@ -97,7 +97,10 @@ function formatAvailableResources(mcpManager: MCPManager): string { .getConnectedServers() .flatMap(name => { const serverResources = mcpManager.getServerResources(name); - return (serverResources?.resources ?? []).map(r => ` ${r.uri} (${name})`); + if (!serverResources) return []; + const concrete = serverResources.resources.map(r => ` ${r.uri} (${name})`); + const templates = serverResources.templates.map(t => ` ${t.uriTemplate} (${name}, template)`); + return [...concrete, ...templates]; }) .join("\n"); return available || " (none)"; diff --git a/packages/coding-agent/test/internal-urls/mcp-protocol.test.ts b/packages/coding-agent/test/internal-urls/mcp-protocol.test.ts index 96c3b43ca..4ad4e2856 100644 --- a/packages/coding-agent/test/internal-urls/mcp-protocol.test.ts +++ b/packages/coding-agent/test/internal-urls/mcp-protocol.test.ts @@ -73,6 +73,20 @@ describe("McpProtocolHandler", () => { await expect(router.resolve("mcp://test://missing")).rejects.toThrow("server-a"); }); + it("lists resource templates alongside concrete resources when no server matches", async () => { + const resources = new Map(); + resources.set("server-a", { + resources: [{ uri: "example://items/open", name: "open-item" }], + templates: [{ uriTemplate: "example://items/{id}", name: "item-template" }], + }); + const manager = createMockManager({ servers: ["server-a"], resources }); + MCPManager.setInstance(manager); + const router = InternalUrlRouter.instance(); + + await expect(router.resolve("mcp://example://missing")).rejects.toThrow("example://items/open"); + await expect(router.resolve("mcp://example://missing")).rejects.toThrow("example://items/{id}"); + }); + it("reads resource by exact URI match", async () => { const resources = new Map(); resources.set("my-server", {