@absolutejs/mcp 0.17.5 → 0.17.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.17.7 — 2026-09-12
10
+
11
+ ### Added
12
+
13
+ - **Ship a synthetic external-checkout host canary with expiring links, explicit approval and purchase-status checks**
14
+
15
+ ## 0.17.6 — 2026-09-11
16
+
17
+ ### Added
18
+
19
+ - **Allow verified patched hosts through the version fallback with optional Apps configuration** (`clientSupportsMcpApps`, `McpAppsConfig`)
20
+
21
+ ### Fixed
22
+
23
+ - **Use text and structured report results on affected VS Code builds while their upstream webview startup race remains unresolved**
24
+
9
25
  ## 0.17.5 — 2026-09-11
10
26
 
11
27
  ### Added
@@ -0,0 +1,19 @@
1
+ # Upstream issues
2
+
3
+ ## VS Code webviews can go blank after a remount
4
+
5
+ Tracking: [microsoft/vscode#335908](https://github.com/microsoft/vscode/issues/335908). An issue was submitted; no pull request was submitted.
6
+
7
+ An earlier asynchronous origin-hash completion can replace the iframe after a newer mount connects. In native Windows VS Code 1.135.0, delaying the first hash reproduced a blank report. A current-promise guard passed three rounds across balance, usage and receipts in the isolated test process. The same unguarded method was found in the local 1.136.1 bundle; that version was source-inspected, not runtime-tested. See [the source patch and regression checker](canary/vscode/README.md).
8
+
9
+ ### Shared workaround in MCP 0.17.6
10
+
11
+ New sessions identifying themselves as `Visual Studio Code` version `1.135.0` or `1.136.1` receive text and structured results without Apps metadata or HTML resources. Report tools remain available. Authorization, billing and other host negotiations are unchanged. This exact-version rule is a presentation workaround, not a security boundary or a certification of other versions.
12
+
13
+ For an existing VS Code connection, run **MCP: Reset Cached Tools**, then **Developer: Reload Window**, reconnect/start the MCP server and open a new chat. Reconnection alone reused old UI metadata in our test. Reconnect the MCP server after upgrading: the negotiated Apps capability is stored in the session, so existing sessions retain their old decision. Consumers get the workaround through the package; they do not need a project-specific renderer or an editor patch.
14
+
15
+ `apps.allowKnownBrokenHosts: true` bypasses the version exclusion for controlled testing of a verified patched host. It still requires the host to advertise the Apps MIME capability. Do not enable it on ordinary affected installations. The diagnostic in-memory VS Code patch does not survive restart and is not the deployed workaround.
16
+
17
+ ### Removal
18
+
19
+ Keep the fallback for affected builds until they can reliably render Apps. When an upstream fix ships, verify fresh conversations, repeated mounts, refresh and pagination in the released host before certifying rich views there. Remove the override when a patched test build is retired. Keep the source regression and issue history so a successful retry is not mistaken for a fix.
@@ -0,0 +1,198 @@
1
+ /** Synthetic external-checkout fixture. No accounts, card inputs or gateway. */
2
+ import {
3
+ createCheckoutHandoffTool,
4
+ createMcpHandler,
5
+ createPurchaseStatusTool,
6
+ } from "@absolutejs/mcp";
7
+
8
+ export function createCheckoutCanary(origin: string, now = () => Date.now()) {
9
+ const publicUrl = new URL(origin);
10
+ if (publicUrl.protocol !== "https:" || publicUrl.origin !== origin)
11
+ throw Error("Provide an exact HTTPS checkout origin");
12
+ const purchases = new Map<
13
+ string,
14
+ { token: string; expires: number; approved: boolean }
15
+ >();
16
+ const started = now();
17
+ const checkout = createCheckoutHandoffTool({
18
+ origin,
19
+ issue: async (productId) => {
20
+ if (productId !== "synthetic-1000")
21
+ throw Error("Only synthetic-1000 is supported");
22
+ if (purchases.size >= 100)
23
+ throw Error("Restart the canary before creating more fixtures");
24
+ const purchaseId = crypto.randomUUID();
25
+ const token = crypto.randomUUID();
26
+ const expires = now() + 15 * 60_000;
27
+ purchases.set(purchaseId, { token, expires, approved: false });
28
+ return {
29
+ purchaseId,
30
+ url: `${origin}/checkout#${purchaseId}/${token}`,
31
+ expiresAt: new Date(expires).toISOString(),
32
+ };
33
+ },
34
+ });
35
+ const status = createPurchaseStatusTool({
36
+ read: async (purchaseId) => {
37
+ const purchase = purchases.get(purchaseId);
38
+ return purchase
39
+ ? {
40
+ purchaseId,
41
+ status: purchase.approved ? "approved" : "not_started",
42
+ creditsGranted: purchase.approved ? 1000 : 0,
43
+ }
44
+ : null;
45
+ },
46
+ });
47
+ const handler = createMcpHandler({
48
+ issuer: "http://127.0.0.1:4428",
49
+ path: "/mcp",
50
+ serverInfo: { name: "absolute-checkout-canary", version: "1" },
51
+ authorize: async () => ({
52
+ ok: true,
53
+ caller: "synthetic-fixture",
54
+ scopes: [],
55
+ }),
56
+ // This review authorizes only this synthetic developer fixture. Never reuse
57
+ // it for a real merchant or infer a commerce binding from clientInfo.
58
+ commerce: () => ({
59
+ profiles: ["direct-mcp"],
60
+ capabilities: { externalLinks: true },
61
+ reviews: [
62
+ {
63
+ id: "operator-synthetic-checkout-canary",
64
+ profile: "direct-mcp",
65
+ actions: ["external_checkout"],
66
+ categories: ["usage_credits"],
67
+ reviewedAt: new Date(started).toISOString(),
68
+ expiresAt: new Date(started + 60 * 60_000).toISOString(),
69
+ sourceUrls: ["https://code.visualstudio.com/license"],
70
+ },
71
+ ],
72
+ }),
73
+ tools: () => ({
74
+ prepare_test_checkout: {
75
+ ...checkout,
76
+ description: `SYNTHETIC TEST ONLY. Use productId synthetic-1000. ${checkout.description}`,
77
+ },
78
+ get_test_purchase_status: status,
79
+ }),
80
+ });
81
+ const headers = {
82
+ "content-type": "text/html; charset=utf-8",
83
+ "cache-control": "no-store",
84
+ "referrer-policy": "no-referrer",
85
+ "x-content-type-options": "nosniff",
86
+ "content-security-policy":
87
+ "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'",
88
+ };
89
+ const page = `<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>MCP checkout test</title><style>:root{color-scheme:light dark;font:18px system-ui}body{max-width:40rem;margin:10vh auto;padding:2rem}button{padding:1rem;font:inherit}strong{display:block;margin:1rem 0}</style><h1>MCP checkout test</h1><p>Synthetic developer fixture. No real payment, card information, account or subscription.</p><strong>1,000 simulated credits · $0 charged</strong><p id="status" role="status">Checking test link…</p><button id="approve" disabled>Simulate approval</button><script>
90
+ const capability=location.hash.slice(1);history.replaceState(null,'','/checkout');const status=document.getElementById('status'),button=document.getElementById('approve');
91
+ async function update(action){button.disabled=true;try{const r=await fetch('/state',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({capability,action})});if(!r.ok)throw Error('This test link is invalid or expired.');const value=await r.json();status.textContent=value.approved?'Approved — 1,000 simulated credits. Return to your assistant and check purchase status.':'Ready. Opening this page has not approved anything.';button.hidden=value.approved;button.disabled=value.approved;}catch(e){status.textContent=e.message;}}
92
+ button.addEventListener('click',()=>update('approve'));update('read');</script></html>`;
93
+ return {
94
+ mcp: handler,
95
+ checkout: async (request: Request): Promise<Response> => {
96
+ const url = new URL(request.url);
97
+ if (url.pathname === "/checkout" && request.method === "GET")
98
+ return new Response(page, { headers });
99
+ if (url.pathname !== "/state" || request.method !== "POST")
100
+ return new Response("Not found", { status: 404 });
101
+ if (
102
+ request.headers.get("origin") !== origin ||
103
+ !request.headers.get("content-type")?.startsWith("application/json")
104
+ )
105
+ return new Response("Forbidden", { status: 403 });
106
+ const raw = await request.text();
107
+ if (raw.length > 1024) return new Response("Too large", { status: 413 });
108
+ let input;
109
+ try {
110
+ input = JSON.parse(raw);
111
+ } catch {
112
+ return new Response("Invalid JSON", { status: 400 });
113
+ }
114
+ if (
115
+ !input ||
116
+ typeof input.capability !== "string" ||
117
+ !["read", "approve"].includes(input.action)
118
+ )
119
+ return new Response("Invalid request", { status: 400 });
120
+ const [id, token, extra] = input.capability.split("/");
121
+ const purchase = purchases.get(id);
122
+ if (
123
+ extra !== undefined ||
124
+ !purchase ||
125
+ purchase.token !== token ||
126
+ purchase.expires <= now()
127
+ )
128
+ return new Response("Invalid or expired test link", { status: 404 });
129
+ if (input.action === "approve") purchase.approved = true;
130
+ return Response.json(
131
+ { approved: purchase.approved },
132
+ { headers: { "cache-control": "no-store" } },
133
+ );
134
+ },
135
+ };
136
+ }
137
+
138
+ if (import.meta.main) {
139
+ const fixture = createCheckoutCanary(
140
+ process.env.CANARY_CHECKOUT_ORIGIN ?? "",
141
+ );
142
+ Bun.serve({
143
+ hostname: "127.0.0.1",
144
+ port: 4438,
145
+ fetch: async (request) => {
146
+ const response = await fixture.checkout(request);
147
+ const path = new URL(request.url).pathname;
148
+ console.log(
149
+ JSON.stringify({
150
+ surface: "checkout",
151
+ method: request.method,
152
+ route: path === "/checkout" || path === "/state" ? path : "unknown",
153
+ status: response.status,
154
+ }),
155
+ );
156
+ return response;
157
+ },
158
+ });
159
+ Bun.serve({
160
+ hostname: "127.0.0.1",
161
+ port: 4428,
162
+ fetch: async (request) => {
163
+ let rpc;
164
+ try {
165
+ if (request.method === "POST") rpc = await request.clone().json();
166
+ } catch {
167
+ /* handler validates */
168
+ }
169
+ const response =
170
+ (await fixture.mcp(request)) ??
171
+ new Response("Not found", { status: 404 });
172
+ // Never log checkout capabilities, arguments, transcripts or auth headers.
173
+ console.log(
174
+ JSON.stringify({
175
+ method: rpc?.method ?? request.method,
176
+ status: response.status,
177
+ ...(rpc?.method === "initialize"
178
+ ? {
179
+ client: rpc.params?.clientInfo?.name,
180
+ version: rpc.params?.clientInfo?.version,
181
+ }
182
+ : {}),
183
+ ...(rpc?.method === "tools/call" ? { tool: rpc.params?.name } : {}),
184
+ }),
185
+ );
186
+ return response;
187
+ },
188
+ });
189
+ console.log(
190
+ JSON.stringify({
191
+ ready: true,
192
+ mcp: "http://127.0.0.1:4428/mcp",
193
+ checkoutPort: 4438,
194
+ synthetic: true,
195
+ payments: false,
196
+ }),
197
+ );
198
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "host": "Visual Studio Code",
3
+ "version": "1.135.0",
4
+ "surface": "native Windows Copilot chat, directly configured loopback MCP",
5
+ "fixture": "canary/checkout.ts",
6
+ "date": "2026-09-12",
7
+ "synthetic": true,
8
+ "realPayments": false,
9
+ "results": {
10
+ "discoversBothTools": true,
11
+ "linkCreationApprovalVisible": true,
12
+ "toolResultReviewVisible": true,
13
+ "clickableMarkdownAnchor": true,
14
+ "nativeAnchorLaunch": "unverified: mouse and keyboard activation did not produce a measured checkout request",
15
+ "windowsHttpsHandlerOpensReturnedUrl": true,
16
+ "nativeChromeCheckoutPage": true,
17
+ "fragmentRemovedAfterLoad": true,
18
+ "beforeBrowserApproval": { "status": "not_started", "creditsGranted": 0 },
19
+ "afterBrowserApproval": { "status": "approved", "creditsGranted": 1000 },
20
+ "repeatedRead": { "status": "approved", "creditsGranted": 1000 }
21
+ },
22
+ "limits": [
23
+ "Native link launch remains a host-canary gate; no one-click end-to-end claim.",
24
+ "Browser state assertions used a second visible Chrome profile after explicit navigation to the returned URL.",
25
+ "No OAuth, real gateway, rich payment UI, real sales approval or marketplace distribution certified.",
26
+ "No checkout capability, purchase ID, card data or account credentials included."
27
+ ]
28
+ }
@@ -28,4 +28,6 @@ Some unmodified first-load runs passed too: this is a timing-sensitive failure,
28
28
 
29
29
  ## Delivery status
30
30
 
31
- This package distributes a reviewable upstream source patch and regression checker. It does **not** patch users' VS Code installations. The in-memory test change does not survive an editor restart. An upstream release or an explicitly maintained patched host build is required before claiming that ordinary VS Code users receive this fix. Keep the first-load rollout gate open until that distribution is verified. No upstream submission is implied by this artifact.
31
+ The bug is reported in [microsoft/vscode#335908](https://github.com/microsoft/vscode/issues/335908); no PR was submitted. This package distributes the source patch and checker for review, but does not modify installed editors. The test-process patch disappears on restart.
32
+
33
+ MCP 0.17.6 instead defaults affected versions to text and structured reports. Reconnect after upgrading to negotiate the fallback. See [UPSTREAM_ISSUES.md](../../UPSTREAM_ISSUES.md) for the exact version scope, diagnostic override and removal conditions. Rich first-load support remains unverified in an unmodified released host.
package/changelog.json CHANGED
@@ -1,143 +1,171 @@
1
1
  {
2
- "contract": 1,
3
- "name": "@absolutejs/mcp",
4
- "releases": [
5
- {
6
- "version": "0.17.5",
7
- "date": "2026-09-11",
8
- "changes": [
9
- {
10
- "kind": "added",
11
- "summary": "Distribute a verified VS Code webview startup-race source patch and actual-method regression checker, with explicit upstream delivery requirements"
12
- }
13
- ]
14
- },
15
- {
16
- "version": "0.17.4",
17
- "date": "2026-09-11",
18
- "changes": [
19
- {
20
- "kind": "added",
21
- "summary": "Ship an authenticated two-account staging canary for read isolation, credential rejection and session reconnect with private credentials and aggregate-only results"
22
- }
23
- ]
24
- },
25
- {
26
- "version": "0.17.3",
27
- "date": "2026-09-11",
28
- "changes": [
29
- {
30
- "kind": "fixed",
31
- "summary": "Authorize session deletion, recover explicit client initialization after expiry, and preserve typed HTTP failures without replaying tools"
32
- },
33
- {
34
- "kind": "fixed",
35
- "summary": "Accept the standard protocol-header compatibility fallback used by VS Code Copilot and record native report rendering evidence"
36
- }
37
- ]
38
- },
39
- {
40
- "version": "0.17.2",
41
- "date": "2026-09-11",
42
- "changes": [
43
- {
44
- "kind": "added",
45
- "summary": "Record verified Claude web rendering, refresh, pagination and narrow-viewport host canary evidence"
46
- }
47
- ]
48
- },
49
- {
50
- "version": "0.17.1",
51
- "date": "2026-09-11",
52
- "changes": [
53
- {
54
- "kind": "added",
55
- "summary": "Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence"
56
- }
57
- ]
58
- },
59
- {
60
- "version": "0.17.0",
61
- "date": "2026-09-11",
62
- "changes": [
63
- {
64
- "kind": "added",
65
- "summary": "Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views"
66
- },
67
- {
68
- "kind": "added",
69
- "summary": "Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries"
70
- },
71
- {
72
- "kind": "changed",
73
- "summary": "Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported",
74
- "symbols": [
75
- "McpClientOptions",
76
- "McpRemoteTool",
77
- "createSessionRegistry",
78
- "McpSessionStore",
79
- "McpServerConfig",
80
- "McpTool",
81
- "McpToolResult"
82
- ]
83
- }
84
- ]
85
- },
86
- {
87
- "version": "0.16.0",
88
- "date": "2026-09-11",
89
- "changes": [
90
- {
91
- "kind": "added",
92
- "summary": "Add account-bound billing status, paginated receipts, bounded usage and reviewed billing-management links"
93
- }
94
- ]
95
- },
96
- {
97
- "version": "0.15.1",
98
- "date": "2026-09-11",
99
- "changes": [
100
- {
101
- "kind": "fixed",
102
- "summary": "Build and test before publishing so checkout exports are present in the distributed artifact"
103
- }
104
- ]
105
- },
106
- {
107
- "version": "0.15.0",
108
- "date": "2026-09-11",
109
- "changes": [
110
- {
111
- "kind": "added",
112
- "summary": "Add commerce-classified account-bound checkout handoff and purchase status tools"
113
- }
114
- ]
115
- },
116
- {
117
- "changes": [
118
- {
119
- "kind": "added",
120
- "summary": "Add explicit credit-budget envelopes for durable prepaid MCP work"
121
- }
122
- ],
123
- "date": "2026-09-11",
124
- "version": "0.14.0"
125
- },
126
- {
127
- "changes": [
128
- {
129
- "kind": "added",
130
- "summary": "Add reviewed host commerce eligibility, execution guards, and reusable credit status tools",
131
- "symbols": [
132
- "McpServerConfig",
133
- "McpTool",
134
- "evaluateCommerce",
135
- "createCreditBalanceTool"
136
- ]
137
- }
138
- ],
139
- "date": "2026-09-11",
140
- "version": "0.13.0"
141
- }
142
- ]
2
+ "contract": 1,
3
+ "name": "@absolutejs/mcp",
4
+ "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "kind": "added",
9
+ "summary": "Ship a synthetic external-checkout host canary with expiring links, explicit approval and purchase-status checks"
10
+ }
11
+ ],
12
+ "date": "2026-09-12",
13
+ "version": "0.17.7"
14
+ },
15
+ {
16
+ "changes": [
17
+ {
18
+ "kind": "fixed",
19
+ "summary": "Use text and structured report results on affected VS Code builds while their upstream webview startup race remains unresolved"
20
+ },
21
+ {
22
+ "kind": "added",
23
+ "summary": "Allow verified patched hosts through the version fallback with optional Apps configuration",
24
+ "symbols": [
25
+ "clientSupportsMcpApps",
26
+ "McpAppsConfig"
27
+ ]
28
+ }
29
+ ],
30
+ "date": "2026-09-11",
31
+ "version": "0.17.6"
32
+ },
33
+ {
34
+ "changes": [
35
+ {
36
+ "kind": "added",
37
+ "summary": "Distribute a verified VS Code webview startup-race source patch and actual-method regression checker, with explicit upstream delivery requirements"
38
+ }
39
+ ],
40
+ "date": "2026-09-11",
41
+ "version": "0.17.5"
42
+ },
43
+ {
44
+ "changes": [
45
+ {
46
+ "kind": "added",
47
+ "summary": "Ship an authenticated two-account staging canary for read isolation, credential rejection and session reconnect with private credentials and aggregate-only results"
48
+ }
49
+ ],
50
+ "date": "2026-09-11",
51
+ "version": "0.17.4"
52
+ },
53
+ {
54
+ "changes": [
55
+ {
56
+ "kind": "fixed",
57
+ "summary": "Authorize session deletion, recover explicit client initialization after expiry, and preserve typed HTTP failures without replaying tools"
58
+ },
59
+ {
60
+ "kind": "fixed",
61
+ "summary": "Accept the standard protocol-header compatibility fallback used by VS Code Copilot and record native report rendering evidence"
62
+ }
63
+ ],
64
+ "date": "2026-09-11",
65
+ "version": "0.17.3"
66
+ },
67
+ {
68
+ "changes": [
69
+ {
70
+ "kind": "added",
71
+ "summary": "Record verified Claude web rendering, refresh, pagination and narrow-viewport host canary evidence"
72
+ }
73
+ ],
74
+ "date": "2026-09-11",
75
+ "version": "0.17.2"
76
+ },
77
+ {
78
+ "changes": [
79
+ {
80
+ "kind": "added",
81
+ "summary": "Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence"
82
+ }
83
+ ],
84
+ "date": "2026-09-11",
85
+ "version": "0.17.1"
86
+ },
87
+ {
88
+ "changes": [
89
+ {
90
+ "kind": "added",
91
+ "summary": "Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views"
92
+ },
93
+ {
94
+ "kind": "added",
95
+ "summary": "Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries"
96
+ },
97
+ {
98
+ "kind": "changed",
99
+ "summary": "Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported",
100
+ "symbols": [
101
+ "McpClientOptions",
102
+ "McpRemoteTool",
103
+ "createSessionRegistry",
104
+ "McpSessionStore",
105
+ "McpServerConfig",
106
+ "McpTool",
107
+ "McpToolResult"
108
+ ]
109
+ }
110
+ ],
111
+ "date": "2026-09-11",
112
+ "version": "0.17.0"
113
+ },
114
+ {
115
+ "changes": [
116
+ {
117
+ "kind": "added",
118
+ "summary": "Add account-bound billing status, paginated receipts, bounded usage and reviewed billing-management links"
119
+ }
120
+ ],
121
+ "date": "2026-09-11",
122
+ "version": "0.16.0"
123
+ },
124
+ {
125
+ "changes": [
126
+ {
127
+ "kind": "fixed",
128
+ "summary": "Build and test before publishing so checkout exports are present in the distributed artifact"
129
+ }
130
+ ],
131
+ "date": "2026-09-11",
132
+ "version": "0.15.1"
133
+ },
134
+ {
135
+ "changes": [
136
+ {
137
+ "kind": "added",
138
+ "summary": "Add commerce-classified account-bound checkout handoff and purchase status tools"
139
+ }
140
+ ],
141
+ "date": "2026-09-11",
142
+ "version": "0.15.0"
143
+ },
144
+ {
145
+ "changes": [
146
+ {
147
+ "kind": "added",
148
+ "summary": "Add explicit credit-budget envelopes for durable prepaid MCP work"
149
+ }
150
+ ],
151
+ "date": "2026-09-11",
152
+ "version": "0.14.0"
153
+ },
154
+ {
155
+ "changes": [
156
+ {
157
+ "kind": "added",
158
+ "summary": "Add reviewed host commerce eligibility, execution guards, and reusable credit status tools",
159
+ "symbols": [
160
+ "McpServerConfig",
161
+ "McpTool",
162
+ "evaluateCommerce",
163
+ "createCreditBalanceTool"
164
+ ]
165
+ }
166
+ ],
167
+ "date": "2026-09-11",
168
+ "version": "0.13.0"
169
+ }
170
+ ]
143
171
  }
