@haven_ai/mcp 0.3.0-alpha.0 → 0.5.0-alpha.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/dist/cli.cjs +55 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +56 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +55 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +102 -4
- package/dist/index.d.ts +102 -4
- package/dist/index.js +56 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { HavenClient } from '@haven_ai/sdk';
|
|
2
|
+
import { HavenClientUpdate, HavenClient } from '@haven_ai/sdk';
|
|
3
3
|
import { z } from 'zod/v3';
|
|
4
4
|
|
|
5
5
|
interface HavenCredentialFile {
|
|
@@ -67,7 +67,79 @@ declare function loadCredentials(source?: string | HavenCredentialSource | undef
|
|
|
67
67
|
*/
|
|
68
68
|
|
|
69
69
|
type HavenMcpToolName = 'haven_send' | 'haven_pay_mcp_tool' | 'haven_quote_x402' | 'haven_pay_x402_quote' | 'haven_pay_x402' | 'haven_resume_x402_payment' | 'haven_get_payment_status' | 'haven_get_resume_state' | 'haven_get_agent' | 'haven_get_allowances' | 'haven_list_receipts' | 'haven_verify_receipt' | 'haven_sweep_delegate' | 'haven_discover_tools' | 'haven_submit_catalog_entry';
|
|
70
|
-
declare const toolSchemas:
|
|
70
|
+
declare const toolSchemas: {
|
|
71
|
+
readonly haven_send: {
|
|
72
|
+
readonly asset: z.ZodEnum<["ETH", "USDC"]>;
|
|
73
|
+
readonly recipient: z.ZodString;
|
|
74
|
+
readonly amount: z.ZodString;
|
|
75
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
76
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
77
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
78
|
+
};
|
|
79
|
+
readonly haven_pay_mcp_tool: {
|
|
80
|
+
readonly merchant_url: z.ZodString;
|
|
81
|
+
readonly tool_name: z.ZodString;
|
|
82
|
+
readonly arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
83
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
84
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
85
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
86
|
+
};
|
|
87
|
+
readonly haven_quote_x402: {
|
|
88
|
+
readonly url: z.ZodString;
|
|
89
|
+
readonly method: z.ZodOptional<z.ZodString>;
|
|
90
|
+
readonly headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
91
|
+
readonly body: z.ZodOptional<z.ZodString>;
|
|
92
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
93
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
94
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
95
|
+
};
|
|
96
|
+
readonly haven_pay_x402_quote: {
|
|
97
|
+
readonly quote: z.ZodUnknown;
|
|
98
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
99
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
100
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
101
|
+
};
|
|
102
|
+
readonly haven_pay_x402: {
|
|
103
|
+
readonly url: z.ZodString;
|
|
104
|
+
readonly method: z.ZodOptional<z.ZodString>;
|
|
105
|
+
readonly headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
106
|
+
readonly body: z.ZodOptional<z.ZodString>;
|
|
107
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
108
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
109
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
110
|
+
};
|
|
111
|
+
readonly haven_resume_x402_payment: {
|
|
112
|
+
readonly payment_id: z.ZodOptional<z.ZodString>;
|
|
113
|
+
readonly resume_state: z.ZodOptional<z.ZodUnknown>;
|
|
114
|
+
};
|
|
115
|
+
readonly haven_get_payment_status: {
|
|
116
|
+
readonly payment_id: z.ZodString;
|
|
117
|
+
};
|
|
118
|
+
readonly haven_get_resume_state: {
|
|
119
|
+
readonly payment_id: z.ZodString;
|
|
120
|
+
};
|
|
121
|
+
readonly haven_get_agent: {};
|
|
122
|
+
readonly haven_get_allowances: {};
|
|
123
|
+
readonly haven_sweep_delegate: {};
|
|
124
|
+
readonly haven_discover_tools: {
|
|
125
|
+
readonly category: z.ZodOptional<z.ZodString>;
|
|
126
|
+
readonly search: z.ZodOptional<z.ZodString>;
|
|
127
|
+
readonly rail: z.ZodOptional<z.ZodEnum<["x402", "mpp"]>>;
|
|
128
|
+
readonly verified: z.ZodOptional<z.ZodEnum<["any", "verified", "operator"]>>;
|
|
129
|
+
};
|
|
130
|
+
readonly haven_submit_catalog_entry: {
|
|
131
|
+
readonly resource_url: z.ZodString;
|
|
132
|
+
readonly website: z.ZodOptional<z.ZodString>;
|
|
133
|
+
};
|
|
134
|
+
readonly haven_list_receipts: {
|
|
135
|
+
readonly limit: z.ZodOptional<z.ZodNumber>;
|
|
136
|
+
/** #3128: the previous page's next_cursor (a receipt id). */
|
|
137
|
+
readonly cursor: z.ZodOptional<z.ZodString>;
|
|
138
|
+
};
|
|
139
|
+
readonly haven_verify_receipt: {
|
|
140
|
+
readonly receipt: z.ZodUnknown;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
71
143
|
/**
|
|
72
144
|
* MCP tool descriptions, composed from the shared semantic source in
|
|
73
145
|
* `@haven_ai/sdk`'s `tool-descriptions.ts`. Keeping both the SDK tool-calling
|
|
@@ -87,6 +159,12 @@ interface ToolSuccess<T> {
|
|
|
87
159
|
* leave, which is how `idempotencyKey` survived #2312 and #2348.
|
|
88
160
|
*/
|
|
89
161
|
warnings?: string[];
|
|
162
|
+
/**
|
|
163
|
+
* #3303: the backend's `client_update` hint when this package is behind the
|
|
164
|
+
* version the deployment recommends (`required: false`) or below its
|
|
165
|
+
* minimum (`required: true`). Carries the exact command that updates it.
|
|
166
|
+
*/
|
|
167
|
+
client_update?: HavenClientUpdate;
|
|
90
168
|
}
|
|
91
169
|
interface ToolFailure {
|
|
92
170
|
success: false;
|
|
@@ -98,7 +176,25 @@ interface ToolFailure {
|
|
|
98
176
|
paymentId?: string;
|
|
99
177
|
status?: string;
|
|
100
178
|
phase?: string;
|
|
179
|
+
/**
|
|
180
|
+
* @deprecated since #3103 — read `next_action`. Kept with the same value for
|
|
181
|
+
* one release (the #2908 pattern) and removed in the release after the one
|
|
182
|
+
* carrying #3103.
|
|
183
|
+
*/
|
|
101
184
|
nextAction?: string;
|
|
185
|
+
/**
|
|
186
|
+
* #3103 (epic #3105, decision 10): the same value as `nextAction`, spelled
|
|
187
|
+
* the way the hosted server and the signer spell it. Dual-emitted for one
|
|
188
|
+
* release (the #2908 pattern) before `nextAction` is dropped.
|
|
189
|
+
*/
|
|
190
|
+
next_action?: string;
|
|
191
|
+
/** #3101 (epic #3105, decision 7): the typed next-step family, additive; `next_tool` never null. */
|
|
192
|
+
next_tool?: string;
|
|
193
|
+
next_tool_server?: string;
|
|
194
|
+
next_tool_name?: string;
|
|
195
|
+
next_tool_server_role?: 'hosted' | 'signer';
|
|
196
|
+
next_arguments?: Record<string, unknown>;
|
|
197
|
+
next_tool_omitted_reason?: string;
|
|
102
198
|
resume_state?: unknown;
|
|
103
199
|
body?: unknown;
|
|
104
200
|
/**
|
|
@@ -108,6 +204,8 @@ interface ToolFailure {
|
|
|
108
204
|
* own wallet needs to recover first.
|
|
109
205
|
*/
|
|
110
206
|
retry_with_new_quote?: boolean;
|
|
207
|
+
/** #3303: as on {@link ToolSuccess}; on a 426 `client_outdated` refusal it is always `required: true`. */
|
|
208
|
+
client_update?: HavenClientUpdate;
|
|
111
209
|
}
|
|
112
210
|
type ToolPayload<T = unknown> = ToolSuccess<T> | ToolFailure;
|
|
113
211
|
declare function createToolHandlers(haven: HavenClient): Record<HavenMcpToolName, (input: unknown) => Promise<ToolPayload>>;
|
|
@@ -149,7 +247,7 @@ interface ConsentInput {
|
|
|
149
247
|
apiUrl?: string;
|
|
150
248
|
/** Agent identity from the credential file, when present. */
|
|
151
249
|
agentId?: string;
|
|
152
|
-
/** Haven wallet
|
|
250
|
+
/** Haven wallet the agent spends from. */
|
|
153
251
|
accountAddress?: string;
|
|
154
252
|
/** Agent's delegate EOA — the local signer. */
|
|
155
253
|
delegateAddress?: string;
|
|
@@ -255,7 +353,7 @@ declare function createHavenMcpServer(options?: HavenMcpServerOptions): Promise<
|
|
|
255
353
|
* `agent_tool_invocations` rows are always attributed to the right tool.
|
|
256
354
|
*/
|
|
257
355
|
declare const MCP_NAME = "@haven_ai/mcp";
|
|
258
|
-
declare const MCP_VERSION = "0.
|
|
356
|
+
declare const MCP_VERSION = "0.5.0-alpha.1";
|
|
259
357
|
/**
|
|
260
358
|
* Refuse to start on an unsupported Node (#1161).
|
|
261
359
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { HavenClient } from '@haven_ai/sdk';
|
|
2
|
+
import { HavenClientUpdate, HavenClient } from '@haven_ai/sdk';
|
|
3
3
|
import { z } from 'zod/v3';
|
|
4
4
|
|
|
5
5
|
interface HavenCredentialFile {
|
|
@@ -67,7 +67,79 @@ declare function loadCredentials(source?: string | HavenCredentialSource | undef
|
|
|
67
67
|
*/
|
|
68
68
|
|
|
69
69
|
type HavenMcpToolName = 'haven_send' | 'haven_pay_mcp_tool' | 'haven_quote_x402' | 'haven_pay_x402_quote' | 'haven_pay_x402' | 'haven_resume_x402_payment' | 'haven_get_payment_status' | 'haven_get_resume_state' | 'haven_get_agent' | 'haven_get_allowances' | 'haven_list_receipts' | 'haven_verify_receipt' | 'haven_sweep_delegate' | 'haven_discover_tools' | 'haven_submit_catalog_entry';
|
|
70
|
-
declare const toolSchemas:
|
|
70
|
+
declare const toolSchemas: {
|
|
71
|
+
readonly haven_send: {
|
|
72
|
+
readonly asset: z.ZodEnum<["ETH", "USDC"]>;
|
|
73
|
+
readonly recipient: z.ZodString;
|
|
74
|
+
readonly amount: z.ZodString;
|
|
75
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
76
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
77
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
78
|
+
};
|
|
79
|
+
readonly haven_pay_mcp_tool: {
|
|
80
|
+
readonly merchant_url: z.ZodString;
|
|
81
|
+
readonly tool_name: z.ZodString;
|
|
82
|
+
readonly arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
83
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
84
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
85
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
86
|
+
};
|
|
87
|
+
readonly haven_quote_x402: {
|
|
88
|
+
readonly url: z.ZodString;
|
|
89
|
+
readonly method: z.ZodOptional<z.ZodString>;
|
|
90
|
+
readonly headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
91
|
+
readonly body: z.ZodOptional<z.ZodString>;
|
|
92
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
93
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
94
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
95
|
+
};
|
|
96
|
+
readonly haven_pay_x402_quote: {
|
|
97
|
+
readonly quote: z.ZodUnknown;
|
|
98
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
99
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
100
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
101
|
+
};
|
|
102
|
+
readonly haven_pay_x402: {
|
|
103
|
+
readonly url: z.ZodString;
|
|
104
|
+
readonly method: z.ZodOptional<z.ZodString>;
|
|
105
|
+
readonly headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
106
|
+
readonly body: z.ZodOptional<z.ZodString>;
|
|
107
|
+
readonly idempotency_key: z.ZodOptional<z.ZodString>;
|
|
108
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
109
|
+
readonly idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
110
|
+
};
|
|
111
|
+
readonly haven_resume_x402_payment: {
|
|
112
|
+
readonly payment_id: z.ZodOptional<z.ZodString>;
|
|
113
|
+
readonly resume_state: z.ZodOptional<z.ZodUnknown>;
|
|
114
|
+
};
|
|
115
|
+
readonly haven_get_payment_status: {
|
|
116
|
+
readonly payment_id: z.ZodString;
|
|
117
|
+
};
|
|
118
|
+
readonly haven_get_resume_state: {
|
|
119
|
+
readonly payment_id: z.ZodString;
|
|
120
|
+
};
|
|
121
|
+
readonly haven_get_agent: {};
|
|
122
|
+
readonly haven_get_allowances: {};
|
|
123
|
+
readonly haven_sweep_delegate: {};
|
|
124
|
+
readonly haven_discover_tools: {
|
|
125
|
+
readonly category: z.ZodOptional<z.ZodString>;
|
|
126
|
+
readonly search: z.ZodOptional<z.ZodString>;
|
|
127
|
+
readonly rail: z.ZodOptional<z.ZodEnum<["x402", "mpp"]>>;
|
|
128
|
+
readonly verified: z.ZodOptional<z.ZodEnum<["any", "verified", "operator"]>>;
|
|
129
|
+
};
|
|
130
|
+
readonly haven_submit_catalog_entry: {
|
|
131
|
+
readonly resource_url: z.ZodString;
|
|
132
|
+
readonly website: z.ZodOptional<z.ZodString>;
|
|
133
|
+
};
|
|
134
|
+
readonly haven_list_receipts: {
|
|
135
|
+
readonly limit: z.ZodOptional<z.ZodNumber>;
|
|
136
|
+
/** #3128: the previous page's next_cursor (a receipt id). */
|
|
137
|
+
readonly cursor: z.ZodOptional<z.ZodString>;
|
|
138
|
+
};
|
|
139
|
+
readonly haven_verify_receipt: {
|
|
140
|
+
readonly receipt: z.ZodUnknown;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
71
143
|
/**
|
|
72
144
|
* MCP tool descriptions, composed from the shared semantic source in
|
|
73
145
|
* `@haven_ai/sdk`'s `tool-descriptions.ts`. Keeping both the SDK tool-calling
|
|
@@ -87,6 +159,12 @@ interface ToolSuccess<T> {
|
|
|
87
159
|
* leave, which is how `idempotencyKey` survived #2312 and #2348.
|
|
88
160
|
*/
|
|
89
161
|
warnings?: string[];
|
|
162
|
+
/**
|
|
163
|
+
* #3303: the backend's `client_update` hint when this package is behind the
|
|
164
|
+
* version the deployment recommends (`required: false`) or below its
|
|
165
|
+
* minimum (`required: true`). Carries the exact command that updates it.
|
|
166
|
+
*/
|
|
167
|
+
client_update?: HavenClientUpdate;
|
|
90
168
|
}
|
|
91
169
|
interface ToolFailure {
|
|
92
170
|
success: false;
|
|
@@ -98,7 +176,25 @@ interface ToolFailure {
|
|
|
98
176
|
paymentId?: string;
|
|
99
177
|
status?: string;
|
|
100
178
|
phase?: string;
|
|
179
|
+
/**
|
|
180
|
+
* @deprecated since #3103 — read `next_action`. Kept with the same value for
|
|
181
|
+
* one release (the #2908 pattern) and removed in the release after the one
|
|
182
|
+
* carrying #3103.
|
|
183
|
+
*/
|
|
101
184
|
nextAction?: string;
|
|
185
|
+
/**
|
|
186
|
+
* #3103 (epic #3105, decision 10): the same value as `nextAction`, spelled
|
|
187
|
+
* the way the hosted server and the signer spell it. Dual-emitted for one
|
|
188
|
+
* release (the #2908 pattern) before `nextAction` is dropped.
|
|
189
|
+
*/
|
|
190
|
+
next_action?: string;
|
|
191
|
+
/** #3101 (epic #3105, decision 7): the typed next-step family, additive; `next_tool` never null. */
|
|
192
|
+
next_tool?: string;
|
|
193
|
+
next_tool_server?: string;
|
|
194
|
+
next_tool_name?: string;
|
|
195
|
+
next_tool_server_role?: 'hosted' | 'signer';
|
|
196
|
+
next_arguments?: Record<string, unknown>;
|
|
197
|
+
next_tool_omitted_reason?: string;
|
|
102
198
|
resume_state?: unknown;
|
|
103
199
|
body?: unknown;
|
|
104
200
|
/**
|
|
@@ -108,6 +204,8 @@ interface ToolFailure {
|
|
|
108
204
|
* own wallet needs to recover first.
|
|
109
205
|
*/
|
|
110
206
|
retry_with_new_quote?: boolean;
|
|
207
|
+
/** #3303: as on {@link ToolSuccess}; on a 426 `client_outdated` refusal it is always `required: true`. */
|
|
208
|
+
client_update?: HavenClientUpdate;
|
|
111
209
|
}
|
|
112
210
|
type ToolPayload<T = unknown> = ToolSuccess<T> | ToolFailure;
|
|
113
211
|
declare function createToolHandlers(haven: HavenClient): Record<HavenMcpToolName, (input: unknown) => Promise<ToolPayload>>;
|
|
@@ -149,7 +247,7 @@ interface ConsentInput {
|
|
|
149
247
|
apiUrl?: string;
|
|
150
248
|
/** Agent identity from the credential file, when present. */
|
|
151
249
|
agentId?: string;
|
|
152
|
-
/** Haven wallet
|
|
250
|
+
/** Haven wallet the agent spends from. */
|
|
153
251
|
accountAddress?: string;
|
|
154
252
|
/** Agent's delegate EOA — the local signer. */
|
|
155
253
|
delegateAddress?: string;
|
|
@@ -255,7 +353,7 @@ declare function createHavenMcpServer(options?: HavenMcpServerOptions): Promise<
|
|
|
255
353
|
* `agent_tool_invocations` rows are always attributed to the right tool.
|
|
256
354
|
*/
|
|
257
355
|
declare const MCP_NAME = "@haven_ai/mcp";
|
|
258
|
-
declare const MCP_VERSION = "0.
|
|
356
|
+
declare const MCP_VERSION = "0.5.0-alpha.1";
|
|
259
357
|
/**
|
|
260
358
|
* Refuse to start on an unsupported Node (#1161).
|
|
261
359
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import { composeDescription, toolDescriptions as toolDescriptions$1, HavenPaymentStateError, HavenSigningError, HavenApiError, AgentPaymentNextAction, HavenError, HavenClient, isSupportedNodeVersion, unsupportedNodeVersionMessage, verifyPaymentReceipt, discoverMerchantMcpUrl, sameUrl, AgentPaymentFailureCode } from '@haven_ai/sdk';
|
|
3
|
+
import { composeDescription, toolDescriptions as toolDescriptions$1, HavenPaymentStateError, HavenSigningError, HavenApiError, AgentPaymentNextAction, HavenError, HavenClient, havenClientIdentity, isSupportedNodeVersion, unsupportedNodeVersionMessage, verifyPaymentReceipt, discoverMerchantMcpUrl, sameUrl, AgentPaymentFailureCode } from '@haven_ai/sdk';
|
|
4
4
|
import { readFile, stat, mkdir, writeFile } from 'fs/promises';
|
|
5
5
|
import { z } from 'zod/v3';
|
|
6
6
|
import { createHash } from 'crypto';
|
|
@@ -302,11 +302,14 @@ var toolSchemas = {
|
|
|
302
302
|
website: z.string().optional()
|
|
303
303
|
},
|
|
304
304
|
haven_list_receipts: {
|
|
305
|
-
limit: z.number().int().min(1).max(100).optional()
|
|
305
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
306
|
+
/** #3128: the previous page's next_cursor (a receipt id). */
|
|
307
|
+
cursor: z.string().min(1).optional()
|
|
306
308
|
},
|
|
307
309
|
haven_verify_receipt: {
|
|
308
310
|
receipt: z.unknown()
|
|
309
311
|
}
|
|
312
|
+
// #3101: keys survive on the type (see the hosted server's contracts.ts).
|
|
310
313
|
};
|
|
311
314
|
var toolDescriptions = {
|
|
312
315
|
haven_send: composeDescription(toolDescriptions$1.send),
|
|
@@ -497,12 +500,32 @@ function createToolHandlers(haven) {
|
|
|
497
500
|
source: entry.source,
|
|
498
501
|
domain_verified: entry.domainVerified,
|
|
499
502
|
verified_payable: entry.verifiedPayable,
|
|
500
|
-
// Which Haven pay tool reaches this entry from the local MCP surface
|
|
503
|
+
// Which Haven pay tool reaches this entry from the local MCP surface,
|
|
504
|
+
// and — #3100 (epic #3105, decision 4) — the arguments that tool
|
|
505
|
+
// accepts VERBATIM, spelled in ITS vocabulary (`merchant_url`, not
|
|
506
|
+
// the entry's `resource_url`). The local surface keeps pointing at
|
|
507
|
+
// its pay tools: they need no cap, so a verbatim hint exists.
|
|
501
508
|
// #1328: the 'mpp' rail's only-ever catalog row (the Haven MPP demo
|
|
502
509
|
// resource) is delisted with the mpp_demo retirement, so this
|
|
503
510
|
// fallback is unreachable today; it stays x402 rather than naming a
|
|
504
511
|
// deleted tool in case a future non-demo 'mpp' rail entry appears.
|
|
505
|
-
|
|
512
|
+
// A row without a tool_name cannot get a verbatim hint —
|
|
513
|
+
// haven_pay_mcp_tool requires tool_name — so it gets the REASON
|
|
514
|
+
// instead of a hint its own tool refuses (haven-reviewer on #3113;
|
|
515
|
+
// the epic's "omitted + reason, never null" shape, decision 3).
|
|
516
|
+
...entry.protocol === "mcp" ? entry.toolName ? {
|
|
517
|
+
suggested_tool: "haven_pay_mcp_tool",
|
|
518
|
+
suggested_arguments: {
|
|
519
|
+
merchant_url: entry.resourceUrl,
|
|
520
|
+
tool_name: entry.toolName,
|
|
521
|
+
...entry.toolArguments ? { arguments: entry.toolArguments } : {}
|
|
522
|
+
}
|
|
523
|
+
} : {
|
|
524
|
+
suggested_tool_omitted_reason: "this catalog row carries no tool_name, which haven_pay_mcp_tool requires; read the merchant's tool list yourself, then call haven_pay_mcp_tool with merchant_url, tool_name and arguments"
|
|
525
|
+
} : {
|
|
526
|
+
suggested_tool: "haven_pay_x402",
|
|
527
|
+
suggested_arguments: { url: entry.resourceUrl }
|
|
528
|
+
}
|
|
506
529
|
}));
|
|
507
530
|
});
|
|
508
531
|
},
|
|
@@ -522,7 +545,7 @@ function createToolHandlers(haven) {
|
|
|
522
545
|
},
|
|
523
546
|
haven_list_receipts: async (input) => {
|
|
524
547
|
const args = objectInput("haven_list_receipts", input);
|
|
525
|
-
return runTool(async () => haven.
|
|
548
|
+
return runTool(async () => haven.listReceiptsPage({ limit: args.limit, cursor: args.cursor }));
|
|
526
549
|
},
|
|
527
550
|
haven_verify_receipt: async (input) => {
|
|
528
551
|
const args = objectInput("haven_verify_receipt", input);
|
|
@@ -667,7 +690,11 @@ function normalizeError(err) {
|
|
|
667
690
|
message: err.message,
|
|
668
691
|
statusCode: err.statusCode,
|
|
669
692
|
nextAction: err.nextAction,
|
|
670
|
-
|
|
693
|
+
next_action: err.nextAction,
|
|
694
|
+
retry_with_new_quote: err.retryWithNewQuote,
|
|
695
|
+
// #3103: the local runtime's one decision site — no tool can act until
|
|
696
|
+
// the merchant recovers; the message carries retry_after_s.
|
|
697
|
+
next_tool_omitted_reason: "the merchant needs to recover first; re-quote after the retry_after_s in the message"
|
|
671
698
|
};
|
|
672
699
|
}
|
|
673
700
|
if (err instanceof HavenPaymentStateError) {
|
|
@@ -680,6 +707,7 @@ function normalizeError(err) {
|
|
|
680
707
|
status: err.status,
|
|
681
708
|
phase: err.phase,
|
|
682
709
|
nextAction: err.nextAction,
|
|
710
|
+
next_action: err.nextAction,
|
|
683
711
|
resume_state: err.resumeState,
|
|
684
712
|
body: err.body
|
|
685
713
|
};
|
|
@@ -701,6 +729,10 @@ function normalizeError(err) {
|
|
|
701
729
|
paymentId: err.paymentId,
|
|
702
730
|
phase: stringOrUndefined(body?.phase),
|
|
703
731
|
nextAction: stringOrUndefined(body?.nextAction) ?? stringOrUndefined(body?.next_action) ?? AgentPaymentNextAction.StopAndTellUser,
|
|
732
|
+
next_action: stringOrUndefined(body?.nextAction) ?? stringOrUndefined(body?.next_action) ?? AgentPaymentNextAction.StopAndTellUser,
|
|
733
|
+
// #3303: a backend refusal that already names why no tool follows (the
|
|
734
|
+
// 426 `client_outdated` does) keeps that reason at the top level.
|
|
735
|
+
...typeof body?.next_tool_omitted_reason === "string" ? { next_tool_omitted_reason: body.next_tool_omitted_reason } : {},
|
|
704
736
|
body: err.body
|
|
705
737
|
};
|
|
706
738
|
}
|
|
@@ -717,7 +749,11 @@ function normalizeError(err) {
|
|
|
717
749
|
success: false,
|
|
718
750
|
code: "UNKNOWN_ERROR",
|
|
719
751
|
message: err instanceof Error ? err.message : String(err),
|
|
720
|
-
nextAction: AgentPaymentNextAction.StopAndTellUser
|
|
752
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
753
|
+
next_action: AgentPaymentNextAction.StopAndTellUser,
|
|
754
|
+
// #3103: the second local decision site — nothing structured can follow an
|
|
755
|
+
// error this runtime did not recognise.
|
|
756
|
+
next_tool_omitted_reason: "an error this runtime does not recognise; tell the user what the message says"
|
|
721
757
|
};
|
|
722
758
|
}
|
|
723
759
|
function stringOrUndefined(value) {
|
|
@@ -749,7 +785,7 @@ function renderConsentBlock(input, hash) {
|
|
|
749
785
|
];
|
|
750
786
|
if (input.apiUrl) lines.push(`Haven API: ${input.apiUrl}`);
|
|
751
787
|
if (input.agentId) lines.push(`Agent ID: ${input.agentId}`);
|
|
752
|
-
if (input.accountAddress) lines.push(`Haven wallet
|
|
788
|
+
if (input.accountAddress) lines.push(`Haven wallet: ${input.accountAddress}`);
|
|
753
789
|
if (input.delegateAddress) lines.push(`Delegate (local signer): ${input.delegateAddress}`);
|
|
754
790
|
if (typeof input.chainId === "number") lines.push(`Chain ID: ${input.chainId}`);
|
|
755
791
|
lines.push("");
|
|
@@ -912,7 +948,10 @@ async function resolveHavenClient(options = {}) {
|
|
|
912
948
|
const client = new HavenClient({
|
|
913
949
|
apiKey: credentials.apiKey,
|
|
914
950
|
delegateKey: credentials.delegateKey,
|
|
915
|
-
baseUrl: credentials.apiUrl
|
|
951
|
+
baseUrl: credentials.apiUrl,
|
|
952
|
+
// #3303: name this package, not the SDK inside it, so the backend's
|
|
953
|
+
// update hint and refusal speak about what the user actually installed.
|
|
954
|
+
clientIdentity: havenClientIdentity(MCP_NAME, MCP_VERSION)
|
|
916
955
|
});
|
|
917
956
|
return { client, credentials };
|
|
918
957
|
}
|
|
@@ -921,7 +960,7 @@ async function createHavenMcpServer(options = {}) {
|
|
|
921
960
|
return buildMcpServer(haven);
|
|
922
961
|
}
|
|
923
962
|
var MCP_NAME = "@haven_ai/mcp";
|
|
924
|
-
var MCP_VERSION = "0.
|
|
963
|
+
var MCP_VERSION = "0.5.0-alpha.1";
|
|
925
964
|
var MCP_INSTRUCTIONS = [
|
|
926
965
|
"Haven local MCP server: signs in-process with the delegate key it holds on",
|
|
927
966
|
"this machine \u2014 the key never leaves this process. Call haven_get_agent",
|
|
@@ -930,7 +969,8 @@ var MCP_INSTRUCTIONS = [
|
|
|
930
969
|
"",
|
|
931
970
|
"To pay: haven_discover_tools to find a payable service, then",
|
|
932
971
|
"haven_pay_mcp_tool for MCP merchants or haven_pay_x402 for any x402",
|
|
933
|
-
"paywall. Tool responses carry nextAction
|
|
972
|
+
"paywall. Tool responses carry next_action (nextAction is the same value, kept one more",
|
|
973
|
+
"release) and, when no tool follows, next_tool_omitted_reason \u2014 follow them; description prose",
|
|
934
974
|
"is fallback, not the source of truth.",
|
|
935
975
|
"",
|
|
936
976
|
"A payment outside the agent budget is declined before any money moves. Haven",
|
|
@@ -957,7 +997,7 @@ function buildMcpServer(haven) {
|
|
|
957
997
|
toolSchemas[name],
|
|
958
998
|
async (args) => haven.withRequestContext(
|
|
959
999
|
{ "X-Haven-MCP-Tool": name },
|
|
960
|
-
async () => toMcpResult(await handlers[name](args))
|
|
1000
|
+
async () => toMcpResult(withClientUpdate(await handlers[name](args), haven.clientUpdate()))
|
|
961
1001
|
)
|
|
962
1002
|
);
|
|
963
1003
|
}
|
|
@@ -1007,6 +1047,10 @@ async function runConsentGate(haven, credentials, options) {
|
|
|
1007
1047
|
writeAck: options.writeAck
|
|
1008
1048
|
});
|
|
1009
1049
|
}
|
|
1050
|
+
function withClientUpdate(payload, hint) {
|
|
1051
|
+
if (!hint || payload.client_update) return payload;
|
|
1052
|
+
return { ...payload, client_update: hint };
|
|
1053
|
+
}
|
|
1010
1054
|
function toMcpResult(payload) {
|
|
1011
1055
|
return {
|
|
1012
1056
|
isError: !payload.success,
|