diff --git a/package-lock.json b/package-lock.json index 2b0bcb12..85addf15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@waishnav/devspace", - "version": "1.0.19", + "version": "1.0.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@waishnav/devspace", - "version": "1.0.19", + "version": "1.0.20", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -15,7 +15,7 @@ "@anthropic-ai/sandbox-runtime": "0.0.71", "@clack/prompts": "^1.5.1", "@earendil-works/pi-coding-agent": "^0.80.3", - "@modelcontextprotocol/ext-apps": "^1.7.2", + "@modelcontextprotocol/ext-apps": "^1.7.5", "@modelcontextprotocol/sdk": "^1.29.0", "@opencode-ai/sdk": "^1.17.13", "@pierre/diffs": "^1.2.5", @@ -2586,9 +2586,9 @@ } }, "node_modules/@modelcontextprotocol/ext-apps": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/ext-apps/-/ext-apps-1.7.2.tgz", - "integrity": "sha512-OOWKDxdAjYDcgHkmzVzccyyag3FK+jBWPaWu4WvTxFsU4R/cgOX4eep66zPRA5n4v6WfxUNibPyvX4iJ7egYTg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/ext-apps/-/ext-apps-1.7.5.tgz", + "integrity": "sha512-TjPH2S2y5UEGKhmI6+XGFuqfqOV4ppe1x6DA3txnUaEWkgtA4G5vo14jGKFZmegdkZ1H4QMLyujLvoU1BEdnAg==", "license": "MIT", "workspaces": [ "examples/*" diff --git a/package.json b/package.json index fcf401cd..7b0e3ef5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@waishnav/devspace", - "version": "1.0.19", + "version": "1.0.20", "description": "Expose a secure local coding workspace through an MCP server.", "type": "module", "main": "dist/server.js", @@ -41,7 +41,7 @@ "@anthropic-ai/sandbox-runtime": "0.0.71", "@clack/prompts": "^1.5.1", "@earendil-works/pi-coding-agent": "^0.80.3", - "@modelcontextprotocol/ext-apps": "^1.7.2", + "@modelcontextprotocol/ext-apps": "^1.7.5", "@modelcontextprotocol/sdk": "^1.29.0", "@opencode-ai/sdk": "^1.17.13", "@pierre/diffs": "^1.2.5", diff --git a/src/server.test.ts b/src/server.test.ts index cf039537..32a48e38 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -22,7 +22,7 @@ test("workspace app resource declares its dedicated public origin", async (t) => const context = await fixture(t); const listed = await context.client.listResources(); const resource = listed.resources.find((entry) => - entry.uri === "ui://devspace/workspace-app/v1.html" + entry.uri === "ui://devspace/workspace-app/v2.html" ); assert.ok(resource); @@ -39,17 +39,17 @@ test("workspace app resource declares its dedicated public origin", async (t) => assert.deepEqual(ui?.csp?.connectDomains, [origin]); }); -test("widget tools expose the ChatGPT outputTemplate compatibility alias", async (t) => { +test("widget tools use the MCP Apps resource URI without the legacy ChatGPT alias", async (t) => { const context = await fixture(t); const listed = await context.client.listTools(); const openWorkspace = listed.tools.find((tool) => tool.name === "open_workspace"); assert.ok(openWorkspace); const meta = openWorkspace._meta as Record | undefined; - assert.equal(meta?.["openai/outputTemplate"], "ui://devspace/workspace-app/v1.html"); - assert.equal(meta?.["ui/resourceUri"], "ui://devspace/workspace-app/v1.html"); + assert.equal(meta?.["openai/outputTemplate"], undefined); + assert.equal(meta?.["ui/resourceUri"], "ui://devspace/workspace-app/v2.html"); assert.deepEqual(meta?.ui, { - resourceUri: "ui://devspace/workspace-app/v1.html", + resourceUri: "ui://devspace/workspace-app/v2.html", visibility: ["model"], }); }); diff --git a/src/server.ts b/src/server.ts index 0b9084dc..9ad2db93 100644 --- a/src/server.ts +++ b/src/server.ts @@ -64,7 +64,7 @@ import { } from "./local-agent-availability.js"; const PROCESS_HANDOFF_MS = 2_000; -const WORKSPACE_APP_URI = "ui://devspace/workspace-app/v1.html"; +const WORKSPACE_APP_URI = "ui://devspace/workspace-app/v2.html"; const WORKSPACE_APP_MANIFEST_ENTRY = "workspace-app.html"; const WRITE_TOOL_ANNOTATIONS = { readOnlyHint: false, @@ -134,7 +134,6 @@ interface ToolDefinitionMeta extends Record { resourceUri: string; visibility: ["model"]; }; - "openai/outputTemplate": string; } type EmptyToolDefinitionMeta = Record & { @@ -168,7 +167,6 @@ function toolWidgetDescriptorMeta( resourceUri: WORKSPACE_APP_URI, visibility: ["model"], }, - "openai/outputTemplate": WORKSPACE_APP_URI, }, }; } diff --git a/src/stateless-mcp-http.test.ts b/src/stateless-mcp-http.test.ts index 35cbe5c1..727b2727 100644 --- a/src/stateless-mcp-http.test.ts +++ b/src/stateless-mcp-http.test.ts @@ -12,7 +12,7 @@ import { SqliteOAuthStore } from "./oauth-store.js"; import { createServer } from "./server.js"; const PROTOCOL_VERSION = "2025-06-18"; -const WORKSPACE_APP_URI = "ui://devspace/workspace-app/v1.html"; +const WORKSPACE_APP_URI = "ui://devspace/workspace-app/v2.html"; test("stateless MCP keeps resources readable after more than 32 fresh client initializations", async (t) => { const root = await mkdtemp(join(tmpdir(), "devspace-stateless-http-test-")); @@ -107,7 +107,7 @@ test("stateless MCP keeps resources readable after more than 32 fresh client ini assert.equal(resource.status, 200); assert.equal(resource.headers.get("mcp-session-id"), null); const body = await resource.text(); - assert.match(body, /ui:\/\/devspace\/workspace-app\/v1\.html/); + assert.match(body, /ui:\/\/devspace\/workspace-app\/v2\.html/); assert.match(body, /text\/html/); } }); diff --git a/src/ui/workspace-app.tsx b/src/ui/workspace-app.tsx index 063e05b1..b4e7798a 100644 --- a/src/ui/workspace-app.tsx +++ b/src/ui/workspace-app.tsx @@ -82,7 +82,7 @@ if (!maybeAppRoot) { const appRoot = maybeAppRoot; const CARD_PROBE_PREFIX = "[DevSpace card-probe]"; -const CARD_PROBE_BUILD = "card-race-v4"; +const CARD_PROBE_BUILD = "card-race-v5"; void boot(); @@ -91,7 +91,7 @@ async function boot(): Promise { render(); app = new App( - { name: "devspace-tool-cards", version: "0.5.0-card-store-probe" }, + { name: "devspace-tool-cards", version: "0.6.0-mcp-apps-only" }, {}, );