package/dist/apps.js CHANGED
@@ -49,9 +49,11 @@ var createBillingApps = () => {
49
49
 
50
50
  // src/apps.ts
51
51
  var MCP_APP_MIME = "text/html;profile=mcp-app";
52
- var clientSupportsMcpApps = (params) => {
52
+ var clientSupportsMcpApps = (params, options = {}) => {
53
53
  if (!isRecord(params) || !isRecord(params.capabilities) || !isRecord(params.capabilities.extensions))
54
54
  return false;
55
+ if (!options.allowKnownBrokenHosts && isRecord(params.clientInfo) && params.clientInfo.name === "Visual Studio Code" && (params.clientInfo.version === "1.135.0" || params.clientInfo.version === "1.136.1"))
56
+ return false;
55
57
  const ui = params.capabilities.extensions["io.modelcontextprotocol/ui"];
56
58
  return isRecord(ui) && Array.isArray(ui.mimeTypes) && ui.mimeTypes.includes(MCP_APP_MIME);
57
59
  };
package/dist/index.js CHANGED
@@ -49,9 +49,11 @@ var createBillingApps = () => {
49
49
 
50
50
  // src/apps.ts
51
51
  var MCP_APP_MIME = "text/html;profile=mcp-app";
52
- var clientSupportsMcpApps = (params) => {
52
+ var clientSupportsMcpApps = (params, options = {}) => {
53
53
  if (!isRecord(params) || !isRecord(params.capabilities) || !isRecord(params.capabilities.extensions))
54
54
  return false;
55
+ if (!options.allowKnownBrokenHosts && isRecord(params.clientInfo) && params.clientInfo.name === "Visual Studio Code" && (params.clientInfo.version === "1.135.0" || params.clientInfo.version === "1.136.1"))
56
+ return false;
55
57
  const ui = params.capabilities.extensions["io.modelcontextprotocol/ui"];
56
58
  return isRecord(ui) && Array.isArray(ui.mimeTypes) && ui.mimeTypes.includes(MCP_APP_MIME);
57
59
  };
@@ -1379,7 +1381,7 @@ var initialize = async (config, id, params, context) => {
1379
1381
  if (!config.elicitation?.enabled && !config.apps || !context.sessions)
1380
1382
  return response;
1381
1383
  const elicitation = clientElicitation(params);
1382
- const sessionId = await context.sessions.create(elicitation.form || elicitation.url, elicitation.url, Boolean(config.apps) && clientSupportsMcpApps(params));
1384
+ const sessionId = await context.sessions.create(elicitation.form || elicitation.url, elicitation.url, Boolean(config.apps) && clientSupportsMcpApps(params, config.apps));
1383
1385
  response.headers.set("Mcp-Session-Id", sessionId);
1384
1386
  return response;
1385
1387
  };
@@ -5,11 +5,13 @@ export type McpAppResource = {
5
5
  html: string;
6
6
  };
7
7
  export type McpAppsConfig = {
8
+ /** Only enable for a host build whose upstream rendering fix has been verified. */
9
+ allowKnownBrokenHosts?: boolean;
8
10
  resources: Record<string, McpAppResource>;
9
11
  store?: McpSessionStore;
10
12
  };
11
13
  /** Capability is presentation only; never a commerce or authorization decision. */
12
- export declare const clientSupportsMcpApps: (params: unknown) => boolean;
14
+ export declare const clientSupportsMcpApps: (params: unknown, options?: Pick<McpAppsConfig, "allowKnownBrokenHosts">) => boolean;
13
15
  export declare const withMcpApp: (tool: McpTool, resourceUri: string) => McpTool;
14
16
  /** Offline templates: all data comes through authenticated tool results and the
15
17
  * official host bridge. Network, nested frames and privileged permissions are not requested. */
@@ -264,3 +264,16 @@ The first slice exports `evaluateCommerce` through `@absolutejs/mcp/commerce`, a
264
264
  The bundled rules cover the explicit restrictions established above; the broad host inventory currently maps to reviewed direct/self-hosted or unknown profiles rather than claiming every host has been verified. Missing policy, malformed categories, ambiguous restrictions, expired reviews and unavailable capabilities block the action. Deployment reviews cannot override bundled restrictions.
265
265
 
266
266
  This slice is not a general content filter: prompts, resources, untagged tools and arbitrary returned links require the shared evaluator at their own presentation boundaries. Shared renderers, native capability plumbing, checkout sessions, prepaid accounting changes and live cross-host conformance remain to implement. Existing Agency enforcement remains independent.
267
+
268
+ ## September 12 follow-up: native VS Code developer checkout test
269
+
270
+ The directly configured VS Code/Copilot channel now has a package-owned
271
+ [synthetic checkout canary](host-canaries.md#synthetic-external-checkout-canary).
272
+ This is an application development test within VS Code license §1, with no real
273
+ merchant, card input, funds or credits. It does not change the `direct-mcp`
274
+ production default, approve Marketplace distribution, or establish permission
275
+ for live sales under every Copilot agreement. Check the actual account's terms:
276
+ individual Copilot uses GitHub ToS §J; volume licensing has separate current
277
+ Generative AI Services Terms. The old Copilot product-specific terms are archived.
278
+ The linked canary record preserves the exact native host result independently
279
+ of commercial eligibility. Existing Claude and ChatGPT restrictions still apply.
@@ -97,3 +97,68 @@ This verifies the selected read path, not every tenant resource, token revocatio
97
97
  ## VS Code first-load race identified
98
98
 
99
99
  MCP 0.17.5 includes `canary/vscode/README.md`, a VS Code source patch and an executable actual-method regression. A controlled out-of-order origin-hash completion reproduces a blank view in native VS Code 1.135.0. The candidate current-promise guard passed three rounds across all three report views and both source-level completion orders. This is a host fix, not an MCP renderer change. The package distributes the patch for review; it does not modify installed editors or certify an upstream release. First-load activation remains blocked until a supported host containing the fix is verified.
100
+
101
+ ## Temporary VS Code fallback (0.17.6)
102
+
103
+ The issue is tracked in [microsoft/vscode#335908](https://github.com/microsoft/vscode/issues/335908). Known affected versions now receive text and structured reports on new sessions, keeping tools usable without invoking the faulty webview path. Other hosts retain their negotiated presentation. See [UPSTREAM_ISSUES.md](../UPSTREAM_ISSUES.md) for scope and removal conditions. This workaround does not certify rich rendering on affected editors.
104
+
105
+ Native Windows VS Code 1.135.0 verification: after removing the in-memory editor patch, reconnecting alone left cached UI metadata and produced resource errors. Running **MCP: Reset Cached Tools**, reloading the window and opening a new chat cleared it. The final run returned all three reports as visible text, with three successful tool calls, no resource reads and no App frames. This is a verified text fallback, not rich rendering evidence.
106
+
107
+ ## Synthetic external-checkout canary
108
+
109
+ `bun run canary:checkout` (installed: `bun node_modules/@absolutejs/mcp/canary/checkout.ts`)
110
+ uses the package's real checkout handoff and purchase-status tools with in-memory
111
+ synthetic purchases. Set `CANARY_CHECKOUT_ORIGIN` to the exact HTTPS origin of a
112
+ temporary reverse proxy to loopback port 4438. Connect the desktop test host only
113
+ to `http://127.0.0.1:4428/mcp`. Expose only port 4438 through the proxy; it serves
114
+ only the fixture page/state routes, never MCP. Stop both processes after testing.
115
+ No account database, payment provider, card input or real credit ledger is used.
116
+ Do not mount either handler in a customer application.
117
+
118
+ This is an operator-authorized development test, not a live commerce approval.
119
+ The fixture's one-hour, server-owned review applies only to synthetic links;
120
+ never copy it into a production commerce binding. VS Code's [license §1](https://code.visualstudio.com/license)
121
+ permits application development/testing. GitHub's [additional product terms](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot)
122
+ point individual Copilot users to ToS §J and business users to their applicable
123
+ agreement. The older Copilot product terms are archived; current volume purchases
124
+ may instead use the [March 2026 Generative AI Services Terms](https://github.com/customer-terms/github-generative-ai-services-terms).
125
+ Do not treat an old agreement, another product's marketplace rules, or this
126
+ technical test as approval for every Copilot account or live digital sales.
127
+
128
+ 1. Request `prepare_test_checkout` with `productId: "synthetic-1000"` and approve
129
+ the host's tool prompt if shown. Ask for a clickable link and a
130
+ `get_test_purchase_status` read using the returned `purchaseId`.
131
+ 2. Confirm status is `not_started`, with zero granted credits. Click the link
132
+ using the host's ordinary external-link UI. The HTTPS page must clearly say
133
+ synthetic test, show no card fields, and require **Simulate approval**.
134
+ 3. Before clicking that button, read status again: still zero. Click once, then
135
+ return to chat and request status again: approved, 1,000 simulated credits.
136
+ 4. Repeat the read: still 1,000. Never let the agent approve the browser step on
137
+ behalf of a paying customer. This operator test contains no real payment.
138
+
139
+ Links expire after 15 minutes. Capabilities travel in a URL fragment, are removed
140
+ from the address bar on load, and are submitted only to the same checkout origin.
141
+ Refreshing after removal intentionally requires reopening the original link.
142
+ The fixture is bounded to 100 purchases per run. Its aggregate log excludes
143
+ capabilities and tool arguments; keep full host transcripts private. Record the
144
+ actual link UI, approval UI, browser navigation, before/after tool results and
145
+ host version. This does not certify real merchant approval, OAuth continuity,
146
+ 3DS, or rich embedded payment support.
147
+
148
+ ### September 12 VS Code checkout observation
149
+
150
+ Native Windows VS Code 1.135.0/Copilot discovered both tools, displayed link-creation
151
+ and result-review prompts, and rendered the returned HTTPS URL as a Markdown
152
+ anchor. Native Chrome showed the fixture page with its fragment removed. Copilot
153
+ reported `not_started`/0 after the browser opened, then `approved`/1000 after the
154
+ operator's simulated approval, including a second unchanged status read.
155
+
156
+ **Qualified result:** mouse/keyboard activation of the Copilot anchor did not
157
+ produce a measured checkout request in the final navigation probe. Opening the
158
+ returned URL through the Windows HTTPS handler worked in the default Chrome
159
+ profile. Browser state assertions used explicit navigation in a separate visible
160
+ Chrome profile. These are separate observations: native one-click chat-to-browser
161
+ launch is still unverified. No upstream cause has been established. Use the
162
+ returned URL manually during development; do not advertise the seamless host
163
+ handoff as passed. See `canary/results/vscode-checkout-2026-09-12.json` for aggregate
164
+ evidence. No host/source patch or browser-default change was applied.
package/package.json CHANGED
@@ -72,7 +72,8 @@
72
72
  "docs/mcp-apps.md",
73
73
  "docs/third-party",
74
74
  "canary",
75
- "docs/host-canaries.md"
75
+ "docs/host-canaries.md",
76
+ "UPSTREAM_ISSUES.md"
76
77
  ],
77
78
  "scripts": {
78
79
  "build": "bun run build:apps && rm -rf dist && bun build src/index.ts src/manifest.ts src/commerce.ts src/apps.ts --outdir dist --root ./src --target=bun --external @absolutejs/agency --external '@absolutejs/agency/*' --external elysia && tsc --emitDeclarationOnly --project tsconfig.json && absolute-manifest emit",
@@ -84,8 +85,9 @@
84
85
  "prepublishOnly": "bun run check:package",
85
86
  "build:apps": "bun scripts/build-apps.ts",
86
87
  "canary": "bun canary/server.ts",
87
- "check:canary": "tsc --noEmit --strict --skipLibCheck --moduleResolution bundler --module esnext --target esnext --types bun canary/server.ts canary/authenticated.ts canary/vscode/check-mount.ts"
88
+ "check:canary": "tsc --noEmit --strict --skipLibCheck --moduleResolution bundler --module esnext --target esnext --types bun canary/server.ts canary/authenticated.ts canary/vscode/check-mount.ts canary/checkout.ts",
89
+ "canary:checkout": "bun canary/checkout.ts"
88
90
  },
89
91
  "types": "./dist/src/index.d.ts",
90
- "version": "0.17.5"
92
+ "version": "0.17.7"
91
93
  }