@ductape/mcp 0.1.47 → 0.1.49
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 +64 -3
- package/package.json +1 -1
- package/src/index.ts +65 -3
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
|
|
@@ -1187,9 +1192,58 @@ const docsInputSchema = z.object({
|
|
|
1187
1192
|
topic: z.string().describe('Feature topic to look up. Supported: ' +
|
|
1188
1193
|
'transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
1189
1194
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
1190
|
-
'notifications, resilience, features, events, logs'),
|
|
1195
|
+
'notifications, resilience, features, events, logs, frontend, client, react, vue'),
|
|
1191
1196
|
});
|
|
1192
1197
|
const DOCS = {
|
|
1198
|
+
frontend: `
|
|
1199
|
+
DUCTAPE FRONTEND SDK GUIDE
|
|
1200
|
+
|
|
1201
|
+
Choose one integration package:
|
|
1202
|
+
React 17+ — npm install @ductape/react
|
|
1203
|
+
Provider and hooks built on @ductape/client.
|
|
1204
|
+
Continue with ductape_docs({ topic: "react" }).
|
|
1205
|
+
Vue 3+ — npm install @ductape/vue
|
|
1206
|
+
Plugin and composables built on @ductape/client.
|
|
1207
|
+
Continue with ductape_docs({ topic: "vue" }).
|
|
1208
|
+
Other UI — npm install @ductape/client
|
|
1209
|
+
frameworks Use directly with Svelte, Angular, vanilla JavaScript, or a custom adapter.
|
|
1210
|
+
Continue with ductape_docs({ topic: "client" }).
|
|
1211
|
+
|
|
1212
|
+
Do not install @ductape/client separately when using @ductape/react or @ductape/vue unless the
|
|
1213
|
+
application also needs direct access to a client API not exposed by the framework package. Both
|
|
1214
|
+
framework packages wrap @ductape/client and expose the underlying client through useDuctape().
|
|
1215
|
+
|
|
1216
|
+
SHARED APPLICATION LIFECYCLE
|
|
1217
|
+
1. Create one client at the application root using a browser-safe publishableKey, proxy baseUrl,
|
|
1218
|
+
default product tag, and environment slug.
|
|
1219
|
+
2. Connect the real-time client only in the browser. In React use DuctapeProvider autoConnect or
|
|
1220
|
+
connect() after mount; in Vue use createDuctape({ autoConnect: true }) or connect() in onMounted.
|
|
1221
|
+
3. Authenticate the player with the sessions API and retain the returned session token according
|
|
1222
|
+
to the application's security policy. Refresh it before expiry (the React/Vue packages provide
|
|
1223
|
+
useSessionAutoRefresh) and revoke it on logout.
|
|
1224
|
+
4. Pass the session value when connecting a broker that requires player-scoped authorization.
|
|
1225
|
+
5. Subscribe through the framework hook/composable or the client service. Always unsubscribe on
|
|
1226
|
+
component teardown; the framework integrations do this automatically for declarative hooks.
|
|
1227
|
+
6. The underlying client reconnects its WebSocket and restores active subscriptions. Observe
|
|
1228
|
+
connectionState to render disconnected/reconnecting UI; do not create duplicate subscriptions.
|
|
1229
|
+
7. Disconnect resource sessions and the root client when the owning application scope is torn down.
|
|
1230
|
+
|
|
1231
|
+
AUTHENTICATION AND SECURITY
|
|
1232
|
+
- Use publishableKey in browser applications. Never ship workspace private keys or privileged
|
|
1233
|
+
access keys in frontend bundles.
|
|
1234
|
+
- A Ductape player session and the real-time transport connection are separate: authenticate or
|
|
1235
|
+
refresh the session, then use that session when opening player-scoped broker resources.
|
|
1236
|
+
- For SSR, create/connect the real-time client only on the browser side.
|
|
1237
|
+
|
|
1238
|
+
MIGRATING A CUSTOM WRAPPER
|
|
1239
|
+
- Keep @ductape/client when the wrapper implements application-specific projection or state logic.
|
|
1240
|
+
- For React, move root connection ownership to DuctapeProvider, replace imperative subscriptions
|
|
1241
|
+
with useBroker/useBrokerSubscription, and keep projection reduction in an application hook.
|
|
1242
|
+
- For Vue, move root ownership to createDuctape(), replace imperative subscriptions with
|
|
1243
|
+
useBroker/useBrokerSubscription, and keep projection reduction in an application composable.
|
|
1244
|
+
- Verify session handoff, initial loading state, error state, reconnect UI, subscription cleanup,
|
|
1245
|
+
and duplicate-event behavior with a live end-to-end run before removing the old wrapper.
|
|
1246
|
+
`.trim(),
|
|
1193
1247
|
transactions: `
|
|
1194
1248
|
DUCTAPE DATABASE TRANSACTIONS
|
|
1195
1249
|
|
|
@@ -3418,7 +3472,14 @@ async function main() {
|
|
|
3418
3472
|
return { content: [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }] };
|
|
3419
3473
|
}
|
|
3420
3474
|
catch (err) {
|
|
3421
|
-
|
|
3475
|
+
let message = err instanceof Error ? err.message : String(err);
|
|
3476
|
+
const isAuthFailed = /authentication failed/i.test(message);
|
|
3477
|
+
const isDbWrite = args.module === 'databases' && /^(insert|update|delete|upsert)$/.test(args.method);
|
|
3478
|
+
if (isAuthFailed && isDbWrite) {
|
|
3479
|
+
message += '\n\nThe publishable key does not have write access for this database operation. ' +
|
|
3480
|
+
'Enable it in Workbench → Tokens → Publishable Key. ' +
|
|
3481
|
+
'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.';
|
|
3482
|
+
}
|
|
3422
3483
|
return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
|
|
3423
3484
|
}
|
|
3424
3485
|
};
|
|
@@ -3537,7 +3598,7 @@ async function main() {
|
|
|
3537
3598
|
'index strategy, operation types) that should be confirmed with the user first.\n\n' +
|
|
3538
3599
|
'Available topics: transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
3539
3600
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
3540
|
-
'notifications, resilience, features, events, logs, client, react, vue',
|
|
3601
|
+
'notifications, resilience, features, events, logs, frontend, client, react, vue',
|
|
3541
3602
|
inputSchema: docsInputSchema,
|
|
3542
3603
|
}, docsHandler);
|
|
3543
3604
|
server.registerTool('ductape_cli', {
|
package/package.json
CHANGED
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
|
|
@@ -1237,11 +1242,61 @@ const docsInputSchema = z.object({
|
|
|
1237
1242
|
'Feature topic to look up. Supported: ' +
|
|
1238
1243
|
'transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
1239
1244
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
1240
|
-
'notifications, resilience, features, events, logs',
|
|
1245
|
+
'notifications, resilience, features, events, logs, frontend, client, react, vue',
|
|
1241
1246
|
),
|
|
1242
1247
|
});
|
|
1243
1248
|
|
|
1244
1249
|
const DOCS: Record<string, string> = {
|
|
1250
|
+
frontend: `
|
|
1251
|
+
DUCTAPE FRONTEND SDK GUIDE
|
|
1252
|
+
|
|
1253
|
+
Choose one integration package:
|
|
1254
|
+
React 17+ — npm install @ductape/react
|
|
1255
|
+
Provider and hooks built on @ductape/client.
|
|
1256
|
+
Continue with ductape_docs({ topic: "react" }).
|
|
1257
|
+
Vue 3+ — npm install @ductape/vue
|
|
1258
|
+
Plugin and composables built on @ductape/client.
|
|
1259
|
+
Continue with ductape_docs({ topic: "vue" }).
|
|
1260
|
+
Other UI — npm install @ductape/client
|
|
1261
|
+
frameworks Use directly with Svelte, Angular, vanilla JavaScript, or a custom adapter.
|
|
1262
|
+
Continue with ductape_docs({ topic: "client" }).
|
|
1263
|
+
|
|
1264
|
+
Do not install @ductape/client separately when using @ductape/react or @ductape/vue unless the
|
|
1265
|
+
application also needs direct access to a client API not exposed by the framework package. Both
|
|
1266
|
+
framework packages wrap @ductape/client and expose the underlying client through useDuctape().
|
|
1267
|
+
|
|
1268
|
+
SHARED APPLICATION LIFECYCLE
|
|
1269
|
+
1. Create one client at the application root using a browser-safe publishableKey, proxy baseUrl,
|
|
1270
|
+
default product tag, and environment slug.
|
|
1271
|
+
2. Connect the real-time client only in the browser. In React use DuctapeProvider autoConnect or
|
|
1272
|
+
connect() after mount; in Vue use createDuctape({ autoConnect: true }) or connect() in onMounted.
|
|
1273
|
+
3. Authenticate the player with the sessions API and retain the returned session token according
|
|
1274
|
+
to the application's security policy. Refresh it before expiry (the React/Vue packages provide
|
|
1275
|
+
useSessionAutoRefresh) and revoke it on logout.
|
|
1276
|
+
4. Pass the session value when connecting a broker that requires player-scoped authorization.
|
|
1277
|
+
5. Subscribe through the framework hook/composable or the client service. Always unsubscribe on
|
|
1278
|
+
component teardown; the framework integrations do this automatically for declarative hooks.
|
|
1279
|
+
6. The underlying client reconnects its WebSocket and restores active subscriptions. Observe
|
|
1280
|
+
connectionState to render disconnected/reconnecting UI; do not create duplicate subscriptions.
|
|
1281
|
+
7. Disconnect resource sessions and the root client when the owning application scope is torn down.
|
|
1282
|
+
|
|
1283
|
+
AUTHENTICATION AND SECURITY
|
|
1284
|
+
- Use publishableKey in browser applications. Never ship workspace private keys or privileged
|
|
1285
|
+
access keys in frontend bundles.
|
|
1286
|
+
- A Ductape player session and the real-time transport connection are separate: authenticate or
|
|
1287
|
+
refresh the session, then use that session when opening player-scoped broker resources.
|
|
1288
|
+
- For SSR, create/connect the real-time client only on the browser side.
|
|
1289
|
+
|
|
1290
|
+
MIGRATING A CUSTOM WRAPPER
|
|
1291
|
+
- Keep @ductape/client when the wrapper implements application-specific projection or state logic.
|
|
1292
|
+
- For React, move root connection ownership to DuctapeProvider, replace imperative subscriptions
|
|
1293
|
+
with useBroker/useBrokerSubscription, and keep projection reduction in an application hook.
|
|
1294
|
+
- For Vue, move root ownership to createDuctape(), replace imperative subscriptions with
|
|
1295
|
+
useBroker/useBrokerSubscription, and keep projection reduction in an application composable.
|
|
1296
|
+
- Verify session handoff, initial loading state, error state, reconnect UI, subscription cleanup,
|
|
1297
|
+
and duplicate-event behavior with a live end-to-end run before removing the old wrapper.
|
|
1298
|
+
`.trim(),
|
|
1299
|
+
|
|
1245
1300
|
transactions: `
|
|
1246
1301
|
DUCTAPE DATABASE TRANSACTIONS
|
|
1247
1302
|
|
|
@@ -3517,7 +3572,14 @@ async function main() {
|
|
|
3517
3572
|
const result = await executeViaProxy(key, proxyModule, args.method, params);
|
|
3518
3573
|
return { content: [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }] };
|
|
3519
3574
|
} catch (err) {
|
|
3520
|
-
|
|
3575
|
+
let message = err instanceof Error ? err.message : String(err);
|
|
3576
|
+
const isAuthFailed = /authentication failed/i.test(message);
|
|
3577
|
+
const isDbWrite = args.module === 'databases' && /^(insert|update|delete|upsert)$/.test(args.method);
|
|
3578
|
+
if (isAuthFailed && isDbWrite) {
|
|
3579
|
+
message += '\n\nThe publishable key does not have write access for this database operation. ' +
|
|
3580
|
+
'Enable it in Workbench → Tokens → Publishable Key. ' +
|
|
3581
|
+
'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.';
|
|
3582
|
+
}
|
|
3521
3583
|
return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
|
|
3522
3584
|
}
|
|
3523
3585
|
};
|
|
@@ -3670,7 +3732,7 @@ async function main() {
|
|
|
3670
3732
|
'index strategy, operation types) that should be confirmed with the user first.\n\n' +
|
|
3671
3733
|
'Available topics: transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
3672
3734
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
3673
|
-
'notifications, resilience, features, events, logs, client, react, vue',
|
|
3735
|
+
'notifications, resilience, features, events, logs, frontend, client, react, vue',
|
|
3674
3736
|
inputSchema: docsInputSchema,
|
|
3675
3737
|
},
|
|
3676
3738
|
docsHandler,
|