@paybond/kit 0.9.5 → 0.9.7

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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # `@paybond/kit`
2
2
 
3
+ <!-- mcp-name: io.github.nonameuserd/paybond -->
4
+
3
5
  Paybond Kit for TypeScript is the npm package for tenant-bound Paybond integrations and delegated agent spend controls. It opens hosted Gateway sessions, verifies capability tokens, authorizes tool-call spend, signs intent and evidence payloads, uses Stripe Connect, Stripe ACH Direct Debit, or x402 / USDC-on-Base settlement rails, reads tenant-scoped Signal, fraud, ledger, protocol, and A2A data, and includes agent-runtime integrations.
4
6
 
5
7
  Paybond is the SDK to use when you do not want to build your own delegated agent spend-governance middleware. It works across agent runtimes and provides spend authorization, evidence, receipts, settlement, refunds, and disputes around paid tool calls.
package/dist/init.js CHANGED
@@ -170,7 +170,7 @@ export async function openPaybondFromEnv(options: OpenPaybondFromEnvOptions = {}
170
170
 
171
171
  return Paybond.open({
172
172
  apiKey,
173
- gatewayBaseUrl: process.env.PAYBOND_GATEWAY_BASE_URL,
173
+ gatewayBaseUrl: process.env.PAYBOND_GATEWAY_URL ?? process.env.PAYBOND_GATEWAY_BASE_URL,
174
174
  expectedEnvironment: "sandbox",
175
175
  });
176
176
  }
