@absolutejs/mcp 0.16.0 → 0.17.1
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 +17 -0
- package/README.md +4 -0
- package/canary/results/2026-09-11-terminal.jsonl +20 -0
- package/canary/server.ts +154 -0
- package/changelog.json +37 -0
- package/dist/apps.js +90 -0
- package/dist/browser/billing.d.ts +1 -0
- package/dist/index.js +161 -36
- package/dist/scripts/build-apps.d.ts +1 -0
- package/dist/src/apps.d.ts +33 -0
- package/dist/src/billingApp.generated.d.ts +2 -0
- package/dist/src/billingApps.d.ts +8 -0
- package/dist/src/client.d.ts +3 -0
- package/dist/src/index.d.ts +3 -1
- package/dist/src/postgres.d.ts +5 -0
- package/dist/src/sessions.d.ts +2 -1
- package/dist/src/types.d.ts +11 -0
- package/docs/host-canaries.md +60 -0
- package/docs/mcp-apps.md +60 -0
- package/docs/third-party/mcp-apps-LICENSE +216 -0
- package/docs/third-party/mcp-client-LICENSE +216 -0
- package/docs/third-party/mcp-core-LICENSE +216 -0
- package/docs/third-party/standard-schema-LICENSE +21 -0
- package/docs/third-party/zod-LICENSE +21 -0
- package/package.json +20 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ 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.1 — 2026-09-11
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence**
|
|
14
|
+
|
|
15
|
+
## 0.17.0 — 2026-09-11
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views**
|
|
20
|
+
- **Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries**
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported** (`McpClientOptions`, `McpRemoteTool`, `createSessionRegistry`, `McpSessionStore`, `McpServerConfig`, `McpTool`, `McpToolResult`)
|
|
25
|
+
|
|
9
26
|
## 0.16.0 — 2026-09-11
|
|
10
27
|
|
|
11
28
|
### Added
|
package/README.md
CHANGED
|
@@ -433,3 +433,7 @@ on the Change Date.
|
|
|
433
433
|
`createCheckoutHandoffTool` and `createPurchaseStatusTool` provide account-bound credit checkout and recovery contracts. The issuer must bind server pricing and identity; route these tools through the commerce guard. Checkout is classified as `external_checkout`, so restricted and unverified channels cannot discover or execute it. Status works at zero credits. Never pass card data in tool input. See [host rules](docs/commerce-host-rules.md).
|
|
434
434
|
|
|
435
435
|
`createBillingReportTools` binds billing status, paginated receipts, and bounded UTC usage reports to authenticated reader callbacks. These non-transactional tools remain available at zero balance. The shared billing projections discard payment/provider secrets and enforce reconciled usage breakdowns. `createBillingManagementTool` returns a fixed HTTPS browser page requiring normal browser authentication; because that page can initiate purchases, it retains `external_checkout` commerce classification. Never label a purchase-capable page informational to bypass host restrictions.
|
|
436
|
+
|
|
437
|
+
## Interactive MCP Apps
|
|
438
|
+
|
|
439
|
+
`createBillingApps()` adds reusable read-only credit, usage and receipt views with the official browser SDK. Apps capability negotiation, guarded resources and text fallbacks live in the package. See [MCP Apps](docs/mcp-apps.md) for integration, session migration, CSP restrictions and host validation boundaries.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{"ready":true,"url":"http://127.0.0.1:4428/mcp","data":"synthetic","payments":false}
|
|
2
|
+
{"method":"server/discover","status":400}
|
|
3
|
+
{"method":"initialize","status":200,"client":"claude-code","version":"2.1.265","requestedProtocol":"2025-11-25","negotiatedProtocol":"2025-06-18","appsMimeTypes":[],"elicitation":true}
|
|
4
|
+
{"method":"notifications/initialized","status":202}
|
|
5
|
+
{"method":"GET","status":405}
|
|
6
|
+
{"method":"tools/list","status":200,"tools":[{"name":"get_billing_status","ui":false},{"name":"list_receipts","ui":false},{"name":"get_usage_report","ui":false}]}
|
|
7
|
+
{"method":"resources/list","status":200}
|
|
8
|
+
{"method":"tools/call","status":200,"tool":"get_billing_status","isError":false}
|
|
9
|
+
{"method":"tools/call","status":200,"tool":"get_usage_report","isError":false}
|
|
10
|
+
{"method":"tools/call","status":200,"tool":"list_receipts","isError":false}
|
|
11
|
+
{"method":"tools/call","status":200,"tool":"list_receipts","isError":false}
|
|
12
|
+
{"method":"initialize","status":200,"client":"codex-mcp-client","version":"0.154.0","requestedProtocol":"2025-06-18","negotiatedProtocol":"2025-06-18","appsMimeTypes":[],"elicitation":true}
|
|
13
|
+
{"method":"notifications/initialized","status":202}
|
|
14
|
+
{"method":"GET","status":405}
|
|
15
|
+
{"method":"tools/list","status":200,"tools":[{"name":"get_billing_status","ui":false},{"name":"list_receipts","ui":false},{"name":"get_usage_report","ui":false}]}
|
|
16
|
+
{"method":"tools/call","status":200,"tool":"get_billing_status","isError":false}
|
|
17
|
+
{"method":"tools/call","status":200,"tool":"get_usage_report","isError":false}
|
|
18
|
+
{"method":"tools/call","status":200,"tool":"list_receipts","isError":false}
|
|
19
|
+
{"method":"tools/call","status":200,"tool":"list_receipts","isError":false}
|
|
20
|
+
{"method":"DELETE","status":204}
|
package/canary/server.ts
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Synthetic host canary. Never mount this handler in a customer application. */
|
|
2
|
+
import {
|
|
3
|
+
createMcpHandler,
|
|
4
|
+
createBillingApps,
|
|
5
|
+
createBillingReportTools,
|
|
6
|
+
} from "@absolutejs/mcp";
|
|
7
|
+
import { encodeReceiptCursor } from "@absolutejs/billing/reports";
|
|
8
|
+
const apps = createBillingApps();
|
|
9
|
+
const id = "00000000-0000-4000-8000-000000000001";
|
|
10
|
+
const at = "2026-09-01T00:00:00.000Z";
|
|
11
|
+
const readers = createBillingReportTools({
|
|
12
|
+
status: async () => ({
|
|
13
|
+
automaticRefill: false,
|
|
14
|
+
credits: {
|
|
15
|
+
remaining: 0,
|
|
16
|
+
reserved: 12,
|
|
17
|
+
purchased: 0,
|
|
18
|
+
promotional: 0,
|
|
19
|
+
debt: 0,
|
|
20
|
+
},
|
|
21
|
+
portalAccess: false,
|
|
22
|
+
subscription: null,
|
|
23
|
+
}),
|
|
24
|
+
receipts: async ({ cursor }) => ({
|
|
25
|
+
receipts: cursor
|
|
26
|
+
? []
|
|
27
|
+
: [
|
|
28
|
+
{
|
|
29
|
+
id,
|
|
30
|
+
issuedAt: at,
|
|
31
|
+
source: "credit_purchase",
|
|
32
|
+
amountCents: 1000,
|
|
33
|
+
refundedAmountCents: 200,
|
|
34
|
+
currency: "USD",
|
|
35
|
+
status: "partially_refunded",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
nextCursor: cursor ? null : encodeReceiptCursor({ at, id }),
|
|
39
|
+
}),
|
|
40
|
+
usage: async (range) => ({
|
|
41
|
+
...range,
|
|
42
|
+
creditsConsumed: 8,
|
|
43
|
+
events: 2,
|
|
44
|
+
byFeature: [{ feature: "fixture_workflow", credits: 8, events: 2 }],
|
|
45
|
+
byDay: [{ day: range.from, credits: 8, events: 2 }],
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
const handler = createMcpHandler({
|
|
49
|
+
issuer: "http://127.0.0.1:4428",
|
|
50
|
+
path: "/mcp",
|
|
51
|
+
serverInfo: { name: "absolute-billing-canary", version: "1" },
|
|
52
|
+
supportedProtocols: ["2025-06-18"],
|
|
53
|
+
authorize: async () => ({
|
|
54
|
+
ok: true,
|
|
55
|
+
caller: "synthetic-fixture",
|
|
56
|
+
scopes: [],
|
|
57
|
+
}),
|
|
58
|
+
commerce: () => ({ profiles: ["unknown"] }),
|
|
59
|
+
apps: { resources: apps.resources },
|
|
60
|
+
tools: () => apps.decorateTools(readers),
|
|
61
|
+
});
|
|
62
|
+
// Fail before accepting a host if synthetic records violate the public contract.
|
|
63
|
+
for (const [name, args] of [
|
|
64
|
+
["get_billing_status", {}],
|
|
65
|
+
["get_usage_report", { from: "2026-09-01", to: "2026-09-11" }],
|
|
66
|
+
["list_receipts", {}],
|
|
67
|
+
["list_receipts", { cursor: encodeReceiptCursor({ at, id }) }],
|
|
68
|
+
] as const) {
|
|
69
|
+
const response = await handler(
|
|
70
|
+
new Request("http://127.0.0.1:4428/mcp", {
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: {
|
|
73
|
+
"content-type": "application/json",
|
|
74
|
+
"mcp-protocol-version": "2025-06-18",
|
|
75
|
+
},
|
|
76
|
+
body: JSON.stringify({
|
|
77
|
+
jsonrpc: "2.0",
|
|
78
|
+
id: 1,
|
|
79
|
+
method: "tools/call",
|
|
80
|
+
params: { name, arguments: args },
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
const body = await response?.json();
|
|
85
|
+
if (!response?.ok || !body?.result || body.error || body.result.isError)
|
|
86
|
+
throw Error(`Canary preflight failed: ${name}`);
|
|
87
|
+
}
|
|
88
|
+
Bun.serve({
|
|
89
|
+
hostname: "127.0.0.1",
|
|
90
|
+
port: 4428,
|
|
91
|
+
fetch: async (request) => {
|
|
92
|
+
let rpc;
|
|
93
|
+
try {
|
|
94
|
+
if (request.method === "POST") rpc = await request.clone().json();
|
|
95
|
+
} catch {
|
|
96
|
+
/* Handler owns malformed input. */
|
|
97
|
+
}
|
|
98
|
+
const response =
|
|
99
|
+
(await handler(request)) ?? new Response("Not found", { status: 404 });
|
|
100
|
+
let body;
|
|
101
|
+
if (response.headers.get("content-type")?.includes("application/json")) {
|
|
102
|
+
try {
|
|
103
|
+
body = await response.clone().json();
|
|
104
|
+
} catch {
|
|
105
|
+
/* No raw response logging. */
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Only explicit protocol fields: never headers, tokens, session IDs, arguments or report bodies.
|
|
109
|
+
console.log(
|
|
110
|
+
JSON.stringify({
|
|
111
|
+
method: rpc?.method ?? request.method,
|
|
112
|
+
status: response.status,
|
|
113
|
+
...(rpc?.method === "initialize"
|
|
114
|
+
? {
|
|
115
|
+
client: rpc.params?.clientInfo?.name,
|
|
116
|
+
version: rpc.params?.clientInfo?.version,
|
|
117
|
+
requestedProtocol: rpc.params?.protocolVersion,
|
|
118
|
+
negotiatedProtocol: body?.result?.protocolVersion,
|
|
119
|
+
appsMimeTypes:
|
|
120
|
+
rpc.params?.capabilities?.extensions?.[
|
|
121
|
+
"io.modelcontextprotocol/ui"
|
|
122
|
+
]?.mimeTypes ?? [],
|
|
123
|
+
elicitation: !!rpc.params?.capabilities?.elicitation,
|
|
124
|
+
}
|
|
125
|
+
: {}),
|
|
126
|
+
...(rpc?.method === "tools/list"
|
|
127
|
+
? {
|
|
128
|
+
tools: body?.result?.tools?.map(
|
|
129
|
+
(tool: { name: string; _meta?: { ui?: unknown } }) => ({
|
|
130
|
+
name: tool.name,
|
|
131
|
+
ui: !!tool._meta?.ui,
|
|
132
|
+
}),
|
|
133
|
+
),
|
|
134
|
+
}
|
|
135
|
+
: {}),
|
|
136
|
+
...(rpc?.method === "tools/call"
|
|
137
|
+
? {
|
|
138
|
+
tool: rpc.params?.name,
|
|
139
|
+
isError: body?.result?.isError ?? !!body?.error,
|
|
140
|
+
}
|
|
141
|
+
: {}),
|
|
142
|
+
}),
|
|
143
|
+
);
|
|
144
|
+
return response;
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
console.log(
|
|
148
|
+
JSON.stringify({
|
|
149
|
+
ready: true,
|
|
150
|
+
url: "http://127.0.0.1:4428/mcp",
|
|
151
|
+
data: "synthetic",
|
|
152
|
+
payments: false,
|
|
153
|
+
}),
|
|
154
|
+
);
|
package/changelog.json
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
"contract": 1,
|
|
3
3
|
"name": "@absolutejs/mcp",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.17.1",
|
|
7
|
+
"date": "2026-09-11",
|
|
8
|
+
"changes": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "added",
|
|
11
|
+
"summary": "Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"version": "0.17.0",
|
|
17
|
+
"date": "2026-09-11",
|
|
18
|
+
"changes": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "added",
|
|
21
|
+
"summary": "Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "added",
|
|
25
|
+
"summary": "Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"kind": "changed",
|
|
29
|
+
"summary": "Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported",
|
|
30
|
+
"symbols": [
|
|
31
|
+
"McpClientOptions",
|
|
32
|
+
"McpRemoteTool",
|
|
33
|
+
"createSessionRegistry",
|
|
34
|
+
"McpSessionStore",
|
|
35
|
+
"McpServerConfig",
|
|
36
|
+
"McpTool",
|
|
37
|
+
"McpToolResult"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
5
42
|
{
|
|
6
43
|
"version": "0.16.0",
|
|
7
44
|
"date": "2026-09-11",
|