@absolutejs/mcp 0.15.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 +6 -0
- package/changelog.json +10 -0
- 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,12 @@ 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
|
+
|
|
9
15
|
## 0.15.0 — 2026-09-11
|
|
10
16
|
|
|
11
17
|
### Added
|
package/changelog.json
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
"contract": 1,
|
|
3
3
|
"name": "@absolutejs/mcp",
|
|
4
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
|
+
},
|
|
5
15
|
{
|
|
6
16
|
"version": "0.15.0",
|
|
7
17
|
"date": "2026-09-11",
|
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.15.
|
|
75
|
+
"version": "0.15.1"
|
|
76
76
|
}
|