@@ -281,15 +281,41 @@ export async function main(argv = process.argv.slice(2)) {
281
281
  function normalizeFileURL(url) {
282
282
  return url.startsWith("file:///var/") ? url.replace("file:///var/", "file:///private/var/") : url;
283
283
  }
284
- function invokedFromCLI() {
285
- const invokedPath = process.argv[1] ? normalizeFileURL(new URL("file://" + process.argv[1]).href) : "";
286
- return Boolean(invokedPath && normalizeFileURL(import.meta.url) === invokedPath);
284
+ async function invokedFromCLI() {
285
+ const scriptPath = process.argv[1];
286
+ if (!scriptPath) {
287
+ return false;
288
+ }
289
+ // @ts-ignore Node builtins are available in the published CLI runtime.
290
+ const fs = (await import("node:fs/promises"));
291
+ // @ts-ignore Node builtins are available in the published CLI runtime.
292
+ const path = (await import("node:path"));
293
+ // @ts-ignore Node builtins are available in the published CLI runtime.
294
+ const url = (await import("node:url"));
295
+ async function realFileURL(filePath) {
296
+ let resolved = path.resolve(filePath);
297
+ try {
298
+ resolved = await fs.realpath(resolved);
299
+ }
300
+ catch {
301
+ // If realpath fails, compare the absolute path. This keeps direct execution
302
+ // working even when the script path disappears during process startup.
303
+ }
304
+ return normalizeFileURL(url.pathToFileURL(resolved).href);
305
+ }
306
+ return (await realFileURL(scriptPath)) === (await realFileURL(url.fileURLToPath(import.meta.url)));
287
307
  }
288
- if (invokedFromCLI()) {
308
+ invokedFromCLI().then((invoked) => {
309
+ if (!invoked) {
310
+ return;
311
+ }
289
312
  main().then((code) => {
290
313
  process.exitCode = code;
291
314
  }, (err) => {
292
315
  process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
293
316
  process.exitCode = 1;
294
317
  });
295
- }
318
+ }, (err) => {
319
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
320
+ process.exitCode = 1;
321
+ });
package/dist/login.js CHANGED
@@ -440,15 +440,41 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
440
440
  function normalizeFileURL(url) {
441
441
  return url.startsWith("file:///var/") ? url.replace("file:///var/", "file:///private/var/") : url;
442
442
  }
443
- function invokedFromCLI() {
444
- const invokedPath = process.argv[1] ? normalizeFileURL(new URL("file://" + process.argv[1]).href) : "";
445
- return Boolean(invokedPath && normalizeFileURL(import.meta.url) === invokedPath);
443
+ async function invokedFromCLI() {
444
+ const scriptPath = process.argv[1];
445
+ if (!scriptPath) {
446
+ return false;
447
+ }
448
+ // @ts-ignore Node builtins are available in the published CLI runtime.
449
+ const fs = (await import("node:fs/promises"));
450
+ // @ts-ignore Node builtins are available in the published CLI runtime.
451
+ const path = (await import("node:path"));
452
+ // @ts-ignore Node builtins are available in the published CLI runtime.
453
+ const url = (await import("node:url"));
454
+ async function realFileURL(filePath) {
455
+ let resolved = path.resolve(filePath);
456
+ try {
457
+ resolved = await fs.realpath(resolved);
458
+ }
459
+ catch {
460
+ // If realpath fails, compare the absolute path. This keeps direct execution
461
+ // working even when the script path disappears during process startup.
462
+ }
463
+ return normalizeFileURL(url.pathToFileURL(resolved).href);
464
+ }
465
+ return (await realFileURL(scriptPath)) === (await realFileURL(url.fileURLToPath(import.meta.url)));
446
466
  }
447
- if (invokedFromCLI()) {
467
+ invokedFromCLI().then((invoked) => {
468
+ if (!invoked) {
469
+ return;
470
+ }
448
471
  main().then((code) => {
449
472
  process.exitCode = code;
450
473
  }, (err) => {
451
474
  process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
452
475
  process.exitCode = 1;
453
476
  });
454
- }
477
+ }, (err) => {
478
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
479
+ process.exitCode = 1;
480
+ });
@@ -3,12 +3,276 @@
3
3
  import { readFileSync } from "node:fs";
4
4
  import { GatewayAuthError, GatewayFraudClient, GatewaySignalClient, SignalHttpError, DEFAULT_PAYBOND_GATEWAY_BASE_URL, } from "./index.js";
5
5
  const SERVER_NAME = "Paybond MCP";
6
- const SERVER_VERSION = "0.6.0";
6
+ const SERVER_VERSION = "0.9.7";
7
7
  const MCP_PROTOCOL_VERSION = "2025-11-25";
8
8
  const DEFAULT_PRINCIPAL_PATH = "/v1/auth/principal";
9
9
  const DEFAULT_RECOGNITION_VERIFIER_ID = "paybond-gateway";
10
10
  const agentRecognitionProofHeader = "x-paybond-agent-recognition-proof";
11
11
  const DEFAULT_ENV_FILE = ".env.local";
12
+ const TOOL_SELECTION_METADATA = {
13
+ paybond_get_principal: {
14
+ title: "Get Paybond Principal",
15
+ annotations: readOnlyToolAnnotations("Get Paybond Principal"),
16
+ outputSchema: outputObjectSchema({
17
+ tenant_id: { type: "string", description: "Tenant bound to the configured Paybond API key." },
18
+ subject: { type: "string" },
19
+ roles: { type: "array", items: { type: "string" } },
20
+ }),
21
+ },
22
+ paybond_verify_capability: {
23
+ title: "Verify Paybond Capability",
24
+ description: "Use this when you need raw capability-token verification for one tenant-bound Harbor intent. " +
25
+ "Do not use this to create, fund, or modify intents; use paybond_authorize_agent_spend as the clearer gate before side-effecting agent tools.",
26
+ annotations: additiveMutationToolAnnotations("Verify Paybond Capability"),
27
+ outputSchema: outputObjectSchema({
28
+ allow: { type: "boolean", description: "Whether the requested operation is allowed." },
29
+ tenant: { type: "string", description: "Tenant echoed by the gateway." },
30
+ intent_id: { type: "string", description: "Verified Harbor intent UUID." },
31
+ audit_id: { type: "string", description: "Gateway audit identifier when available." },
32
+ }, ["tenant", "intent_id"]),
33
+ },
34
+ paybond_authorize_agent_spend: {
35
+ title: "Authorize Agent Spend",
36
+ description: "Use this when an agent has an intent_id and capability_token and needs a tenant-bound spend gate before calling a side-effecting tool, paid API, vendor action, or settlement workflow. " +
37
+ "Do not use this for creating, funding, or changing intents; call paybond_create_spend_intent or paybond_fund_intent first when no funded capability token exists.",
38
+ annotations: additiveMutationToolAnnotations("Authorize Agent Spend"),
39
+ outputSchema: outputObjectSchema({
40
+ allow: { type: "boolean", description: "Whether the requested operation is allowed." },
41
+ tenant: { type: "string", description: "Tenant echoed by the gateway." },
42
+ intent_id: { type: "string", description: "Verified Harbor intent UUID." },
43
+ audit_id: { type: "string", description: "Gateway audit identifier when available." },
44
+ }, ["tenant", "intent_id"]),
45
+ },
46
+ paybond_bootstrap_sandbox_guardrail: {
47
+ title: "Bootstrap Sandbox Guardrail",
48
+ description: "Use this when building or testing a first paid-tool integration and you need a sandbox-only guardrail intent with no live settlement rails. " +
49
+ "Do not use this for production live money movement or already-created Harbor intents.",
50
+ annotations: additiveMutationToolAnnotations("Bootstrap Sandbox Guardrail"),
51
+ outputSchema: outputObjectSchema({
52
+ tenant_id: { type: "string" },
53
+ intent_id: { type: "string" },
54
+ capability_token: { type: "string" },
55
+ operation: { type: "string" },
56
+ requested_spend_cents: { type: "integer" },
57
+ sandbox_lifecycle_status: { type: "string" },
58
+ settlement_rail: { type: "string" },
59
+ settlement_mode: { type: "string" },
60
+ }, ["tenant_id", "intent_id", "capability_token", "operation", "requested_spend_cents", "sandbox_lifecycle_status"]),
61
+ },
62
+ paybond_submit_sandbox_guardrail_evidence: {
63
+ title: "Submit Sandbox Guardrail Evidence",
64
+ description: "Use this when a sandbox guardrail intent needs evidence to complete simulator settlement or predicate checks. " +
65
+ "Do not use this for live Harbor spend evidence; use paybond_submit_spend_evidence for production spend intents.",
66
+ annotations: additiveMutationToolAnnotations("Submit Sandbox Guardrail Evidence"),
67
+ outputSchema: outputObjectSchema({
68
+ tenant_id: { type: "string" },
69
+ intent_id: { type: "string" },
70
+ operation: { type: "string" },
71
+ requested_spend_cents: { type: "integer" },
72
+ sandbox_lifecycle_status: { type: "string" },
73
+ predicate_passed: { type: "boolean" },
74
+ payload_digest: { type: "string" },
75
+ }, ["tenant_id", "intent_id", "operation", "requested_spend_cents", "sandbox_lifecycle_status"]),
76
+ },
77
+ paybond_list_intents: {
78
+ title: "List Harbor Intents",
79
+ annotations: readOnlyToolAnnotations("List Harbor Intents"),
80
+ outputSchema: outputObjectSchema({
81
+ items: { type: "array", items: { type: "object", additionalProperties: true } },
82
+ next_cursor: { type: "string" },
83
+ }),
84
+ },
85
+ paybond_get_intent: {
86
+ title: "Get Harbor Intent",
87
+ annotations: readOnlyToolAnnotations("Get Harbor Intent"),
88
+ outputSchema: outputObjectSchema({
89
+ intent_id: { type: "string" },
90
+ state: { type: "string" },
91
+ tenant_id: { type: "string" },
92
+ }),
93
+ },
94
+ paybond_get_reputation_receipt: {
95
+ title: "Get Reputation Receipt",
96
+ annotations: readOnlyToolAnnotations("Get Reputation Receipt"),
97
+ outputSchema: outputObjectSchema({
98
+ tenant_id: { type: "string" },
99
+ operator_did: { type: "string" },
100
+ signature_hex: { type: "string" },
101
+ }),
102
+ },
103
+ paybond_get_portfolio_summary: {
104
+ title: "Get Portfolio Summary",
105
+ annotations: readOnlyToolAnnotations("Get Portfolio Summary"),
106
+ outputSchema: outputObjectSchema({
107
+ tenant_id: { type: "string" },
108
+ score_model_version: { type: "string" },
109
+ operators: { type: "array", items: { type: "object", additionalProperties: true } },
110
+ }),
111
+ },
112
+ paybond_get_signed_portfolio_artifact: {
113
+ title: "Get Signed Portfolio Artifact",
114
+ annotations: readOnlyToolAnnotations("Get Signed Portfolio Artifact"),
115
+ outputSchema: outputObjectSchema({
116
+ tenant_id: { type: "string" },
117
+ kind: { type: "string" },
118
+ signature_hex: { type: "string" },
119
+ checkpoint_last_ledger_seq: { type: "integer" },
120
+ }),
121
+ },
122
+ paybond_get_fraud_assessment: {
123
+ title: "Get Fraud Assessment",
124
+ annotations: readOnlyToolAnnotations("Get Fraud Assessment"),
125
+ outputSchema: outputObjectSchema({
126
+ tenant_id: { type: "string" },
127
+ operator_did: { type: "string" },
128
+ fraud_assessment: { type: "object", additionalProperties: true },
129
+ }),
130
+ },
131
+ paybond_get_fraud_metrics: {
132
+ title: "Get Fraud Metrics",
133
+ annotations: readOnlyToolAnnotations("Get Fraud Metrics"),
134
+ outputSchema: outputObjectSchema({
135
+ tenant_id: { type: "string" },
136
+ window: { type: "string" },
137
+ flagged_operator_count: { type: "integer" },
138
+ critical_signal_count: { type: "integer" },
139
+ }),
140
+ },
141
+ paybond_get_a2a_agent_card: {
142
+ title: "Get A2A Agent Card",
143
+ annotations: readOnlyToolAnnotations("Get A2A Agent Card"),
144
+ outputSchema: outputObjectSchema({
145
+ name: { type: "string" },
146
+ version: { type: "string" },
147
+ skills: { type: "array", items: { type: "object", additionalProperties: true } },
148
+ }),
149
+ },
150
+ paybond_list_a2a_task_contracts: {
151
+ title: "List A2A Task Contracts",
152
+ annotations: readOnlyToolAnnotations("List A2A Task Contracts"),
153
+ outputSchema: outputObjectSchema({
154
+ contracts: { type: "array", items: { type: "object", additionalProperties: true } },
155
+ }),
156
+ },
157
+ paybond_get_a2a_task_contract: {
158
+ title: "Get A2A Task Contract",
159
+ annotations: readOnlyToolAnnotations("Get A2A Task Contract"),
160
+ outputSchema: outputObjectSchema({
161
+ id: { type: "string" },
162
+ name: { type: "string" },
163
+ description: { type: "string" },
164
+ }),
165
+ },
166
+ paybond_verify_agent_mandate_v1: {
167
+ title: "Verify Agent Mandate",
168
+ annotations: readOnlyToolAnnotations("Verify Agent Mandate"),
169
+ outputSchema: outputObjectSchema({
170
+ valid: { type: "boolean" },
171
+ mandate_digest_sha256_hex: { type: "string" },
172
+ }),
173
+ },
174
+ paybond_verify_agent_recognition_proof_v1: {
175
+ title: "Verify Agent Recognition Proof",
176
+ annotations: readOnlyToolAnnotations("Verify Agent Recognition Proof"),
177
+ outputSchema: outputObjectSchema({
178
+ valid: { type: "boolean" },
179
+ proof: { type: "object", additionalProperties: true },
180
+ }),
181
+ },
182
+ paybond_import_agent_mandate_v1: {
183
+ title: "Import Agent Mandate",
184
+ annotations: additiveMutationToolAnnotations("Import Agent Mandate"),
185
+ outputSchema: outputObjectSchema({
186
+ valid: { type: "boolean" },
187
+ intent_id: { type: "string" },
188
+ mandate_digest_sha256_hex: { type: "string" },
189
+ authorization_receipt: { type: "object", additionalProperties: true },
190
+ }),
191
+ },
192
+ paybond_get_settlement_receipt_v1: {
193
+ title: "Get Settlement Receipt",
194
+ annotations: readOnlyToolAnnotations("Get Settlement Receipt"),
195
+ outputSchema: outputObjectSchema({
196
+ tenant_id: { type: "string" },
197
+ receipt_id: { type: "string" },
198
+ intent_id: { type: "string" },
199
+ }, ["tenant_id", "receipt_id"]),
200
+ },
201
+ paybond_verify_protocol_receipt_v1: {
202
+ title: "Verify Protocol Receipt",
203
+ annotations: readOnlyToolAnnotations("Verify Protocol Receipt"),
204
+ outputSchema: outputObjectSchema({
205
+ valid: { type: "boolean" },
206
+ receipt_id: { type: "string" },
207
+ }),
208
+ },
209
+ paybond_create_intent: {
210
+ title: "Create Harbor Intent",
211
+ description: "Use this when you already have a fully signed Harbor intent request body and replay-safe recognition proof for the gateway /harbor/intents route. " +
212
+ "Do not use this for the normal agent spend-control path unless you specifically need the low-level Harbor API; prefer paybond_create_spend_intent.",
213
+ annotations: additiveMutationToolAnnotations("Create Harbor Intent"),
214
+ outputSchema: outputObjectSchema({
215
+ intent_id: { type: "string" },
216
+ state: { type: "string" },
217
+ capability_token: { type: "string" },
218
+ }),
219
+ },
220
+ paybond_create_spend_intent: {
221
+ title: "Create Spend Intent",
222
+ description: "Use this when an agent workflow needs a new Paybond spend intent with bounded budget, allowed operations, evidence requirements, and settlement review. " +
223
+ "Do not use this for checking an already funded capability token; use paybond_authorize_agent_spend before the paid action.",
224
+ annotations: additiveMutationToolAnnotations("Create Spend Intent"),
225
+ outputSchema: outputObjectSchema({
226
+ intent_id: { type: "string" },
227
+ state: { type: "string" },
228
+ capability_token: { type: "string" },
229
+ }),
230
+ },
231
+ paybond_fund_intent: {
232
+ title: "Fund Intent",
233
+ description: "Use this when an existing Harbor intent needs to advance through funding via the gateway and you have a replay-safe recognition proof. " +
234
+ "Do not use this to create a new intent or to authorize a downstream tool call; use the returned intent_id and capability_token with paybond_authorize_agent_spend.",
235
+ annotations: liveMutationToolAnnotations("Fund Intent"),
236
+ outputSchema: outputObjectSchema({
237
+ intent_id: { type: "string" },
238
+ state: { type: "string" },
239
+ capability_token: { type: "string" },
240
+ }),
241
+ },
242
+ paybond_submit_evidence: {
243
+ title: "Submit Harbor Evidence",
244
+ description: "Use this when you already have a Harbor evidence request body and recognition proof for the gateway /harbor/intents/{id}/evidence route. " +
245
+ "Do not use this for the high-level spend-control path unless you need the low-level Harbor API; prefer paybond_submit_spend_evidence.",
246
+ annotations: additiveMutationToolAnnotations("Submit Harbor Evidence"),
247
+ outputSchema: outputObjectSchema({
248
+ intent_id: { type: "string" },
249
+ state: { type: "string" },
250
+ evidence_id: { type: "string" },
251
+ }),
252
+ },
253
+ paybond_submit_spend_evidence: {
254
+ title: "Submit Spend Evidence",
255
+ description: "Use this when a Paybond spend intent needs signed evidence so release, refund, review, and receipt generation use the same audit-ready record. " +
256
+ "Do not use this to create or fund intents, and do not use it for sandbox guardrail evidence.",
257
+ annotations: additiveMutationToolAnnotations("Submit Spend Evidence"),
258
+ outputSchema: outputObjectSchema({
259
+ intent_id: { type: "string" },
260
+ state: { type: "string" },
261
+ evidence_id: { type: "string" },
262
+ }),
263
+ },
264
+ paybond_confirm_settlement: {
265
+ title: "Confirm Settlement",
266
+ description: "Use this when a Harbor intent is ready for final settlement confirmation and you have the signed body plus recognition proof. " +
267
+ "Do not use this for evidence submission or capability authorization.",
268
+ annotations: liveMutationToolAnnotations("Confirm Settlement"),
269
+ outputSchema: outputObjectSchema({
270
+ intent_id: { type: "string" },
271
+ state: { type: "string" },
272
+ receipt_id: { type: "string" },
273
+ }),
274
+ },
275
+ };
12
276
  function readEnvFileValue(envFile, key) {
13
277
  let body;
14
278
  try {
@@ -393,8 +657,11 @@ export class PaybondMCPServer {
393
657
  listTools() {
394
658
  return this.tools.map((tool) => ({
395
659
  name: tool.name,
660
+ title: tool.title,
396
661
  description: tool.description,
397
662
  inputSchema: tool.inputSchema,
663
+ ...(tool.outputSchema === undefined ? {} : { outputSchema: tool.outputSchema }),
664
+ ...(tool.annotations === undefined ? {} : { annotations: tool.annotations }),
398
665
  }));
399
666
  }
400
667
  async callTool(name, args = {}) {
@@ -445,7 +712,10 @@ export class PaybondMCPServer {
445
712
  },
446
713
  serverInfo: {
447
714
  name: SERVER_NAME,
715
+ title: "Paybond MCP",
448
716
  version: SERVER_VERSION,
717
+ description: "Tenant-bound Paybond gateway tools for agent spend controls, Harbor intents, Signal reputation, fraud review, and protocol verification.",
718
+ websiteUrl: "https://paybond.ai",
449
719
  },
450
720
  instructions: "This MCP server is tenant-bound to the configured Paybond service-account API key. " +
451
721
  "Use paybond_create_spend_intent or paybond_fund_intent to obtain the intent_id and " +
@@ -872,7 +1142,7 @@ export class PaybondMCPServer {
872
1142
  }),
873
1143
  },
874
1144
  ];
875
- return tools;
1145
+ return tools.map((tool) => toolWithSelectionMetadata(tool));
876
1146
  }
877
1147
  }
878
1148
  export function settingsFromEnv(env = process.env) {
@@ -882,7 +1152,9 @@ export function settingsFromEnv(env = process.env) {
882
1152
  throw new Error("PAYBOND_API_KEY is required; run paybond login or configure your MCP host environment");
883
1153
  }
884
1154
  return {
885
- gatewayBaseUrl: optionalEnv(env.PAYBOND_GATEWAY_BASE_URL) ?? DEFAULT_PAYBOND_GATEWAY_BASE_URL,
1155
+ gatewayBaseUrl: optionalEnv(env.PAYBOND_GATEWAY_URL) ??
1156
+ optionalEnv(env.PAYBOND_GATEWAY_BASE_URL) ??
1157
+ DEFAULT_PAYBOND_GATEWAY_BASE_URL,
886
1158
  apiKey,
887
1159
  principalPath: optionalEnv(env.PAYBOND_PRINCIPAL_PATH) ?? DEFAULT_PRINCIPAL_PATH,
888
1160
  maxRetries: optionalEnv(env.PAYBOND_MCP_MAX_RETRIES)
@@ -985,6 +1257,52 @@ function emptyObjectSchema() {
985
1257
  additionalProperties: false,
986
1258
  };
987
1259
  }
1260
+ function outputObjectSchema(properties, required = []) {
1261
+ return {
1262
+ type: "object",
1263
+ properties,
1264
+ additionalProperties: true,
1265
+ ...(required.length === 0 ? {} : { required }),
1266
+ };
1267
+ }
1268
+ function readOnlyToolAnnotations(title) {
1269
+ return {
1270
+ title,
1271
+ readOnlyHint: true,
1272
+ openWorldHint: false,
1273
+ };
1274
+ }
1275
+ function additiveMutationToolAnnotations(title) {
1276
+ return {
1277
+ title,
1278
+ readOnlyHint: false,
1279
+ destructiveHint: false,
1280
+ idempotentHint: false,
1281
+ openWorldHint: true,
1282
+ };
1283
+ }
1284
+ function liveMutationToolAnnotations(title) {
1285
+ return {
1286
+ title,
1287
+ readOnlyHint: false,
1288
+ destructiveHint: true,
1289
+ idempotentHint: false,
1290
+ openWorldHint: true,
1291
+ };
1292
+ }
1293
+ function toolWithSelectionMetadata(tool) {
1294
+ const metadata = TOOL_SELECTION_METADATA[tool.name];
1295
+ if (metadata === undefined) {
1296
+ throw new Error(`missing MCP tool selection metadata for ${tool.name}`);
1297
+ }
1298
+ return {
1299
+ ...tool,
1300
+ title: metadata.title,
1301
+ description: metadata.description ?? tool.description,
1302
+ outputSchema: metadata.outputSchema,
1303
+ annotations: metadata.annotations,
1304
+ };
1305
+ }
988
1306
  function toToolResult(value) {
989
1307
  if (value === null) {
990
1308
  return {
@@ -1049,18 +1367,35 @@ function formatError(err) {
1049
1367
  function normalizeFileURL(url) {
1050
1368
  return url.startsWith("file:///var/") ? url.replace("file:///var/", "file:///private/var/") : url;
1051
1369
  }
1052
- const isMainModule = (() => {
1370
+ async function invokedFromCLI() {
1053
1371
  const scriptPath = process.argv[1];
1054
1372
  if (!scriptPath) {
1055
1373
  return false;
1056
1374
  }
1057
- try {
1058
- return normalizeFileURL(import.meta.url) === normalizeFileURL(new URL("file://" + scriptPath).href);
1375
+ // @ts-ignore Node builtins are available in the published CLI runtime.
1376
+ const fs = (await import("node:fs/promises"));
1377
+ // @ts-ignore Node builtins are available in the published CLI runtime.
1378
+ const path = (await import("node:path"));
1379
+ // @ts-ignore Node builtins are available in the published CLI runtime.
1380
+ const url = (await import("node:url"));
1381
+ async function realFileURL(filePath) {
1382
+ let resolved = path.resolve(filePath);
1383
+ try {
1384
+ resolved = await fs.realpath(resolved);
1385
+ }
1386
+ catch {
1387
+ // If realpath fails, compare the absolute path. This keeps direct execution
1388
+ // working even when the script path disappears during process startup.
1389
+ }
1390
+ return normalizeFileURL(url.pathToFileURL(resolved).href);
1059
1391
  }
1060
- catch {
1061
- return import.meta.url.endsWith(scriptPath);
1392
+ return (await realFileURL(scriptPath)) === (await realFileURL(url.fileURLToPath(import.meta.url)));
1393
+ }
1394
+ invokedFromCLI().then((invoked) => {
1395
+ if (invoked && main() !== 0) {
1396
+ process.exitCode = 1;
1062
1397
  }
1063
- })();
1064
- if (isMainModule && main() !== 0) {
1398
+ }, (err) => {
1399
+ process.stderr.write(`${formatError(err)}\n`);
1065
1400
  process.exitCode = 1;
1066
- }
1401
+ });
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@paybond/kit",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
+ "mcpName": "io.github.nonameuserd/paybond",
4
5
  "description": "Paybond Kit for TypeScript: agent spend governance for paid tool calls with spend authorization, evidence receipts, refunds, disputes, hosted Gateway sessions, and settlement.",
5
6
  "license": "Apache-2.0",
6
7
  "type": "module",