@curless/mcp-server 0.1.58 → 0.1.60

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/client.d.ts CHANGED
@@ -23,10 +23,14 @@ export declare class CurlessClient {
23
23
  constructor(opts?: CurlessClientOptions);
24
24
  /** GET with optional query params. */
25
25
  get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<T>;
26
- /** POST JSON body. */
27
- post<T = unknown>(path: string, body: unknown): Promise<T>;
28
- /** PUT JSON body. */
29
- put<T = unknown>(path: string, body: unknown): Promise<T>;
26
+ /** POST JSON body. Optionally pass `auth` to set Authorization: Bearer <sk>. */
27
+ post<T = unknown>(path: string, body: unknown, opts?: {
28
+ auth?: string;
29
+ }): Promise<T>;
30
+ /** PUT JSON body. Optionally pass `auth` to set Authorization: Bearer <sk>. */
31
+ put<T = unknown>(path: string, body: unknown, opts?: {
32
+ auth?: string;
33
+ }): Promise<T>;
30
34
  private fetch;
31
35
  }
32
36
  /**
package/dist/client.js CHANGED
@@ -36,19 +36,25 @@ export class CurlessClient {
36
36
  }
37
37
  return this.fetch(url.toString(), { method: 'GET' });
38
38
  }
39
- /** POST JSON body. */
40
- async post(path, body) {
39
+ /** POST JSON body. Optionally pass `auth` to set Authorization: Bearer <sk>. */
40
+ async post(path, body, opts) {
41
+ const headers = { 'Content-Type': 'application/json' };
42
+ if (opts?.auth)
43
+ headers['Authorization'] = `Bearer ${opts.auth}`;
41
44
  return this.fetch(this.baseUrl + path, {
42
45
  method: 'POST',
43
- headers: { 'Content-Type': 'application/json' },
46
+ headers,
44
47
  body: JSON.stringify(body),
45
48
  });
46
49
  }
47
- /** PUT JSON body. */
48
- async put(path, body) {
50
+ /** PUT JSON body. Optionally pass `auth` to set Authorization: Bearer <sk>. */
51
+ async put(path, body, opts) {
52
+ const headers = { 'Content-Type': 'application/json' };
53
+ if (opts?.auth)
54
+ headers['Authorization'] = `Bearer ${opts.auth}`;
49
55
  return this.fetch(this.baseUrl + path, {
50
56
  method: 'PUT',
51
- headers: { 'Content-Type': 'application/json' },
57
+ headers,
52
58
  body: JSON.stringify(body),
53
59
  });
54
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -823,6 +823,7 @@ const TOOLS = [
823
823
  // auto_open removed 2026-05-13: storefront page no longer
824
824
  // auto-launches in the OS browser. Click the markdown link in
825
825
  // the response instead.
826
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
826
827
  },
827
828
  },
828
829
  handler: async (args) => {
@@ -830,7 +831,7 @@ const TOOLS = [
830
831
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
831
832
  if (approvalId) {
832
833
  try {
833
- const result = unwrap(await client.post('/api/cotti/checkout', { approval_id: approvalId }));
834
+ const result = unwrap(await client.post('/api/cotti/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
834
835
  if (result?.status === 'pending_approval') {
835
836
  return {
836
837
  status: 'pending_approval',
@@ -984,7 +985,7 @@ const TOOLS = [
984
985
  sugar_level: sugarLevel,
985
986
  with_milk: withMilk,
986
987
  temperature: temperature,
987
- }));
988
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
988
989
  // Approval gate fired — surface the URL to the LLM.
989
990
  if (result?.status === 'pending_approval') {
990
991
  return {
@@ -1120,6 +1121,7 @@ const TOOLS = [
1120
1121
  // auto_open removed 2026-05-13: booking page no longer
1121
1122
  // auto-launches in the OS browser. Click the markdown link
1122
1123
  // in the response instead.
1124
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
1123
1125
  },
1124
1126
  },
1125
1127
  handler: async (args) => {
@@ -1132,7 +1134,7 @@ const TOOLS = [
1132
1134
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
1133
1135
  if (approvalId) {
1134
1136
  try {
1135
- const result = unwrap(await client.post('/api/clubmed/checkout', { approval_id: approvalId }));
1137
+ const result = unwrap(await client.post('/api/clubmed/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1136
1138
  // If the result still says pending_approval, surface it
1137
1139
  // verbatim so the LLM tells the user "still waiting".
1138
1140
  if (result?.status === 'pending_approval') {
@@ -1198,7 +1200,7 @@ const TOOLS = [
1198
1200
  vcc_id: vccId,
1199
1201
  agent_id: stampAgent('hotel'),
1200
1202
  caller_agent_id: callerAgentId(),
1201
- }));
1203
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1202
1204
  // Approval gate fired — return the pending state to the LLM
1203
1205
  // so it can show the URL to the human and stop.
1204
1206
  if (result?.status === 'pending_approval') {
@@ -1328,6 +1330,7 @@ const TOOLS = [
1328
1330
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with austrian-compatible merchant_lock.' },
1329
1331
  approval_id: { type: 'string', description: 'When retrying a booking previously gated for human approval, pass the approval_id from the first call. Other args are ignored on replay.' },
1330
1332
  inline_screenshot: { type: 'boolean', description: 'Embed an inline screenshot of the booking confirmation page. Defaults to TRUE for book_flight. Pass false to skip (faster).' },
1333
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
1331
1334
  },
1332
1335
  },
1333
1336
  handler: async (args) => {
@@ -1335,7 +1338,7 @@ const TOOLS = [
1335
1338
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
1336
1339
  if (approvalId) {
1337
1340
  try {
1338
- const result = unwrap(await client.post('/api/austrian/checkout', { approval_id: approvalId }));
1341
+ const result = unwrap(await client.post('/api/austrian/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1339
1342
  if (result?.status === 'pending_approval') {
1340
1343
  return {
1341
1344
  status: 'pending_approval',
@@ -1406,7 +1409,7 @@ const TOOLS = [
1406
1409
  vcc_id: vccId,
1407
1410
  agent_id: stampAgent('hotel'), // share TravelBot (agent-001) audit scope
1408
1411
  caller_agent_id: callerAgentId(),
1409
- }));
1412
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1410
1413
  if (result?.status === 'pending_approval') {
1411
1414
  return {
1412
1415
  status: 'pending_approval',
@@ -1578,6 +1581,7 @@ const TOOLS = [
1578
1581
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with ninety-compatible merchant_lock.' },
1579
1582
  approval_id: { type: 'string', description: 'When retrying a previously-gated order, pass the approval_id from the first call. Other args ignored on replay.' },
1580
1583
  inline_screenshot: { type: 'boolean', description: 'Embed an inline screenshot of the order page. Defaults to TRUE. Pass false to skip (faster).' },
1584
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
1581
1585
  },
1582
1586
  },
1583
1587
  handler: async (args) => {
@@ -1585,7 +1589,7 @@ const TOOLS = [
1585
1589
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
1586
1590
  if (approvalId) {
1587
1591
  try {
1588
- const result = unwrap(await client.post('/api/ninety/checkout', { approval_id: approvalId }));
1592
+ const result = unwrap(await client.post('/api/ninety/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1589
1593
  if (result?.status === 'pending_approval') {
1590
1594
  return {
1591
1595
  status: 'pending_approval',
@@ -1639,7 +1643,7 @@ const TOOLS = [
1639
1643
  vcc_id: vccId,
1640
1644
  agent_id: stampAgent('hotel'), // share TravelBot (agent-001) audit scope
1641
1645
  caller_agent_id: callerAgentId(),
1642
- }));
1646
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1643
1647
  if (result?.status === 'pending_approval') {
1644
1648
  return {
1645
1649
  status: 'pending_approval',
@@ -1755,6 +1759,7 @@ const TOOLS = [
1755
1759
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
1756
1760
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with vienna-compatible merchant_lock.' },
1757
1761
  approval_id: { type: 'string', description: 'When retrying a previously-gated order, pass the approval_id from the first call. Other args ignored on replay.' },
1762
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
1758
1763
  },
1759
1764
  },
1760
1765
  handler: async (args) => {
@@ -1762,7 +1767,7 @@ const TOOLS = [
1762
1767
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
1763
1768
  if (approvalId) {
1764
1769
  try {
1765
- const result = unwrap(await client.post('/api/vienna/checkout', { approval_id: approvalId }));
1770
+ const result = unwrap(await client.post('/api/vienna/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1766
1771
  if (result?.status === 'pending_approval') {
1767
1772
  return {
1768
1773
  status: 'pending_approval',
@@ -1813,7 +1818,7 @@ const TOOLS = [
1813
1818
  vcc_id: vccId,
1814
1819
  agent_id: stampAgent('default'),
1815
1820
  caller_agent_id: callerAgentId(),
1816
- }));
1821
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
1817
1822
  if (result?.status === 'pending_approval') {
1818
1823
  return {
1819
1824
  status: 'pending_approval',
@@ -1917,7 +1922,7 @@ const TOOLS = [
1917
1922
  },
1918
1923
  {
1919
1924
  name: 'pay_incar_service',
1920
- description: '[curless-mcp-server v0.1.42] Pay for a Curless InCar AI (jdo.curless.ai) trip-commerce item with the user\'s VCC. Required: item_id + customer_name. Approval-gated ≥ $150 (returns pending_approval + approval_url — retry with approval_id).',
1925
+ description: '[curless-mcp-server v0.1.43] Pay for a Curless InCar AI (jdo.curless.ai) trip-commerce item with the user\'s VCC. Required: item_id + customer_name. Approval-gated ≥ $150 (returns pending_approval + approval_url — retry with approval_id). Pass sk_test when the target VCC has an owner_account_id set — only that owner\'s key may authorize the charge.',
1921
1926
  inputSchema: {
1922
1927
  type: 'object',
1923
1928
  required: ['item_id', 'customer_name'],
@@ -1927,14 +1932,17 @@ const TOOLS = [
1927
1932
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
1928
1933
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with jdo-compatible merchant_lock.' },
1929
1934
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $150), pass the approval_id from the first call. Other args ignored on replay.' },
1935
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
1930
1936
  },
1931
1937
  },
1932
1938
  handler: async (args) => {
1939
+ const skTest = typeof args.sk_test === 'string' && args.sk_test.trim()
1940
+ ? args.sk_test.trim() : undefined;
1933
1941
  // ── Replay branch ──────────────────────────────────────────
1934
1942
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
1935
1943
  if (approvalId) {
1936
1944
  try {
1937
- const result = unwrap(await client.post('/api/jdo/checkout', { approval_id: approvalId }));
1945
+ const result = unwrap(await client.post('/api/jdo/checkout', { approval_id: approvalId }, { auth: skTest }));
1938
1946
  if (result?.status === 'pending_approval') {
1939
1947
  return {
1940
1948
  status: 'pending_approval',
@@ -1985,7 +1993,7 @@ const TOOLS = [
1985
1993
  vcc_id: vccId,
1986
1994
  agent_id: stampAgent('default'),
1987
1995
  caller_agent_id: callerAgentId(),
1988
- }));
1996
+ }, { auth: skTest }));
1989
1997
  if (result?.status === 'pending_approval') {
1990
1998
  return {
1991
1999
  status: 'pending_approval',
@@ -2099,7 +2107,7 @@ const TOOLS = [
2099
2107
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2100
2108
  if (approvalId) {
2101
2109
  try {
2102
- const result = unwrap(await client.post('/api/obb/checkout', { approval_id: approvalId }));
2110
+ const result = unwrap(await client.post('/api/obb/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2103
2111
  if (result?.status === 'pending_approval') {
2104
2112
  return {
2105
2113
  status: 'pending_approval',
@@ -2150,7 +2158,7 @@ const TOOLS = [
2150
2158
  vcc_id: vccId,
2151
2159
  agent_id: stampAgent('default'),
2152
2160
  caller_agent_id: callerAgentId(),
2153
- }));
2161
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2154
2162
  if (result?.status === 'pending_approval') {
2155
2163
  return {
2156
2164
  status: 'pending_approval',
@@ -2226,6 +2234,7 @@ const TOOLS = [
2226
2234
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
2227
2235
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with obb-compatible merchant_lock.' },
2228
2236
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $200), pass the approval_id from the first call. Other args ignored on replay.' },
2237
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
2229
2238
  },
2230
2239
  },
2231
2240
  handler: async (args) => {
@@ -2233,7 +2242,7 @@ const TOOLS = [
2233
2242
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2234
2243
  if (approvalId) {
2235
2244
  try {
2236
- const result = unwrap(await client.post('/api/obb/checkout', { approval_id: approvalId }));
2245
+ const result = unwrap(await client.post('/api/obb/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2237
2246
  if (result?.status === 'pending_approval') {
2238
2247
  return {
2239
2248
  status: 'pending_approval',
@@ -2281,7 +2290,7 @@ const TOOLS = [
2281
2290
  vcc_id: vccId,
2282
2291
  agent_id: stampAgent('default'),
2283
2292
  caller_agent_id: callerAgentId(),
2284
- }));
2293
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2285
2294
  if (result?.status === 'pending_approval') {
2286
2295
  return {
2287
2296
  status: 'pending_approval',
@@ -2395,7 +2404,7 @@ const TOOLS = [
2395
2404
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2396
2405
  if (approvalId) {
2397
2406
  try {
2398
- const result = unwrap(await client.post('/api/putien/checkout', { approval_id: approvalId }));
2407
+ const result = unwrap(await client.post('/api/putien/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2399
2408
  if (result?.status === 'pending_approval') {
2400
2409
  return {
2401
2410
  status: 'pending_approval',
@@ -2454,7 +2463,7 @@ const TOOLS = [
2454
2463
  vcc_id: vccId,
2455
2464
  agent_id: stampAgent('default'),
2456
2465
  caller_agent_id: callerAgentId(),
2457
- }));
2466
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2458
2467
  if (result?.status === 'pending_approval') {
2459
2468
  return {
2460
2469
  status: 'pending_approval',
@@ -2533,6 +2542,7 @@ const TOOLS = [
2533
2542
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
2534
2543
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with putien-compatible merchant_lock.' },
2535
2544
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $200), pass the approval_id from the first call. Other args ignored on replay.' },
2545
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
2536
2546
  },
2537
2547
  },
2538
2548
  handler: async (args) => {
@@ -2540,7 +2550,7 @@ const TOOLS = [
2540
2550
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2541
2551
  if (approvalId) {
2542
2552
  try {
2543
- const result = unwrap(await client.post('/api/putien/checkout', { approval_id: approvalId }));
2553
+ const result = unwrap(await client.post('/api/putien/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2544
2554
  if (result?.status === 'pending_approval') {
2545
2555
  return {
2546
2556
  status: 'pending_approval',
@@ -2588,7 +2598,7 @@ const TOOLS = [
2588
2598
  vcc_id: vccId,
2589
2599
  agent_id: stampAgent('default'),
2590
2600
  caller_agent_id: callerAgentId(),
2591
- }));
2601
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2592
2602
  if (result?.status === 'pending_approval') {
2593
2603
  return {
2594
2604
  status: 'pending_approval',
@@ -2711,6 +2721,7 @@ const TOOLS = [
2711
2721
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
2712
2722
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with a1-compatible merchant_lock.' },
2713
2723
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $50), pass the approval_id from the first call. Other args ignored on replay.' },
2724
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
2714
2725
  },
2715
2726
  },
2716
2727
  handler: async (args) => {
@@ -2718,7 +2729,7 @@ const TOOLS = [
2718
2729
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2719
2730
  if (approvalId) {
2720
2731
  try {
2721
- const result = unwrap(await client.post('/api/a1/checkout', { approval_id: approvalId }));
2732
+ const result = unwrap(await client.post('/api/a1/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2722
2733
  if (result?.status === 'pending_approval') {
2723
2734
  return {
2724
2735
  status: 'pending_approval',
@@ -2767,7 +2778,7 @@ const TOOLS = [
2767
2778
  vcc_id: vccId,
2768
2779
  agent_id: stampAgent('default'),
2769
2780
  caller_agent_id: callerAgentId(),
2770
- }));
2781
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2771
2782
  if (result?.status === 'pending_approval') {
2772
2783
  return {
2773
2784
  status: 'pending_approval',
@@ -2878,6 +2889,7 @@ const TOOLS = [
2878
2889
  quantity: { type: 'integer', minimum: 1, maximum: 20, default: 1 },
2879
2890
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with austria-compatible merchant_lock.' },
2880
2891
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $200), pass the approval_id from the first call. Other args ignored on replay.' },
2892
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
2881
2893
  },
2882
2894
  },
2883
2895
  handler: async (args) => {
@@ -2885,7 +2897,7 @@ const TOOLS = [
2885
2897
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
2886
2898
  if (approvalId) {
2887
2899
  try {
2888
- const result = unwrap(await client.post('/api/austria/checkout', { approval_id: approvalId }));
2900
+ const result = unwrap(await client.post('/api/austria/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2889
2901
  if (result?.status === 'pending_approval') {
2890
2902
  return {
2891
2903
  status: 'pending_approval',
@@ -2934,7 +2946,7 @@ const TOOLS = [
2934
2946
  vcc_id: vccId,
2935
2947
  agent_id: stampAgent('default'),
2936
2948
  caller_agent_id: callerAgentId(),
2937
- }));
2949
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
2938
2950
  if (result?.status === 'pending_approval') {
2939
2951
  return {
2940
2952
  status: 'pending_approval',
@@ -3041,6 +3053,7 @@ const TOOLS = [
3041
3053
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with wolford-compatible merchant_lock.' },
3042
3054
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $300), pass the approval_id from the first call. Other args ignored on replay.' },
3043
3055
  inline_screenshot: { type: 'boolean', default: true, description: 'Embed an inline screenshot of the order confirmation page. Default true; pass false to skip.' },
3056
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
3044
3057
  },
3045
3058
  },
3046
3059
  handler: async (args) => {
@@ -3048,7 +3061,7 @@ const TOOLS = [
3048
3061
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
3049
3062
  if (approvalId) {
3050
3063
  try {
3051
- const result = unwrap(await client.post('/api/wolford/checkout', { approval_id: approvalId }));
3064
+ const result = unwrap(await client.post('/api/wolford/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3052
3065
  if (result?.status === 'pending_approval') {
3053
3066
  return {
3054
3067
  status: 'pending_approval',
@@ -3102,7 +3115,7 @@ const TOOLS = [
3102
3115
  vcc_id: vccId,
3103
3116
  agent_id: stampAgent('default'),
3104
3117
  caller_agent_id: callerAgentId(),
3105
- }));
3118
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3106
3119
  if (result?.status === 'pending_approval') {
3107
3120
  return {
3108
3121
  status: 'pending_approval',
@@ -3213,6 +3226,7 @@ const TOOLS = [
3213
3226
  vcc_id: { type: 'string', description: 'Optional. Defaults to session\'s last-created VCC, then most recent install-stamped active VCC with money2020-compatible merchant_lock.' },
3214
3227
  approval_id: { type: 'string', description: 'When retrying a previously-gated order (≥ $3000), pass the approval_id from the first call. Other args ignored on replay.' },
3215
3228
  inline_screenshot: { type: 'boolean', default: true, description: 'Embed an inline screenshot of the order confirmation page. Default true; pass false to skip.' },
3229
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
3216
3230
  },
3217
3231
  },
3218
3232
  handler: async (args) => {
@@ -3220,7 +3234,7 @@ const TOOLS = [
3220
3234
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
3221
3235
  if (approvalId) {
3222
3236
  try {
3223
- const result = unwrap(await client.post('/api/money2020/checkout', { approval_id: approvalId }));
3237
+ const result = unwrap(await client.post('/api/money2020/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3224
3238
  if (result?.status === 'pending_approval') {
3225
3239
  return {
3226
3240
  status: 'pending_approval',
@@ -3278,7 +3292,7 @@ const TOOLS = [
3278
3292
  vcc_id: vccId,
3279
3293
  agent_id: stampAgent('default'),
3280
3294
  caller_agent_id: callerAgentId(),
3281
- }));
3295
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3282
3296
  if (result?.status === 'pending_approval') {
3283
3297
  return {
3284
3298
  status: 'pending_approval',
@@ -3431,6 +3445,7 @@ const TOOLS = [
3431
3445
  // auto_open removed 2026-05-13: storefront page no longer
3432
3446
  // auto-launches in the OS browser. Click the markdown link in
3433
3447
  // the response instead.
3448
+ sk_test: { type: 'string', description: 'Optional sk_test_* seller API key. REQUIRED when the target VCC has an owner_account_id — only the owner\'s key may authorize the charge. Without it, owned cards return vcc_not_owned (HTTP 403).' },
3434
3449
  },
3435
3450
  },
3436
3451
  handler: async (args) => {
@@ -3438,7 +3453,7 @@ const TOOLS = [
3438
3453
  const approvalId = typeof args.approval_id === 'string' ? args.approval_id.trim() : '';
3439
3454
  if (approvalId) {
3440
3455
  try {
3441
- const result = unwrap(await client.post('/api/procurement/checkout', { approval_id: approvalId }));
3456
+ const result = unwrap(await client.post('/api/procurement/checkout', { approval_id: approvalId }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3442
3457
  if (result?.status === 'pending_approval') {
3443
3458
  return {
3444
3459
  status: 'pending_approval',
@@ -3519,7 +3534,7 @@ const TOOLS = [
3519
3534
  // Audit identity is the actual MCP caller — Spark bug #1.
3520
3535
  caller_agent_id: callerAgentId(),
3521
3536
  scheduled_for: scheduledFor,
3522
- }));
3537
+ }, { auth: typeof args.sk_test === 'string' && args.sk_test.trim() ? args.sk_test.trim() : undefined }));
3523
3538
  // Approval gate fired — surface the URL to the LLM.
3524
3539
  if (result?.status === 'pending_approval') {
3525
3540
  return {