@ductape/mcp 0.1.46 → 0.1.48

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/index.js CHANGED
@@ -576,6 +576,11 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
576
576
  databases.update [{ product, env, database, table, data: {key:value}, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="update", targets={database, table})
577
577
  databases.delete [{ product, env, database, table, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="delete", targets={database, table})
578
578
  databases.upsert [{ product, env, database, table, data: {key:value}, conflictKeys: string[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="upsert", targets={database, table})
579
+ NOTE on write operations (insert/update/delete/upsert): if the proxy returns "Authentication failed",
580
+ the publishable key does not have write access for that database. Write permissions are configured
581
+ in Workbench → Tokens → Publishable Key. An access key is required for write operations that are
582
+ not explicitly enabled for the publishable key. In that case the operation must be performed
583
+ server-side using a full Ductape SDK instance initialized with an access key.
579
584
  NOTE: ductape_generate_payload for databases returns:
580
585
  payload.input — ready-to-use input with real field names in where/data, plus session and cache inside input
581
586
  meta.schema_context.database.fields — { fieldName: { type, required, description?, sample? } } for the table
@@ -3418,7 +3423,14 @@ async function main() {
3418
3423
  return { content: [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }] };
3419
3424
  }
3420
3425
  catch (err) {
3421
- const message = err instanceof Error ? err.message : String(err);
3426
+ let message = err instanceof Error ? err.message : String(err);
3427
+ const isAuthFailed = /authentication failed/i.test(message);
3428
+ const isDbWrite = args.module === 'databases' && /^(insert|update|delete|upsert)$/.test(args.method);
3429
+ if (isAuthFailed && isDbWrite) {
3430
+ message += '\n\nThe publishable key does not have write access for this database operation. ' +
3431
+ 'Enable it in Workbench → Tokens → Publishable Key. ' +
3432
+ 'If write access cannot be granted to the publishable key, perform this operation server-side using a full Ductape SDK instance initialized with an access key.';
3433
+ }
3422
3434
  return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
3423
3435
  }
3424
3436
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "MCP server that exposes Ductape SDK operations via the backend proxy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -587,6 +587,11 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
587
587
  databases.update [{ product, env, database, table, data: {key:value}, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="update", targets={database, table})
588
588
  databases.delete [{ product, env, database, table, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="delete", targets={database, table})
589
589
  databases.upsert [{ product, env, database, table, data: {key:value}, conflictKeys: string[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="upsert", targets={database, table})
590
+ NOTE on write operations (insert/update/delete/upsert): if the proxy returns "Authentication failed",
591
+ the publishable key does not have write access for that database. Write permissions are configured
592
+ in Workbench → Tokens → Publishable Key. An access key is required for write operations that are
593
+ not explicitly enabled for the publishable key. In that case the operation must be performed
594
+ server-side using a full Ductape SDK instance initialized with an access key.
590
595
  NOTE: ductape_generate_payload for databases returns:
591
596
  payload.input — ready-to-use input with real field names in where/data, plus session and cache inside input
592
597
  meta.schema_context.database.fields — { fieldName: { type, required, description?, sample? } } for the table
@@ -3517,7 +3522,14 @@ async function main() {
3517
3522
  const result = await executeViaProxy(key, proxyModule, args.method, params);
3518
3523
  return { content: [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }] };
3519
3524
  } catch (err) {
3520
- const message = err instanceof Error ? err.message : String(err);
3525
+ let message = err instanceof Error ? err.message : String(err);
3526
+ const isAuthFailed = /authentication failed/i.test(message);
3527
+ const isDbWrite = args.module === 'databases' && /^(insert|update|delete|upsert)$/.test(args.method);
3528
+ if (isAuthFailed && isDbWrite) {
3529
+ message += '\n\nThe publishable key does not have write access for this database operation. ' +
3530
+ 'Enable it in Workbench → Tokens → Publishable Key. ' +
3531
+ 'If write access cannot be granted to the publishable key, perform this operation server-side using a full Ductape SDK instance initialized with an access key.';
3532
+ }
3521
3533
  return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
3522
3534
  }
3523
3535
  };