@ductape/mcp 0.2.16 → 0.2.17
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 +127 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -445,7 +445,9 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
445
445
|
ductape_cli("products create --name <name> --tag <tag>")
|
|
446
446
|
ductape_cli("products environments list <tag> --json")
|
|
447
447
|
ductape_cli("products environments get <tag> <slug> --json")
|
|
448
|
-
ductape_cli("products apps list --product <
|
|
448
|
+
ductape_cli("products apps list --product <id_or_tag> --json") ← compact linked apps only
|
|
449
|
+
ductape_cli("products apps actions list --product <id_or_tag> --app <app_tag> --json")
|
|
450
|
+
ductape_cli("products apps actions get --product <id_or_tag> --app <app_tag> --action <action_tag> --json")
|
|
449
451
|
|
|
450
452
|
SDK method signatures (for reference, admin key only):
|
|
451
453
|
product.create [data: { name, description, tag?, envs?: [{slug, name}] }]
|
|
@@ -1086,6 +1088,25 @@ const snippetGenerateInputSchema = payloadGenerateInputSchema.extend({
|
|
|
1086
1088
|
const schemaInputSchema = z.object({
|
|
1087
1089
|
module: z.enum(['app', 'product']).optional().describe('Optional. Scope the result to one module. With no method, returns only the compact list of available methods.'),
|
|
1088
1090
|
method: z.string().optional().describe('Optional method key such as "databases.create" or "notifications.update". Use with module to return only that method schema.'),
|
|
1091
|
+
product_tag: z.string().optional().describe('For live app-action discovery, the product the app is linked to. Must be supplied with app_tag and action_tag.'),
|
|
1092
|
+
app_tag: z.string().optional().describe('For live app-action discovery, the linked app tag. Must be supplied with product_tag and action_tag.'),
|
|
1093
|
+
action_tag: z.string().optional().describe('For live app-action discovery, the exact action tag whose complete contract should be returned.'),
|
|
1094
|
+
});
|
|
1095
|
+
const marketplaceDiscoverInputSchema = z.object({
|
|
1096
|
+
query: z.string().min(1).describe('Capability or provider search, for example "payments" or "paystack".'),
|
|
1097
|
+
category: z.string().optional().describe('Optional marketplace category/domain filter.'),
|
|
1098
|
+
limit: z.number().int().min(1).max(50).optional().default(10),
|
|
1099
|
+
});
|
|
1100
|
+
const marketplaceConnectInputSchema = z.object({
|
|
1101
|
+
product_tag: z.string().min(1).describe('Product that should receive the marketplace app connection.'),
|
|
1102
|
+
app_tag: z.string().min(1).describe('Exact public app tag returned by ductape_marketplace_discover.'),
|
|
1103
|
+
environments: z.array(z.object({
|
|
1104
|
+
app_env_slug: z.string().min(1),
|
|
1105
|
+
product_env_slug: z.string().min(1),
|
|
1106
|
+
})).min(1).describe('Explicit app-to-product environment mappings. Include every product environment that will use the app.'),
|
|
1107
|
+
});
|
|
1108
|
+
const marketplaceInspectInputSchema = z.object({
|
|
1109
|
+
app_tag: z.string().min(1).describe('Exact public app tag returned by ductape_marketplace_discover.'),
|
|
1089
1110
|
});
|
|
1090
1111
|
function toPrettyJson(value) {
|
|
1091
1112
|
return JSON.stringify(value ?? {}, null, 2);
|
|
@@ -2636,17 +2657,27 @@ An App must be fully set up in Ductape before any code can use it:
|
|
|
2636
2657
|
5. The App must be connected to the product (product.apps.add) and its envs mapped
|
|
2637
2658
|
|
|
2638
2659
|
DISCOVER BEFORE CREATING:
|
|
2639
|
-
|
|
2640
|
-
|
|
2660
|
+
ductape_marketplace_discover({ query: "payments" })
|
|
2661
|
+
ductape_marketplace_discover({ query: "paystack" })
|
|
2641
2662
|
ductape_cli("marketplace categories --json")
|
|
2642
|
-
|
|
2663
|
+
ductape_marketplace_inspect({ app_tag: "<exact-returned-tag>" })
|
|
2643
2664
|
|
|
2644
2665
|
marketplace search matches capability terms against public app names, tags, descriptions,
|
|
2645
|
-
categories, actions, and webhooks.
|
|
2646
|
-
including the exact
|
|
2666
|
+
categories, actions, and webhooks. Marketplace inspect returns a compact current-version definition,
|
|
2667
|
+
including the exact action tags and body/query/header/param schemas. Never infer
|
|
2647
2668
|
Paystack action names such as "initialize" or "verify": inspect the marketplace record first.
|
|
2648
2669
|
If no suitable app exists, create one or import Paystack's OpenAPI/Postman definition.
|
|
2649
2670
|
|
|
2671
|
+
CONNECT A DISCOVERED APP THROUGH MCP:
|
|
2672
|
+
1. Run ductape_marketplace_discover and select an exact returned app tag.
|
|
2673
|
+
2. Run ductape_marketplace_inspect to read its environments and compact action contracts.
|
|
2674
|
+
3. Read product environments with ductape_cli("products environments list <product_tag> --json").
|
|
2675
|
+
4. Match each product environment explicitly to one environment exposed by the app.
|
|
2676
|
+
5. Call ductape_marketplace_connect({ product_tag, app_tag, environments }).
|
|
2677
|
+
6. Verify with ductape_cli("products apps list --product <product_tag> --json").
|
|
2678
|
+
Never guess environment mappings or action tags. Connecting mutates product configuration;
|
|
2679
|
+
obtain user approval when the user has not already requested the connection.
|
|
2680
|
+
|
|
2650
2681
|
ONLY after all five steps can any code call:
|
|
2651
2682
|
ctx.api.run({ app: '<app_tag>', event: '<action_tag>', input: { ... } }) ← in a feature handler
|
|
2652
2683
|
actions.run([{ product, env, app: '<app_tag>', action: '<action_tag>', input }]) ← at runtime
|
|
@@ -2676,18 +2707,21 @@ Manage environments (base URLs per stage) in Workbench; this currently has no CL
|
|
|
2676
2707
|
|
|
2677
2708
|
Discover apps in a product and their actions (ALWAYS do this before writing any ctx.api.run call):
|
|
2678
2709
|
Step 1 — list apps connected to the product:
|
|
2679
|
-
ductape_cli("products
|
|
2680
|
-
|
|
2681
|
-
Step 2 — list
|
|
2682
|
-
|
|
2683
|
-
Step 3 — fetch
|
|
2684
|
-
|
|
2710
|
+
ductape_cli("products apps list --product <product_id_or_tag> --json")
|
|
2711
|
+
→ compact list containing ONLY apps linked to that product; accepts an id or tag
|
|
2712
|
+
Step 2 — list compact action summaries for one linked app:
|
|
2713
|
+
ductape_cli("products apps actions list --product <product_id_or_tag> --app <app_tag> --json")
|
|
2714
|
+
Step 3 — fetch one complete action contract:
|
|
2715
|
+
ductape_cli("products apps actions get --product <product_id_or_tag> --app <app_tag> --action <action_tag> --json")
|
|
2716
|
+
OR ductape_schema({ product_tag: "<product_tag>", app_tag: "<app_tag>", action_tag: "<action_tag>" })
|
|
2685
2717
|
→ returns { body: {fieldName: {type, required}}, params: {}, query: {}, headers: {} }
|
|
2686
2718
|
OR: call ductape_generate_payload (operation_family="action", method="run",
|
|
2687
2719
|
targets={app: "app_tag", action: "action_tag"}) to get the exact resolved payload shape
|
|
2688
2720
|
Step 4 — call ductape_schema({ module: "app" }) if you need the JSON schema for creating/updating
|
|
2689
2721
|
app resources (not for runtime input — use actions.fetch or ductape_generate_payload for that)
|
|
2690
2722
|
NEVER assume action input field names. Always fetch the action definition first.
|
|
2723
|
+
NEVER fetch products get, apps get, marketplace get, or products apps list --full merely to inspect
|
|
2724
|
+
one action. Those expanded catalogues can be very large and may exceed MCP/client token limits.
|
|
2691
2725
|
|
|
2692
2726
|
Manage actions (individual API endpoints) in Workbench or import an OpenAPI/Postman file.
|
|
2693
2727
|
Creation/update are administrative and must never use ductape_execute.
|
|
@@ -2746,11 +2780,11 @@ Connecting an app to a product (after creation):
|
|
|
2746
2780
|
3. Configure auth: Workbench
|
|
2747
2781
|
4. Define actions: Workbench
|
|
2748
2782
|
OR import: ductape_cli("apps import <file.json> -t postman|openapi")
|
|
2749
|
-
5. Connect to product: Requires the product_id
|
|
2783
|
+
5. Connect to product: Requires the product_id.
|
|
2750
2784
|
There is no CLI command for this step — the SDK product.apps.add method requires
|
|
2751
2785
|
an access key which only the backend can provide. Connect via Workbench.
|
|
2752
|
-
6. Verify: ductape_cli("products
|
|
2753
|
-
|
|
2786
|
+
6. Verify: ductape_cli("products apps list --product <product_tag> --json")
|
|
2787
|
+
ductape_cli("products apps actions list --product <product_tag> --app <app_tag> --json")
|
|
2754
2788
|
`.trim(),
|
|
2755
2789
|
products: `
|
|
2756
2790
|
DUCTAPE PRODUCTS
|
|
@@ -3524,7 +3558,8 @@ STEP 1 — UNDERSTAND the goal
|
|
|
3524
3558
|
understand: what the feature does, what it returns, what can fail and how failures should behave.
|
|
3525
3559
|
|
|
3526
3560
|
STEP 2 — INVENTORY existing Ductape components
|
|
3527
|
-
Call ductape_cli("products
|
|
3561
|
+
Call ductape_cli("products components list --product-tag <product_tag> --json") for the compact inventory.
|
|
3562
|
+
Call ductape_cli("products apps list --product <product_tag> --json") for linked apps only.
|
|
3528
3563
|
(product.* requires the access key — never use ductape_execute for product reads, it will return 403)
|
|
3529
3564
|
Note what already exists:
|
|
3530
3565
|
- databases[] → available for ctx.database.insert/query/update/delete steps
|
|
@@ -3616,10 +3651,25 @@ STEP 8 — SET rollbacks for reversible steps
|
|
|
3616
3651
|
async (result) => ctx.api.run({ app: 'stripe', event: 'refund', input: { chargeId: result.id } })
|
|
3617
3652
|
);
|
|
3618
3653
|
|
|
3619
|
-
Code-first ctx step types currently record: function | action | database | graph | vector |
|
|
3654
|
+
Code-first ctx step types currently record: function | action | database | graph | vector | session |
|
|
3620
3655
|
notification | storage | produce | quota | fallback | child_feature | sleep | wait_for_signal |
|
|
3621
3656
|
checkpoint.
|
|
3622
3657
|
|
|
3658
|
+
CODE-FIRST SESSION LIFECYCLE:
|
|
3659
|
+
ctx.session is the optional session token inherited by the Feature and all nested Ductape
|
|
3660
|
+
operations. It is read-only execution context and is not a session service.
|
|
3661
|
+
ctx.sessions records explicit product-session lifecycle steps:
|
|
3662
|
+
ctx.sessions.start<T>({ session: "player-session", data, cache? })
|
|
3663
|
+
ctx.sessions.verify<T>({ session: "player-session", token, cache? })
|
|
3664
|
+
ctx.sessions.refresh<T>({ session: "player-session", refreshToken, cache? })
|
|
3665
|
+
ctx.sessions.revoke({ session: "player-session", sessionId?, identifier? })
|
|
3666
|
+
ctx.sessions.list<T>({ session: "player-session", identifier?, page?, limit?, cache? })
|
|
3667
|
+
Put each call inside ctx.step(). The session field identifies the configured product session; the
|
|
3668
|
+
executor supplies product and env. start creates a new token pair but does not replace ctx.session
|
|
3669
|
+
for subsequent steps in the same Feature. Pass the returned token explicitly where application
|
|
3670
|
+
logic needs the newly created session. Never serialize the inherited ctx.session into the Feature
|
|
3671
|
+
definition, logs, metadata, or another step unless the target operation explicitly requires a token.
|
|
3672
|
+
|
|
3623
3673
|
Valid synchronous Feature candidates include generate-world, resolve-nation-turn,
|
|
3624
3674
|
calculate-route-capacity, price-subscription, evaluate-entitlement, and build-replay.
|
|
3625
3675
|
|
|
@@ -5376,6 +5426,35 @@ async function main() {
|
|
|
5376
5426
|
};
|
|
5377
5427
|
const schemaHandler = async (args) => {
|
|
5378
5428
|
try {
|
|
5429
|
+
const liveActionScope = [args.product_tag, args.app_tag, args.action_tag];
|
|
5430
|
+
if (liveActionScope.some(Boolean)) {
|
|
5431
|
+
if (!liveActionScope.every(Boolean)) {
|
|
5432
|
+
throw new Error('product_tag, app_tag, and action_tag are all required to fetch a live app action contract');
|
|
5433
|
+
}
|
|
5434
|
+
const response = await cliHandler({
|
|
5435
|
+
command: `products apps actions get --product ${shellArgument(args.product_tag)} --app ${shellArgument(args.app_tag)} --action ${shellArgument(args.action_tag)} --json`,
|
|
5436
|
+
});
|
|
5437
|
+
if (response.isError)
|
|
5438
|
+
return response;
|
|
5439
|
+
const raw = response.content[0]?.type === 'text' ? response.content[0].text : '';
|
|
5440
|
+
let action = raw;
|
|
5441
|
+
try {
|
|
5442
|
+
action = JSON.parse(raw);
|
|
5443
|
+
}
|
|
5444
|
+
catch { /* Preserve the CLI diagnostic verbatim. */ }
|
|
5445
|
+
return {
|
|
5446
|
+
content: [{
|
|
5447
|
+
type: 'text',
|
|
5448
|
+
text: JSON.stringify({
|
|
5449
|
+
product_tag: args.product_tag,
|
|
5450
|
+
app_tag: args.app_tag,
|
|
5451
|
+
action_tag: args.action_tag,
|
|
5452
|
+
action,
|
|
5453
|
+
hint: 'This is the complete contract for one action linked to this product; use products apps actions list for compact discovery.',
|
|
5454
|
+
}, null, 2),
|
|
5455
|
+
}],
|
|
5456
|
+
};
|
|
5457
|
+
}
|
|
5379
5458
|
if (args.method && !args.module) {
|
|
5380
5459
|
throw new Error('module is required when method is provided');
|
|
5381
5460
|
}
|
|
@@ -5465,9 +5544,10 @@ async function main() {
|
|
|
5465
5544
|
}, snippetGenerateHandler);
|
|
5466
5545
|
server.registerTool('ductape_schema', {
|
|
5467
5546
|
title: 'Ductape Asset Schema',
|
|
5468
|
-
description: 'Returns a compact method index
|
|
5547
|
+
description: 'Returns a compact method index, one targeted asset schema, or one complete live app-action contract. ' +
|
|
5469
5548
|
'Call with module="app" or module="product" first to list method keys, then call again with ' +
|
|
5470
5549
|
'module and method (for example method="databases.create") for the complete field schema. ' +
|
|
5550
|
+
'For one linked app action, call with product_tag, app_tag, and action_tag; do not fetch a full app catalogue. ' +
|
|
5471
5551
|
'Avoid calling without module unless you explicitly need the entire manifest.\n\n' +
|
|
5472
5552
|
'ALWAYS call this before constructing a file for "resources <type> create" or any cloud ' +
|
|
5473
5553
|
'import/provision operation — field shapes are not guessable from context.\n\n' +
|
|
@@ -5542,6 +5622,35 @@ async function main() {
|
|
|
5542
5622
|
'Supports in-place and new-codebase guidance destinations. Read-only unless write or ensure_product is explicitly enabled.',
|
|
5543
5623
|
inputSchema: migrationInputSchema,
|
|
5544
5624
|
}, migrationHandler);
|
|
5625
|
+
server.registerTool('ductape_marketplace_discover', {
|
|
5626
|
+
title: 'Discover Ductape Marketplace Apps',
|
|
5627
|
+
description: 'Search public marketplace apps by capability and return compact app, environment, and action summaries. ' +
|
|
5628
|
+
'Use the returned exact app tag; never infer provider or action tags from a brand name.',
|
|
5629
|
+
inputSchema: marketplaceDiscoverInputSchema,
|
|
5630
|
+
}, async (args) => cliHandler({
|
|
5631
|
+
command: `marketplace search ${shellArgument(args.query)}${args.category ? ` --category ${shellArgument(args.category)}` : ''} --limit ${args.limit ?? 10} --json`,
|
|
5632
|
+
}));
|
|
5633
|
+
server.registerTool('ductape_marketplace_inspect', {
|
|
5634
|
+
title: 'Inspect a Ductape Marketplace App',
|
|
5635
|
+
description: 'Return the selected public app version, supported environment slugs, and compact action contracts. ' +
|
|
5636
|
+
'Call this after discovery and before choosing environment mappings or writing action calls.',
|
|
5637
|
+
inputSchema: marketplaceInspectInputSchema,
|
|
5638
|
+
}, async (args) => cliHandler({
|
|
5639
|
+
command: `marketplace get ${shellArgument(args.app_tag)} --json`,
|
|
5640
|
+
}));
|
|
5641
|
+
server.registerTool('ductape_marketplace_connect', {
|
|
5642
|
+
title: 'Connect a Marketplace App to a Product',
|
|
5643
|
+
description: 'Create/reuse secure app access, connect an exact discovered marketplace app to a product, and map its environments. ' +
|
|
5644
|
+
'Discover first, inspect the returned environments/actions, obtain any required user configuration, and never guess mappings.',
|
|
5645
|
+
inputSchema: marketplaceConnectInputSchema,
|
|
5646
|
+
}, async (args) => {
|
|
5647
|
+
const mappings = args.environments
|
|
5648
|
+
.map((env) => ` --env-map ${shellArgument(`${env.app_env_slug}:${env.product_env_slug}`)}`)
|
|
5649
|
+
.join('');
|
|
5650
|
+
return cliHandler({
|
|
5651
|
+
command: `products apps connect --product ${shellArgument(args.product_tag)} --app ${shellArgument(args.app_tag)}${mappings} --json`,
|
|
5652
|
+
});
|
|
5653
|
+
});
|
|
5545
5654
|
server.registerTool('ductape_cli', {
|
|
5546
5655
|
title: 'Ductape CLI',
|
|
5547
5656
|
description: 'Run a Ductape CLI command for administrative operations.\n\n' +
|