agentpay-mcp 1.2.0 → 3.1.0
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/.env.example +37 -0
- package/LICENSE +21 -0
- package/README.md +380 -31
- package/claude_desktop_config.json +17 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/dist/session/manager.d.ts +90 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +262 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +113 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +16 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/deploy.d.ts +49 -0
- package/dist/tools/deploy.d.ts.map +1 -0
- package/dist/tools/deploy.js +123 -0
- package/dist/tools/deploy.js.map +1 -0
- package/dist/tools/history.d.ts +59 -0
- package/dist/tools/history.d.ts.map +1 -0
- package/dist/tools/history.js +202 -0
- package/dist/tools/history.js.map +1 -0
- package/dist/tools/payments.d.ts +71 -0
- package/dist/tools/payments.d.ts.map +1 -0
- package/dist/tools/payments.js +158 -0
- package/dist/tools/payments.js.map +1 -0
- package/dist/tools/session.d.ts +240 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +678 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/wallet.d.ts +107 -0
- package/dist/tools/wallet.d.ts.map +1 -0
- package/dist/tools/wallet.js +271 -0
- package/dist/tools/wallet.js.map +1 -0
- package/dist/tools/x402.d.ts +90 -0
- package/dist/tools/x402.d.ts.map +1 -0
- package/dist/tools/x402.js +268 -0
- package/dist/tools/x402.js.map +1 -0
- package/dist/utils/client.d.ts +46 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +123 -0
- package/dist/utils/client.js.map +1 -0
- package/dist/utils/format.d.ts +59 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +161 -0
- package/dist/utils/format.js.map +1 -0
- package/package.json +58 -12
- package/index.d.ts +0 -1
- package/index.js +0 -13
package/dist/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
/**
|
|
5
|
+
* AgentPay MCP Server — Entry Point
|
|
6
|
+
*
|
|
7
|
+
* Exposes Agent Wallet SDK tools via the Model Context Protocol (MCP).
|
|
8
|
+
* Compatible with Claude Desktop, Cursor, Windsurf, and any MCP client.
|
|
9
|
+
*
|
|
10
|
+
* v1.1.0 adds x402 V2 session payment support:
|
|
11
|
+
* - x402_session_start — pay once, receive a signed session token
|
|
12
|
+
* - x402_session_fetch — make N calls within a session (no new payments)
|
|
13
|
+
* - x402_session_status — inspect active sessions and TTL
|
|
14
|
+
* - x402_session_end — close a session explicitly
|
|
15
|
+
*
|
|
16
|
+
* Transport: stdio (standard MCP transport)
|
|
17
|
+
* Config: AGENT_PRIVATE_KEY + AGENT_WALLET_ADDRESS env vars required
|
|
18
|
+
*/
|
|
19
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
20
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
21
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
22
|
+
// ─── Tool imports (v1.0.0) ─────────────────────────────────────────────────
|
|
23
|
+
const deploy_js_1 = require("./tools/deploy.js");
|
|
24
|
+
const wallet_js_1 = require("./tools/wallet.js");
|
|
25
|
+
const wallet_js_2 = require("./tools/wallet.js");
|
|
26
|
+
const wallet_js_3 = require("./tools/wallet.js");
|
|
27
|
+
const payments_js_1 = require("./tools/payments.js");
|
|
28
|
+
const x402_js_1 = require("./tools/x402.js");
|
|
29
|
+
const history_js_1 = require("./tools/history.js");
|
|
30
|
+
// ─── Tool imports (v1.1.0 — x402 V2 session payments) ─────────────────────
|
|
31
|
+
const session_js_1 = require("./tools/session.js");
|
|
32
|
+
// ─── Server configuration ──────────────────────────────────────────────────
|
|
33
|
+
const SERVER_INFO = {
|
|
34
|
+
name: 'agentpay-mcp',
|
|
35
|
+
version: '1.1.0',
|
|
36
|
+
};
|
|
37
|
+
const SERVER_CAPABILITIES = {
|
|
38
|
+
tools: {},
|
|
39
|
+
};
|
|
40
|
+
// ─── Tool registry ─────────────────────────────────────────────────────────
|
|
41
|
+
const ALL_TOOLS = [
|
|
42
|
+
// v1.0.0 tools
|
|
43
|
+
deploy_js_1.deployWalletTool,
|
|
44
|
+
wallet_js_1.getWalletInfoTool,
|
|
45
|
+
payments_js_1.sendPaymentTool,
|
|
46
|
+
wallet_js_2.checkSpendLimitTool,
|
|
47
|
+
wallet_js_3.queueApprovalTool,
|
|
48
|
+
x402_js_1.x402PayTool,
|
|
49
|
+
history_js_1.getTransactionHistoryTool,
|
|
50
|
+
// v1.1.0 — x402 V2 session tools
|
|
51
|
+
session_js_1.x402SessionStartTool,
|
|
52
|
+
session_js_1.x402SessionFetchTool,
|
|
53
|
+
session_js_1.x402SessionStatusTool,
|
|
54
|
+
session_js_1.x402SessionEndTool,
|
|
55
|
+
];
|
|
56
|
+
// ─── Server initialization ─────────────────────────────────────────────────
|
|
57
|
+
const server = new index_js_1.Server(SERVER_INFO, {
|
|
58
|
+
capabilities: SERVER_CAPABILITIES,
|
|
59
|
+
});
|
|
60
|
+
// ─── List tools handler ────────────────────────────────────────────────────
|
|
61
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
62
|
+
return {
|
|
63
|
+
tools: ALL_TOOLS,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
// ─── Call tool handler ─────────────────────────────────────────────────────
|
|
67
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
68
|
+
const { name, arguments: args } = request.params;
|
|
69
|
+
try {
|
|
70
|
+
switch (name) {
|
|
71
|
+
// ── v1.0.0 tools ──────────────────────────────────────────────────
|
|
72
|
+
case 'deploy_wallet': {
|
|
73
|
+
const input = deploy_js_1.DeployWalletSchema.parse(args);
|
|
74
|
+
return (0, deploy_js_1.handleDeployWallet)(input);
|
|
75
|
+
}
|
|
76
|
+
case 'get_wallet_info': {
|
|
77
|
+
const input = wallet_js_1.GetWalletInfoSchema.parse(args ?? {});
|
|
78
|
+
return (0, wallet_js_1.handleGetWalletInfo)(input);
|
|
79
|
+
}
|
|
80
|
+
case 'send_payment': {
|
|
81
|
+
const input = payments_js_1.SendPaymentSchema.parse(args);
|
|
82
|
+
return (0, payments_js_1.handleSendPayment)(input);
|
|
83
|
+
}
|
|
84
|
+
case 'check_spend_limit': {
|
|
85
|
+
const input = wallet_js_2.CheckSpendLimitSchema.parse(args);
|
|
86
|
+
return (0, wallet_js_2.handleCheckSpendLimit)(input);
|
|
87
|
+
}
|
|
88
|
+
case 'queue_approval': {
|
|
89
|
+
const input = wallet_js_3.QueueApprovalSchema.parse(args);
|
|
90
|
+
return (0, wallet_js_3.handleQueueApproval)(input);
|
|
91
|
+
}
|
|
92
|
+
case 'x402_pay': {
|
|
93
|
+
const input = x402_js_1.X402PaySchema.parse(args);
|
|
94
|
+
return (0, x402_js_1.handleX402Pay)(input);
|
|
95
|
+
}
|
|
96
|
+
case 'get_transaction_history': {
|
|
97
|
+
const input = history_js_1.GetTransactionHistorySchema.parse(args ?? {});
|
|
98
|
+
return (0, history_js_1.handleGetTransactionHistory)(input);
|
|
99
|
+
}
|
|
100
|
+
// ── v1.1.0 — x402 V2 session tools ───────────────────────────────
|
|
101
|
+
case 'x402_session_start': {
|
|
102
|
+
const input = session_js_1.X402SessionStartSchema.parse(args);
|
|
103
|
+
return (0, session_js_1.handleX402SessionStart)(input);
|
|
104
|
+
}
|
|
105
|
+
case 'x402_session_fetch': {
|
|
106
|
+
const input = session_js_1.X402SessionFetchSchema.parse(args);
|
|
107
|
+
return (0, session_js_1.handleX402SessionFetch)(input);
|
|
108
|
+
}
|
|
109
|
+
case 'x402_session_status': {
|
|
110
|
+
const input = session_js_1.X402SessionStatusSchema.parse(args ?? {});
|
|
111
|
+
return (0, session_js_1.handleX402SessionStatus)(input);
|
|
112
|
+
}
|
|
113
|
+
case 'x402_session_end': {
|
|
114
|
+
const input = session_js_1.X402SessionEndSchema.parse(args);
|
|
115
|
+
return (0, session_js_1.handleX402SessionEnd)(input);
|
|
116
|
+
}
|
|
117
|
+
default:
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: 'text',
|
|
122
|
+
text: `❌ Unknown tool: "${name}". Available tools: ${ALL_TOOLS.map(t => t.name).join(', ')}`,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
isError: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: 'text',
|
|
135
|
+
text: `❌ Tool "${name}" failed: ${message}`,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
isError: true,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
// ─── Start server ──────────────────────────────────────────────────────────
|
|
143
|
+
async function main() {
|
|
144
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
145
|
+
// Graceful shutdown
|
|
146
|
+
process.on('SIGINT', async () => {
|
|
147
|
+
await server.close();
|
|
148
|
+
process.exit(0);
|
|
149
|
+
});
|
|
150
|
+
process.on('SIGTERM', async () => {
|
|
151
|
+
await server.close();
|
|
152
|
+
process.exit(0);
|
|
153
|
+
});
|
|
154
|
+
await server.connect(transport);
|
|
155
|
+
// Log to stderr (not stdout — stdout is reserved for MCP protocol)
|
|
156
|
+
process.stderr.write(`AgentPay MCP v1.1.0 started. ` +
|
|
157
|
+
`Wallet: ${process.env['AGENT_WALLET_ADDRESS'] ?? '(not configured)'} | ` +
|
|
158
|
+
`Chain: ${process.env['CHAIN_ID'] ?? '8453 (Base Mainnet)'} | ` +
|
|
159
|
+
`Session TTL: ${process.env['SESSION_TTL_SECONDS'] ?? '3600'}s\n`);
|
|
160
|
+
}
|
|
161
|
+
main().catch((error) => {
|
|
162
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
163
|
+
process.stderr.write(`Fatal error starting AgentPay MCP: ${msg}\n`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session/manager.ts — x402 V2 session lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* This module implements the "wallet-based access & reusable sessions" concept
|
|
5
|
+
* introduced in x402 V2. Agents pay once to establish a cryptographically
|
|
6
|
+
* authenticated session, then make N subsequent calls without additional
|
|
7
|
+
* on-chain transactions.
|
|
8
|
+
*
|
|
9
|
+
* Non-custodial design:
|
|
10
|
+
* - Session tokens are signed locally by the agent's private key
|
|
11
|
+
* - No third party holds or validates keys
|
|
12
|
+
* - Servers receive a self-contained signed token they can independently verify
|
|
13
|
+
* - The SessionManager has zero knowledge of private keys; it only receives
|
|
14
|
+
* a signMessage callback injected at creation time
|
|
15
|
+
*
|
|
16
|
+
* Token format:
|
|
17
|
+
* X-Session-Token: <base64url(JSON payload)>.<hex signature>
|
|
18
|
+
* Compatible with x402 V2 SIGN-IN-WITH-X (SIWx) header pattern
|
|
19
|
+
* Servers can ecrecover the wallet address without any external service
|
|
20
|
+
*/
|
|
21
|
+
import type { SessionRecord, SessionTokenPayload, CreateSessionOptions, SessionLookupResult } from './types.js';
|
|
22
|
+
/**
|
|
23
|
+
* HTTP header name for session tokens.
|
|
24
|
+
* x402 V2 uses modernised header names (no X- prefix per IETF conventions
|
|
25
|
+
* for new standard headers). We use PAYMENT-SESSION for the session token
|
|
26
|
+
* and retain X-Session-Token as an alias for broad compatibility.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SESSION_TOKEN_HEADER = "X-Session-Token";
|
|
29
|
+
export declare const SESSION_WALLET_HEADER = "X-Session-Wallet";
|
|
30
|
+
export declare const PAYMENT_SESSION_HEADER = "PAYMENT-SESSION";
|
|
31
|
+
/**
|
|
32
|
+
* Create a new session after a successful x402 payment.
|
|
33
|
+
*
|
|
34
|
+
* Signs a canonical token payload with the agent's private key, creating
|
|
35
|
+
* a self-verifiable session token that servers can use to grant access
|
|
36
|
+
* without requiring a new on-chain payment.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createSession(opts: CreateSessionOptions): Promise<SessionRecord>;
|
|
39
|
+
/**
|
|
40
|
+
* Look up a session by ID.
|
|
41
|
+
* Returns the record and whether it has expired.
|
|
42
|
+
*/
|
|
43
|
+
export declare function lookupSession(sessionId: string): SessionLookupResult;
|
|
44
|
+
/**
|
|
45
|
+
* Record a call made within a session.
|
|
46
|
+
* Updates callCount and lastUsedAt in-place.
|
|
47
|
+
*/
|
|
48
|
+
export declare function recordSessionCall(sessionId: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Explicitly end a session (mark as expired by setting expiresAt to past).
|
|
51
|
+
* Returns true if the session was found and ended.
|
|
52
|
+
*/
|
|
53
|
+
export declare function endSession(sessionId: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* List all active (non-expired) sessions.
|
|
56
|
+
*/
|
|
57
|
+
export declare function listActiveSessions(): SessionRecord[];
|
|
58
|
+
/**
|
|
59
|
+
* List all sessions (including expired).
|
|
60
|
+
*/
|
|
61
|
+
export declare function listAllSessions(): SessionRecord[];
|
|
62
|
+
/**
|
|
63
|
+
* Find the best matching active session for a given URL.
|
|
64
|
+
* Prefers exact-scope matches over prefix-scope.
|
|
65
|
+
* Used to auto-attach a session to x402_pay when available.
|
|
66
|
+
*/
|
|
67
|
+
export declare function findSessionForUrl(url: string): SessionRecord | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Build the HTTP headers to include in a session-authenticated request.
|
|
70
|
+
* These headers are inspired by x402 V2's SIGN-IN-WITH-X (SIWx) pattern
|
|
71
|
+
* and the PAYMENT-SESSION header spec.
|
|
72
|
+
*/
|
|
73
|
+
export declare function buildSessionHeaders(session: SessionRecord): Record<string, string>;
|
|
74
|
+
/**
|
|
75
|
+
* Decode a session token string into its payload and signature.
|
|
76
|
+
* Useful for display / debugging purposes.
|
|
77
|
+
*/
|
|
78
|
+
export declare function decodeSessionToken(token: string): {
|
|
79
|
+
payload: SessionTokenPayload;
|
|
80
|
+
signature: string;
|
|
81
|
+
} | null;
|
|
82
|
+
/**
|
|
83
|
+
* Get total sessions count (active + expired).
|
|
84
|
+
*/
|
|
85
|
+
export declare function getStoreSize(): number;
|
|
86
|
+
/**
|
|
87
|
+
* Clear all sessions — for testing only.
|
|
88
|
+
*/
|
|
89
|
+
export declare function _clearAllSessions(): void;
|
|
90
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAOpB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AACxD,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAexD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkDtF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,CAQpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,aAAa,EAAE,CAIpD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,aAAa,EAAE,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAexE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMlF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IACjD,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAcP;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* session/manager.ts — x402 V2 session lifecycle management.
|
|
4
|
+
*
|
|
5
|
+
* This module implements the "wallet-based access & reusable sessions" concept
|
|
6
|
+
* introduced in x402 V2. Agents pay once to establish a cryptographically
|
|
7
|
+
* authenticated session, then make N subsequent calls without additional
|
|
8
|
+
* on-chain transactions.
|
|
9
|
+
*
|
|
10
|
+
* Non-custodial design:
|
|
11
|
+
* - Session tokens are signed locally by the agent's private key
|
|
12
|
+
* - No third party holds or validates keys
|
|
13
|
+
* - Servers receive a self-contained signed token they can independently verify
|
|
14
|
+
* - The SessionManager has zero knowledge of private keys; it only receives
|
|
15
|
+
* a signMessage callback injected at creation time
|
|
16
|
+
*
|
|
17
|
+
* Token format:
|
|
18
|
+
* X-Session-Token: <base64url(JSON payload)>.<hex signature>
|
|
19
|
+
* Compatible with x402 V2 SIGN-IN-WITH-X (SIWx) header pattern
|
|
20
|
+
* Servers can ecrecover the wallet address without any external service
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.PAYMENT_SESSION_HEADER = exports.SESSION_WALLET_HEADER = exports.SESSION_TOKEN_HEADER = void 0;
|
|
24
|
+
exports.createSession = createSession;
|
|
25
|
+
exports.lookupSession = lookupSession;
|
|
26
|
+
exports.recordSessionCall = recordSessionCall;
|
|
27
|
+
exports.endSession = endSession;
|
|
28
|
+
exports.listActiveSessions = listActiveSessions;
|
|
29
|
+
exports.listAllSessions = listAllSessions;
|
|
30
|
+
exports.findSessionForUrl = findSessionForUrl;
|
|
31
|
+
exports.buildSessionHeaders = buildSessionHeaders;
|
|
32
|
+
exports.decodeSessionToken = decodeSessionToken;
|
|
33
|
+
exports.getStoreSize = getStoreSize;
|
|
34
|
+
exports._clearAllSessions = _clearAllSessions;
|
|
35
|
+
const crypto_1 = require("crypto");
|
|
36
|
+
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
37
|
+
/** Default session TTL in seconds (1 hour) */
|
|
38
|
+
const DEFAULT_TTL_SECONDS = 3600;
|
|
39
|
+
/**
|
|
40
|
+
* HTTP header name for session tokens.
|
|
41
|
+
* x402 V2 uses modernised header names (no X- prefix per IETF conventions
|
|
42
|
+
* for new standard headers). We use PAYMENT-SESSION for the session token
|
|
43
|
+
* and retain X-Session-Token as an alias for broad compatibility.
|
|
44
|
+
*/
|
|
45
|
+
exports.SESSION_TOKEN_HEADER = 'X-Session-Token';
|
|
46
|
+
exports.SESSION_WALLET_HEADER = 'X-Session-Wallet';
|
|
47
|
+
exports.PAYMENT_SESSION_HEADER = 'PAYMENT-SESSION';
|
|
48
|
+
// ─── Session store ─────────────────────────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* In-memory session store. Sessions survive within the MCP server process
|
|
51
|
+
* lifetime (typically as long as the AI client has the server running).
|
|
52
|
+
*
|
|
53
|
+
* Key: sessionId (UUIDv4)
|
|
54
|
+
* Value: SessionRecord
|
|
55
|
+
*/
|
|
56
|
+
const store = new Map();
|
|
57
|
+
// ─── Public API ────────────────────────────────────────────────────────────
|
|
58
|
+
/**
|
|
59
|
+
* Create a new session after a successful x402 payment.
|
|
60
|
+
*
|
|
61
|
+
* Signs a canonical token payload with the agent's private key, creating
|
|
62
|
+
* a self-verifiable session token that servers can use to grant access
|
|
63
|
+
* without requiring a new on-chain payment.
|
|
64
|
+
*/
|
|
65
|
+
async function createSession(opts) {
|
|
66
|
+
const sessionId = (0, crypto_1.randomUUID)();
|
|
67
|
+
const now = Math.floor(Date.now() / 1000);
|
|
68
|
+
const ttl = opts.ttlSeconds ?? parseTtlFromEnv();
|
|
69
|
+
const expiresAt = now + ttl;
|
|
70
|
+
const payload = {
|
|
71
|
+
version: 'clawpay/1.1',
|
|
72
|
+
sessionId,
|
|
73
|
+
walletAddress: opts.walletAddress,
|
|
74
|
+
endpoint: opts.endpoint,
|
|
75
|
+
scope: opts.scope ?? 'prefix',
|
|
76
|
+
createdAt: now,
|
|
77
|
+
expiresAt,
|
|
78
|
+
paymentTxHash: opts.paymentTxHash,
|
|
79
|
+
paymentAmount: opts.paymentAmount.toString(),
|
|
80
|
+
};
|
|
81
|
+
// Deterministic canonical JSON (keys sorted alphabetically)
|
|
82
|
+
const canonicalPayload = canonicalise(payload);
|
|
83
|
+
const payloadB64 = Buffer.from(canonicalPayload).toString('base64url');
|
|
84
|
+
// Sign with agent's private key — non-custodial, local only
|
|
85
|
+
const signature = await opts.signMessage(canonicalPayload);
|
|
86
|
+
// Combined token: base64url(payload).hexSignature
|
|
87
|
+
const sessionToken = `${payloadB64}.${signature}`;
|
|
88
|
+
const record = {
|
|
89
|
+
sessionId,
|
|
90
|
+
endpoint: opts.endpoint,
|
|
91
|
+
scope: opts.scope ?? 'prefix',
|
|
92
|
+
walletAddress: opts.walletAddress,
|
|
93
|
+
createdAt: now,
|
|
94
|
+
expiresAt,
|
|
95
|
+
paymentTxHash: opts.paymentTxHash,
|
|
96
|
+
paymentAmount: opts.paymentAmount.toString(),
|
|
97
|
+
paymentToken: opts.paymentToken,
|
|
98
|
+
paymentRecipient: opts.paymentRecipient,
|
|
99
|
+
sessionToken,
|
|
100
|
+
signature,
|
|
101
|
+
label: opts.label,
|
|
102
|
+
callCount: 0,
|
|
103
|
+
lastUsedAt: now,
|
|
104
|
+
};
|
|
105
|
+
store.set(sessionId, record);
|
|
106
|
+
pruneExpired();
|
|
107
|
+
return record;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Look up a session by ID.
|
|
111
|
+
* Returns the record and whether it has expired.
|
|
112
|
+
*/
|
|
113
|
+
function lookupSession(sessionId) {
|
|
114
|
+
const session = store.get(sessionId);
|
|
115
|
+
if (!session)
|
|
116
|
+
return { found: false };
|
|
117
|
+
const now = Math.floor(Date.now() / 1000);
|
|
118
|
+
const expired = now >= session.expiresAt;
|
|
119
|
+
return { found: true, session, expired };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Record a call made within a session.
|
|
123
|
+
* Updates callCount and lastUsedAt in-place.
|
|
124
|
+
*/
|
|
125
|
+
function recordSessionCall(sessionId) {
|
|
126
|
+
const session = store.get(sessionId);
|
|
127
|
+
if (!session)
|
|
128
|
+
return;
|
|
129
|
+
// Mutate callCount and lastUsedAt (the only mutable fields)
|
|
130
|
+
const mutable = session;
|
|
131
|
+
mutable.callCount += 1;
|
|
132
|
+
mutable.lastUsedAt = Math.floor(Date.now() / 1000);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Explicitly end a session (mark as expired by setting expiresAt to past).
|
|
136
|
+
* Returns true if the session was found and ended.
|
|
137
|
+
*/
|
|
138
|
+
function endSession(sessionId) {
|
|
139
|
+
const session = store.get(sessionId);
|
|
140
|
+
if (!session)
|
|
141
|
+
return false;
|
|
142
|
+
// Force-expire it
|
|
143
|
+
const mutable = session;
|
|
144
|
+
mutable.expiresAt = 0;
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* List all active (non-expired) sessions.
|
|
149
|
+
*/
|
|
150
|
+
function listActiveSessions() {
|
|
151
|
+
pruneExpired();
|
|
152
|
+
const now = Math.floor(Date.now() / 1000);
|
|
153
|
+
return Array.from(store.values()).filter((s) => s.expiresAt > now);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* List all sessions (including expired).
|
|
157
|
+
*/
|
|
158
|
+
function listAllSessions() {
|
|
159
|
+
return Array.from(store.values());
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Find the best matching active session for a given URL.
|
|
163
|
+
* Prefers exact-scope matches over prefix-scope.
|
|
164
|
+
* Used to auto-attach a session to x402_pay when available.
|
|
165
|
+
*/
|
|
166
|
+
function findSessionForUrl(url) {
|
|
167
|
+
const now = Math.floor(Date.now() / 1000);
|
|
168
|
+
// Collect all valid sessions
|
|
169
|
+
const active = Array.from(store.values()).filter((s) => s.expiresAt > now);
|
|
170
|
+
// Try exact match first
|
|
171
|
+
const exact = active.find((s) => s.scope === 'exact' && s.endpoint === url);
|
|
172
|
+
if (exact)
|
|
173
|
+
return exact;
|
|
174
|
+
// Try prefix match
|
|
175
|
+
const prefix = active.find((s) => s.scope === 'prefix' && url.startsWith(s.endpoint));
|
|
176
|
+
if (prefix)
|
|
177
|
+
return prefix;
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Build the HTTP headers to include in a session-authenticated request.
|
|
182
|
+
* These headers are inspired by x402 V2's SIGN-IN-WITH-X (SIWx) pattern
|
|
183
|
+
* and the PAYMENT-SESSION header spec.
|
|
184
|
+
*/
|
|
185
|
+
function buildSessionHeaders(session) {
|
|
186
|
+
return {
|
|
187
|
+
[exports.SESSION_TOKEN_HEADER]: session.sessionToken,
|
|
188
|
+
[exports.SESSION_WALLET_HEADER]: session.walletAddress,
|
|
189
|
+
[exports.PAYMENT_SESSION_HEADER]: session.sessionId,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Decode a session token string into its payload and signature.
|
|
194
|
+
* Useful for display / debugging purposes.
|
|
195
|
+
*/
|
|
196
|
+
function decodeSessionToken(token) {
|
|
197
|
+
const dotIdx = token.lastIndexOf('.');
|
|
198
|
+
if (dotIdx === -1)
|
|
199
|
+
return null;
|
|
200
|
+
const payloadB64 = token.slice(0, dotIdx);
|
|
201
|
+
const signature = token.slice(dotIdx + 1);
|
|
202
|
+
try {
|
|
203
|
+
const payloadJson = Buffer.from(payloadB64, 'base64url').toString('utf-8');
|
|
204
|
+
const payload = JSON.parse(payloadJson);
|
|
205
|
+
return { payload, signature };
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get total sessions count (active + expired).
|
|
213
|
+
*/
|
|
214
|
+
function getStoreSize() {
|
|
215
|
+
return store.size;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Clear all sessions — for testing only.
|
|
219
|
+
*/
|
|
220
|
+
function _clearAllSessions() {
|
|
221
|
+
store.clear();
|
|
222
|
+
}
|
|
223
|
+
// ─── Internal helpers ──────────────────────────────────────────────────────
|
|
224
|
+
/**
|
|
225
|
+
* Produce a deterministic canonical JSON representation.
|
|
226
|
+
* Keys are sorted alphabetically to ensure signing is reproducible.
|
|
227
|
+
*/
|
|
228
|
+
function canonicalise(obj) {
|
|
229
|
+
const sorted = Object.keys(obj)
|
|
230
|
+
.sort()
|
|
231
|
+
.reduce((acc, key) => {
|
|
232
|
+
acc[key] = obj[key];
|
|
233
|
+
return acc;
|
|
234
|
+
}, {});
|
|
235
|
+
return JSON.stringify(sorted);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Remove expired sessions from the store.
|
|
239
|
+
* Called automatically on create and list operations.
|
|
240
|
+
*/
|
|
241
|
+
function pruneExpired() {
|
|
242
|
+
const now = Math.floor(Date.now() / 1000);
|
|
243
|
+
for (const [id, session] of store.entries()) {
|
|
244
|
+
if (session.expiresAt <= now) {
|
|
245
|
+
store.delete(id);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Parse session TTL from environment variable.
|
|
251
|
+
*/
|
|
252
|
+
function parseTtlFromEnv() {
|
|
253
|
+
const raw = process.env['SESSION_TTL_SECONDS'];
|
|
254
|
+
if (!raw)
|
|
255
|
+
return DEFAULT_TTL_SECONDS;
|
|
256
|
+
const parsed = parseInt(raw, 10);
|
|
257
|
+
if (isNaN(parsed) || parsed <= 0)
|
|
258
|
+
return DEFAULT_TTL_SECONDS;
|
|
259
|
+
// Cap at 30 days
|
|
260
|
+
return Math.min(parsed, 86400 * 30);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session/types.ts — Type definitions for x402 V2 session management.
|
|
3
|
+
*
|
|
4
|
+
* x402 V2 introduced the concept of "wallet-based access & reusable sessions":
|
|
5
|
+
* agents pay once to establish a session, then skip on-chain payment on every
|
|
6
|
+
* subsequent call within that session. This module defines the data structures
|
|
7
|
+
* that AgentPay MCP uses to implement this pattern non-custodially.
|
|
8
|
+
*
|
|
9
|
+
* Reference: https://www.x402.org/writing/x402-v2-launch
|
|
10
|
+
* "V2 protocol now includes the logic to support wallet-controlled sessions,
|
|
11
|
+
* allowing clients to skip the full payment flow for repeated access if the
|
|
12
|
+
* resource was previously purchased."
|
|
13
|
+
*/
|
|
14
|
+
export interface SessionRecord {
|
|
15
|
+
/** Unique session identifier (UUIDv4) */
|
|
16
|
+
readonly sessionId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Base URL this session covers.
|
|
19
|
+
* All requests to URLs matching this prefix (or exact URL) are included.
|
|
20
|
+
*/
|
|
21
|
+
readonly endpoint: string;
|
|
22
|
+
/**
|
|
23
|
+
* Scope of the session:
|
|
24
|
+
* - "prefix": covers all paths under the endpoint (e.g., all of api.example.com/v1/*)
|
|
25
|
+
* - "exact": covers only the single URL that was paid for
|
|
26
|
+
*/
|
|
27
|
+
readonly scope: 'prefix' | 'exact';
|
|
28
|
+
/** Wallet address that owns this session (from AGENT_WALLET_ADDRESS) */
|
|
29
|
+
readonly walletAddress: string;
|
|
30
|
+
/** Unix timestamp (seconds) when the session was created */
|
|
31
|
+
readonly createdAt: number;
|
|
32
|
+
/** Unix timestamp (seconds) when the session expires */
|
|
33
|
+
readonly expiresAt: number;
|
|
34
|
+
/** On-chain transaction hash of the initial session payment */
|
|
35
|
+
readonly paymentTxHash: string;
|
|
36
|
+
/** Amount paid (in base units / wei) as a string-encoded bigint */
|
|
37
|
+
readonly paymentAmount: string;
|
|
38
|
+
/** Token address that was paid (zero address = native ETH) */
|
|
39
|
+
readonly paymentToken: string;
|
|
40
|
+
/** Recipient address of the initial payment */
|
|
41
|
+
readonly paymentRecipient: string;
|
|
42
|
+
/**
|
|
43
|
+
* Cryptographic session token.
|
|
44
|
+
* Base64url-encoded JSON payload signed by the agent's private key using
|
|
45
|
+
* secp256k1 ECDSA (viem signMessage). Presented to servers as the
|
|
46
|
+
* X-Session-Token header — compatible with x402 V2's SIGN-IN-WITH-X pattern.
|
|
47
|
+
*/
|
|
48
|
+
readonly sessionToken: string;
|
|
49
|
+
/**
|
|
50
|
+
* ECDSA signature over the token payload.
|
|
51
|
+
* Servers can verify ownership of walletAddress without any custody.
|
|
52
|
+
*/
|
|
53
|
+
readonly signature: string;
|
|
54
|
+
/**
|
|
55
|
+
* Human-readable label for this session (optional, set by caller).
|
|
56
|
+
*/
|
|
57
|
+
readonly label?: string;
|
|
58
|
+
/** Number of requests made within this session */
|
|
59
|
+
callCount: number;
|
|
60
|
+
/** Last request timestamp (Unix seconds) */
|
|
61
|
+
lastUsedAt: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Canonical payload signed by the agent wallet.
|
|
65
|
+
* This is serialised to a deterministic JSON string before signing.
|
|
66
|
+
* Servers that implement x402 V2 session verification can reconstruct this
|
|
67
|
+
* and call `ecrecover` / viem's `verifyMessage` to confirm wallet identity.
|
|
68
|
+
*/
|
|
69
|
+
export interface SessionTokenPayload {
|
|
70
|
+
/** Protocol version marker */
|
|
71
|
+
version: 'clawpay/1.1';
|
|
72
|
+
sessionId: string;
|
|
73
|
+
walletAddress: string;
|
|
74
|
+
endpoint: string;
|
|
75
|
+
scope: 'prefix' | 'exact';
|
|
76
|
+
createdAt: number;
|
|
77
|
+
expiresAt: number;
|
|
78
|
+
paymentTxHash: string;
|
|
79
|
+
paymentAmount: string;
|
|
80
|
+
}
|
|
81
|
+
export interface CreateSessionOptions {
|
|
82
|
+
endpoint: string;
|
|
83
|
+
scope?: 'prefix' | 'exact';
|
|
84
|
+
ttlSeconds?: number;
|
|
85
|
+
label?: string;
|
|
86
|
+
paymentTxHash: string;
|
|
87
|
+
paymentAmount: bigint;
|
|
88
|
+
paymentToken: string;
|
|
89
|
+
paymentRecipient: string;
|
|
90
|
+
walletAddress: string;
|
|
91
|
+
/** viem signMessage function — must match walletAddress */
|
|
92
|
+
signMessage: (message: string) => Promise<string>;
|
|
93
|
+
}
|
|
94
|
+
export type SessionLookupResult = {
|
|
95
|
+
found: true;
|
|
96
|
+
session: SessionRecord;
|
|
97
|
+
expired: false;
|
|
98
|
+
} | {
|
|
99
|
+
found: true;
|
|
100
|
+
session: SessionRecord;
|
|
101
|
+
expired: true;
|
|
102
|
+
} | {
|
|
103
|
+
found: false;
|
|
104
|
+
};
|
|
105
|
+
export interface SessionFetchOptions {
|
|
106
|
+
sessionId: string;
|
|
107
|
+
url: string;
|
|
108
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
109
|
+
headers?: Record<string, string>;
|
|
110
|
+
body?: string;
|
|
111
|
+
timeoutMs?: number;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/session/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEnC,wEAAwE;IACxE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,+CAA+C;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,OAAO,EAAE,aAAa,CAAC;IAEvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;AAID,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,GACvD;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GACtD;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAIrB,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|