@absolutejs/mcp 0.14.0 → 0.15.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 +12 -0
- package/README.md +4 -0
- package/changelog.json +50 -30
- package/dist/commerce.js +88 -0
- package/dist/index.js +88 -0
- package/dist/manifest.js +3 -1
- package/dist/src/checkoutTools.d.ts +19 -0
- package/dist/src/commerce.d.ts +1 -0
- package/dist/src/index.d.ts +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,18 @@ 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.15.1 — 2026-09-11
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Build and test before publishing so checkout exports are present in the distributed artifact**
|
|
14
|
+
|
|
15
|
+
## 0.15.0 — 2026-09-11
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Add commerce-classified account-bound checkout handoff and purchase status tools**
|
|
20
|
+
|
|
9
21
|
## 0.14.0 — 2026-09-11
|
|
10
22
|
|
|
11
23
|
### Added
|
package/README.md
CHANGED
|
@@ -427,3 +427,7 @@ on the Change Date.
|
|
|
427
427
|
### Budgeted prepaid work
|
|
428
428
|
|
|
429
429
|
`budgetedMcpTool({ tool, execute })` adds a stable work ID, an explicit maximum-credit budget, and a `paid_access` commerce requirement. The executor must bind the account and use durable claims and settlement (for example `@absolutejs/billing/credit-work`). Only wrap tools whose effects and metering finish inside the execution scope. Deferred jobs need a durable budget handoff. Task-required, authorization-mapped, and already commerce-tagged tools are rejected rather than silently changing their enforcement contracts.
|
|
430
|
+
|
|
431
|
+
## Secure credit checkout
|
|
432
|
+
|
|
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).
|
package/changelog.json
CHANGED
|
@@ -1,32 +1,52 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
2
|
+
"contract": 1,
|
|
3
|
+
"name": "@absolutejs/mcp",
|
|
4
|
+
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.15.1",
|
|
7
|
+
"date": "2026-09-11",
|
|
8
|
+
"changes": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "fixed",
|
|
11
|
+
"summary": "Build and test before publishing so checkout exports are present in the distributed artifact"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"version": "0.15.0",
|
|
17
|
+
"date": "2026-09-11",
|
|
18
|
+
"changes": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "added",
|
|
21
|
+
"summary": "Add commerce-classified account-bound checkout handoff and purchase status tools"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"changes": [
|
|
27
|
+
{
|
|
28
|
+
"kind": "added",
|
|
29
|
+
"summary": "Add explicit credit-budget envelopes for durable prepaid MCP work"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"date": "2026-09-11",
|
|
33
|
+
"version": "0.14.0"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"changes": [
|
|
37
|
+
{
|
|
38
|
+
"kind": "added",
|
|
39
|
+
"summary": "Add reviewed host commerce eligibility, execution guards, and reusable credit status tools",
|
|
40
|
+
"symbols": [
|
|
41
|
+
"McpServerConfig",
|
|
42
|
+
"McpTool",
|
|
43
|
+
"evaluateCommerce",
|
|
44
|
+
"createCreditBalanceTool"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"date": "2026-09-11",
|
|
49
|
+
"version": "0.13.0"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
32
52
|
}
|
package/dist/commerce.js
CHANGED
|
@@ -59,6 +59,92 @@ var createCreditBalanceTool = (options) => ({
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
|
+
// src/checkoutTools.ts
|
|
63
|
+
var record = (input) => typeof input === "object" && input !== null && !Array.isArray(input);
|
|
64
|
+
var createCheckoutHandoffTool = (options) => ({
|
|
65
|
+
annotations: {
|
|
66
|
+
readOnlyHint: false,
|
|
67
|
+
destructiveHint: false,
|
|
68
|
+
openWorldHint: true,
|
|
69
|
+
title: "Open credit checkout"
|
|
70
|
+
},
|
|
71
|
+
commerce: { action: "external_checkout", categories: ["usage_credits"] },
|
|
72
|
+
description: "Prepare a short-lived credit-purchase link on the service website. The user reviews and explicitly pays there. Never send card data in chat. Does not charge a card or create a subscription.",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: { productId: { type: "string", minLength: 1, maxLength: 128 } },
|
|
76
|
+
required: ["productId"],
|
|
77
|
+
additionalProperties: false
|
|
78
|
+
},
|
|
79
|
+
handler: async (input) => {
|
|
80
|
+
if (!record(input) || Object.keys(input).length !== 1 || typeof input.productId !== "string" || !input.productId || input.productId.length > 128)
|
|
81
|
+
throw new Error("A productId is required");
|
|
82
|
+
const result = await options.issue(input.productId);
|
|
83
|
+
const url = new URL(result.url);
|
|
84
|
+
if (url.protocol !== "https:" || url.origin !== new URL(options.origin).origin || url.username || url.password || !Number.isFinite(Date.parse(result.expiresAt)))
|
|
85
|
+
throw new Error("Invalid checkout handoff");
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
text: `Review and pay on ${url.hostname}: ${url.href}. Expires ${result.expiresAt}. No payment has been made.`
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
structuredContent: {
|
|
94
|
+
purchaseId: result.purchaseId,
|
|
95
|
+
url: url.href,
|
|
96
|
+
expiresAt: result.expiresAt
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
var createPurchaseStatusTool = (options) => ({
|
|
102
|
+
annotations: {
|
|
103
|
+
readOnlyHint: true,
|
|
104
|
+
destructiveHint: false,
|
|
105
|
+
openWorldHint: false
|
|
106
|
+
},
|
|
107
|
+
commerce: { action: "entitlement_status", categories: ["usage_credits"] },
|
|
108
|
+
description: "Read this account's credit-purchase status. Available at zero balance. Does not initiate or retry payment.",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
purchaseId: { type: "string", minLength: 1, maxLength: 128 }
|
|
113
|
+
},
|
|
114
|
+
required: ["purchaseId"],
|
|
115
|
+
additionalProperties: false
|
|
116
|
+
},
|
|
117
|
+
handler: async (input) => {
|
|
118
|
+
if (!record(input) || Object.keys(input).length !== 1 || typeof input.purchaseId !== "string" || !input.purchaseId || input.purchaseId.length > 128)
|
|
119
|
+
throw new Error("A purchaseId is required");
|
|
120
|
+
const value = await options.read(input.purchaseId);
|
|
121
|
+
if (!value)
|
|
122
|
+
return "No purchase with that ID exists for this account.";
|
|
123
|
+
if (value.purchaseId !== input.purchaseId || ![
|
|
124
|
+
"not_started",
|
|
125
|
+
"pending",
|
|
126
|
+
"approved",
|
|
127
|
+
"declined",
|
|
128
|
+
"refunded",
|
|
129
|
+
"reconciliation"
|
|
130
|
+
].includes(value.status) || !Number.isSafeInteger(value.creditsGranted) || value.creditsGranted < 0)
|
|
131
|
+
throw new Error("Purchase status is unavailable");
|
|
132
|
+
const summary = {
|
|
133
|
+
purchaseId: value.purchaseId,
|
|
134
|
+
status: value.status,
|
|
135
|
+
creditsGranted: value.creditsGranted
|
|
136
|
+
};
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: `Purchase ${summary.status}; ${summary.creditsGranted} credits granted.`
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
structuredContent: summary
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
});
|
|
62
148
|
|
|
63
149
|
// src/commerce.ts
|
|
64
150
|
var COMMERCE_POLICY_VERSION = "2026-09-10.1";
|
|
@@ -168,6 +254,8 @@ var evaluateCommerce = (req, context, now = new Date) => {
|
|
|
168
254
|
export {
|
|
169
255
|
COMMERCE_POLICY_SOURCES,
|
|
170
256
|
COMMERCE_POLICY_VERSION,
|
|
257
|
+
createCheckoutHandoffTool,
|
|
171
258
|
createCreditBalanceTool,
|
|
259
|
+
createPurchaseStatusTool,
|
|
172
260
|
evaluateCommerce
|
|
173
261
|
};
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,92 @@ var createCreditBalanceTool = (options) => ({
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
|
+
// src/checkoutTools.ts
|
|
63
|
+
var record = (input) => typeof input === "object" && input !== null && !Array.isArray(input);
|
|
64
|
+
var createCheckoutHandoffTool = (options) => ({
|
|
65
|
+
annotations: {
|
|
66
|
+
readOnlyHint: false,
|
|
67
|
+
destructiveHint: false,
|
|
68
|
+
openWorldHint: true,
|
|
69
|
+
title: "Open credit checkout"
|
|
70
|
+
},
|
|
71
|
+
commerce: { action: "external_checkout", categories: ["usage_credits"] },
|
|
72
|
+
description: "Prepare a short-lived credit-purchase link on the service website. The user reviews and explicitly pays there. Never send card data in chat. Does not charge a card or create a subscription.",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: { productId: { type: "string", minLength: 1, maxLength: 128 } },
|
|
76
|
+
required: ["productId"],
|
|
77
|
+
additionalProperties: false
|
|
78
|
+
},
|
|
79
|
+
handler: async (input) => {
|
|
80
|
+
if (!record(input) || Object.keys(input).length !== 1 || typeof input.productId !== "string" || !input.productId || input.productId.length > 128)
|
|
81
|
+
throw new Error("A productId is required");
|
|
82
|
+
const result = await options.issue(input.productId);
|
|
83
|
+
const url = new URL(result.url);
|
|
84
|
+
if (url.protocol !== "https:" || url.origin !== new URL(options.origin).origin || url.username || url.password || !Number.isFinite(Date.parse(result.expiresAt)))
|
|
85
|
+
throw new Error("Invalid checkout handoff");
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
text: `Review and pay on ${url.hostname}: ${url.href}. Expires ${result.expiresAt}. No payment has been made.`
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
structuredContent: {
|
|
94
|
+
purchaseId: result.purchaseId,
|
|
95
|
+
url: url.href,
|
|
96
|
+
expiresAt: result.expiresAt
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
var createPurchaseStatusTool = (options) => ({
|
|
102
|
+
annotations: {
|
|
103
|
+
readOnlyHint: true,
|
|
104
|
+
destructiveHint: false,
|
|
105
|
+
openWorldHint: false
|
|
106
|
+
},
|
|
107
|
+
commerce: { action: "entitlement_status", categories: ["usage_credits"] },
|
|
108
|
+
description: "Read this account's credit-purchase status. Available at zero balance. Does not initiate or retry payment.",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
purchaseId: { type: "string", minLength: 1, maxLength: 128 }
|
|
113
|
+
},
|
|
114
|
+
required: ["purchaseId"],
|
|
115
|
+
additionalProperties: false
|
|
116
|
+
},
|
|
117
|
+
handler: async (input) => {
|
|
118
|
+
if (!record(input) || Object.keys(input).length !== 1 || typeof input.purchaseId !== "string" || !input.purchaseId || input.purchaseId.length > 128)
|
|
119
|
+
throw new Error("A purchaseId is required");
|
|
120
|
+
const value = await options.read(input.purchaseId);
|
|
121
|
+
if (!value)
|
|
122
|
+
return "No purchase with that ID exists for this account.";
|
|
123
|
+
if (value.purchaseId !== input.purchaseId || ![
|
|
124
|
+
"not_started",
|
|
125
|
+
"pending",
|
|
126
|
+
"approved",
|
|
127
|
+
"declined",
|
|
128
|
+
"refunded",
|
|
129
|
+
"reconciliation"
|
|
130
|
+
].includes(value.status) || !Number.isSafeInteger(value.creditsGranted) || value.creditsGranted < 0)
|
|
131
|
+
throw new Error("Purchase status is unavailable");
|
|
132
|
+
const summary = {
|
|
133
|
+
purchaseId: value.purchaseId,
|
|
134
|
+
status: value.status,
|
|
135
|
+
creditsGranted: value.creditsGranted
|
|
136
|
+
};
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: `Purchase ${summary.status}; ${summary.creditsGranted} credits granted.`
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
structuredContent: summary
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
});
|
|
62
148
|
|
|
63
149
|
// src/commerce.ts
|
|
64
150
|
var COMMERCE_POLICY_VERSION = "2026-09-10.1";
|
|
@@ -2008,6 +2094,7 @@ export {
|
|
|
2008
2094
|
MCP_LATEST_PROTOCOL_VERSION,
|
|
2009
2095
|
McpClientError,
|
|
2010
2096
|
budgetedMcpTool,
|
|
2097
|
+
createCheckoutHandoffTool,
|
|
2011
2098
|
createCreditBalanceTool,
|
|
2012
2099
|
createMcpAuthorizationRequest,
|
|
2013
2100
|
createMcpClient,
|
|
@@ -2017,6 +2104,7 @@ export {
|
|
|
2017
2104
|
createMemoryMcpTaskStore,
|
|
2018
2105
|
createPostgresMcpSessionStore,
|
|
2019
2106
|
createPostgresMcpTaskStore,
|
|
2107
|
+
createPurchaseStatusTool,
|
|
2020
2108
|
createSessionRegistry,
|
|
2021
2109
|
discoverMcpAuthorization,
|
|
2022
2110
|
dispatchMcp,
|
package/dist/manifest.js
CHANGED
|
@@ -2861,7 +2861,9 @@ var manifest = defineManifest()({
|
|
|
2861
2861
|
tagline: "Let AI assistants connect to your site and use its tools."
|
|
2862
2862
|
},
|
|
2863
2863
|
requires: {
|
|
2864
|
-
peers: [
|
|
2864
|
+
peers: [
|
|
2865
|
+
{ name: "elysia", range: "^2.0.0-beta.6", reason: "plugin host" }
|
|
2866
|
+
]
|
|
2865
2867
|
},
|
|
2866
2868
|
settings: Type.Object({
|
|
2867
2869
|
instructions: Type.Optional(Type.String({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { McpTool } from "./types";
|
|
2
|
+
export type McpPurchaseStatus = {
|
|
3
|
+
purchaseId: string;
|
|
4
|
+
status: "not_started" | "pending" | "approved" | "declined" | "refunded" | "reconciliation";
|
|
5
|
+
creditsGranted: number;
|
|
6
|
+
};
|
|
7
|
+
/** The issuer is bound to the authenticated account and canonical server pricing.
|
|
8
|
+
* Register only through the commerce guard. This tool never takes payment data. */
|
|
9
|
+
export declare const createCheckoutHandoffTool: (options: {
|
|
10
|
+
origin: string;
|
|
11
|
+
issue: (productId: string) => Promise<{
|
|
12
|
+
purchaseId: string;
|
|
13
|
+
url: string;
|
|
14
|
+
expiresAt: string;
|
|
15
|
+
}>;
|
|
16
|
+
}) => McpTool;
|
|
17
|
+
export declare const createPurchaseStatusTool: (options: {
|
|
18
|
+
read: (purchaseId: string) => Promise<McpPurchaseStatus | null>;
|
|
19
|
+
}) => McpTool;
|
package/dist/src/commerce.d.ts
CHANGED
|
@@ -48,3 +48,4 @@ export type CommerceDecision = {
|
|
|
48
48
|
* Unverified paths need explicit, fresh server-side review evidence. */
|
|
49
49
|
export declare const evaluateCommerce: (req: CommerceRequirement, context: CommerceContext, now?: Date) => CommerceDecision;
|
|
50
50
|
export { createCreditBalanceTool, type McpCreditBalance } from "./creditStatus";
|
|
51
|
+
export { createCheckoutHandoffTool, createPurchaseStatusTool, type McpPurchaseStatus, } from "./checkoutTools";
|
package/dist/src/index.d.ts
CHANGED
|
@@ -45,3 +45,4 @@ export type { McpAgencyOptions, McpAudioContent, McpElicitAnswer, McpElicitation
|
|
|
45
45
|
export * from "./commerce";
|
|
46
46
|
export { createCreditBalanceTool, type McpCreditBalance } from "./creditStatus";
|
|
47
47
|
export { budgetedMcpTool, type McpCreditWorkRequest } from "./budgetedTool";
|
|
48
|
+
export { createCheckoutHandoffTool, createPurchaseStatusTool, type McpPurchaseStatus, } from "./checkoutTools";
|
package/package.json
CHANGED
|
@@ -68,9 +68,9 @@
|
|
|
68
68
|
"release": "bun run format && bun run test && bun run build && bun publish",
|
|
69
69
|
"test": "bun test",
|
|
70
70
|
"typecheck": "tsc --noEmit --project tsconfig.json",
|
|
71
|
-
"check:package": "absolute-changelog check",
|
|
71
|
+
"check:package": "bun run typecheck && bun run test && bun run build && absolute-changelog check",
|
|
72
72
|
"prepublishOnly": "bun run check:package"
|
|
73
73
|
},
|
|
74
74
|
"types": "./dist/src/index.d.ts",
|
|
75
|
-
"version": "0.
|
|
75
|
+
"version": "0.15.1"
|
|
76
76
|
}
|