@ductape/mcp 0.2.0 → 0.2.1
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/CHANGELOG.md +6 -0
- package/README.md +14 -1
- package/dist/index.js +201 -25
- package/docs/TOOLS.md +14 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Broadened Feature guidance from durable/event-driven workflows to synchronous or asynchronous named product capabilities.
|
|
6
|
+
- Added evidence-backed `FEATURE`, `FEATURE_STEP`, `DOMAIN_SERVICE`, `UTILITY`, and `INFRASTRUCTURE_ADAPTER` classification guidance.
|
|
7
|
+
- Added synchronous multi-step examples and repository discovery/grouping rules.
|
|
8
|
+
|
|
3
9
|
## 0.2.0 - 2026-07-26
|
|
4
10
|
|
|
5
11
|
- Added exhaustive AI-led migration guidance for TypeScript, Go, Java, and .NET.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Migration guidance is available from `ductape_docs({ topic: "migration" })`. It starts with an original E2E
|
|
4
4
|
baseline, defaults to a separate new codebase, requires contextual review and strict parity evidence, and ends
|
|
5
|
-
against the unchanged original E2E suite. Administrative work
|
|
5
|
+
against the unchanged original E2E suite. Administrative work and marketplace discovery use `ductape_cli`; `ductape_execute` remains
|
|
6
6
|
publishable-key runtime-only. MCP never accepts or forwards `DUCTAPE_ACCESS_KEY`.
|
|
7
7
|
|
|
8
8
|
MCP (Model Context Protocol) server that exposes **Ductape SDK** operations as tools. All calls go through the **Ductape backend proxy** at a fixed URL; the SDK never runs in the MCP process. It is completely stateless; you provide your **Publishable Key** per execution.
|
|
@@ -82,6 +82,19 @@ The server exposes **three tools**:
|
|
|
82
82
|
- ready-to-copy SDK snippet in `typescript` or `python`
|
|
83
83
|
- Intended for engineers and copilots that need executable examples quickly.
|
|
84
84
|
|
|
85
|
+
The `ductape_cli` MCP tool also exposes public app discovery:
|
|
86
|
+
`marketplace search <capability>`, `marketplace categories`, and
|
|
87
|
+
`marketplace get <app_tag>`. Inspect the app before generating or executing an action payload.
|
|
88
|
+
|
|
89
|
+
## Feature classification
|
|
90
|
+
|
|
91
|
+
`ductape_docs({ topic: "features" })` treats a Feature as a named, reusable product capability
|
|
92
|
+
with a stable input/output contract and a useful managed-execution boundary. Features may be
|
|
93
|
+
synchronous and entirely local; Events, signals, schedules, waits, retries, and rollback are
|
|
94
|
+
optional patterns. Repository analysis distinguishes `FEATURE`, `FEATURE_STEP`, `DOMAIN_SERVICE`,
|
|
95
|
+
`UTILITY`, and `INFRASTRUCTURE_ADAPTER`, explains its evidence, and groups related low-level
|
|
96
|
+
operations instead of turning every exported function into a Feature.
|
|
97
|
+
|
|
85
98
|
## Security
|
|
86
99
|
|
|
87
100
|
- Passing the `publishable_key` on a per-request basis guarantees that each execution is isolated. This architecture safely supports deployments that multiplex multiple user connections in a single server thread (e.g., SSE), avoiding cross-tenant leakage.
|
package/dist/index.js
CHANGED
|
@@ -725,6 +725,10 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
725
725
|
━━━ MODULE: features ━━━
|
|
726
726
|
Feature definitions are code-first. Use features.define in application source; do not call
|
|
727
727
|
administrative create/update/delete methods through ductape_execute.
|
|
728
|
+
A Feature is a named, reusable product capability with a stable input/output contract that
|
|
729
|
+
benefits from managed execution, composition, observability, retries, versioning, policy
|
|
730
|
+
enforcement, or explicit execution steps. It may execute synchronously and entirely locally.
|
|
731
|
+
Signals, Events, schedules, waits, checkpoints, compensation, and rollback are optional patterns.
|
|
728
732
|
features.fetch [product_tag, feature_tag]
|
|
729
733
|
features.fetchAll [product_tag]
|
|
730
734
|
|
|
@@ -1129,7 +1133,7 @@ const ADMIN_SUBCOMMANDS = [
|
|
|
1129
1133
|
'profiles',
|
|
1130
1134
|
'workspaces',
|
|
1131
1135
|
'link', 'unlink', 'init',
|
|
1132
|
-
'products', 'apps',
|
|
1136
|
+
'products', 'apps', 'marketplace',
|
|
1133
1137
|
'resources',
|
|
1134
1138
|
'notifications',
|
|
1135
1139
|
'events',
|
|
@@ -1436,9 +1440,12 @@ COMPONENT DECISIONS
|
|
|
1436
1440
|
Databases/transactions → Ductape Database; brokers/queues → Events; object stores → Storage;
|
|
1437
1441
|
SMTP/SMS/push/callbacks → Notifications; Redis/cache → Cache; Neo4j/Neptune/Arango/Memgraph → Graph;
|
|
1438
1442
|
Pinecone/Qdrant/Weaviate/OpenSearch → Vector; JWT/session middleware → Sessions.
|
|
1439
|
-
|
|
1443
|
+
Named reusable product capabilities with a stable managed-execution boundary → code-first Features,
|
|
1444
|
+
including synchronous multi-step capabilities and durable/scheduled/signal-driven orchestration.
|
|
1440
1445
|
Retries, health checks, fallbacks, quotas, circuit breakers → Resilience.
|
|
1441
|
-
Keep deterministic
|
|
1446
|
+
Keep low-level deterministic rules as ordinary domain functions when they do not form a useful
|
|
1447
|
+
independent capability boundary. Wrap or compose them into Features when the combined operation
|
|
1448
|
+
represents a reusable product capability.
|
|
1442
1449
|
|
|
1443
1450
|
LANGUAGE RUNTIME SHAPES
|
|
1444
1451
|
TypeScript: @ductape/sdk; NestJS uses @ductape/nestjs, @Events.Consumer, and request-scoped context.
|
|
@@ -1474,7 +1481,8 @@ AI EDITING STANDARD
|
|
|
1474
1481
|
Compilation and happy-path tests alone do not demonstrate parity. Use existing tests, characterization
|
|
1475
1482
|
tests, contract tests, integration tests, failure injection, and snd smoke tests appropriate to the slice.
|
|
1476
1483
|
If parity cannot be demonstrated, stop short of cutover and report the exact unverified behavior.
|
|
1477
|
-
Use Events for internal async boundaries and Apps/Actions for external APIs. Keep deterministic
|
|
1484
|
+
Use Events for internal async boundaries and Apps/Actions for external APIs. Keep low-level deterministic
|
|
1485
|
+
rules in code, while allowing a coherent synchronous capability composed from those rules to be a Feature.
|
|
1478
1486
|
Immediate work propagates the full session; durable work uses approved actor metadata or system context.
|
|
1479
1487
|
Consumers are idempotent, retry ownership is singular and bounded, and external effects are not duplicated.
|
|
1480
1488
|
After each slice: format, build, test, rescan, reconcile assets through ductape_cli, smoke-test in snd,
|
|
@@ -1550,6 +1558,10 @@ AUDITABLE REVIEW LEDGER
|
|
|
1550
1558
|
ductape_cli("migration-review validate --ledger <path>/review-ledger.json --json")
|
|
1551
1559
|
Before proposing cutover, require strict validation:
|
|
1552
1560
|
ductape_cli("migration-review validate --ledger <path>/review-ledger.json --strict --json")
|
|
1561
|
+
|
|
1562
|
+
Before writing SDK integration code, query the exact supported language/version catalog:
|
|
1563
|
+
ductape_cli("migration-capabilities --language <typescript|go|java|dotnet> --version <exact-version> --json")
|
|
1564
|
+
The catalog is source-evidenced but does not replace inspection of the package actually installed in the target.
|
|
1553
1565
|
Strict readiness requires no pending or stale files, reasoned exclusions, complete follow-ups,
|
|
1554
1566
|
covered internal references, recorded file purpose, and verified or reasoned-not-applicable
|
|
1555
1567
|
interface/functional/operational parity.
|
|
@@ -1627,6 +1639,18 @@ DEPENDENCY-AWARE LARGE-REPOSITORY PROPOSAL
|
|
|
1627
1639
|
Verification-matrix records may declare details.depends_on using category.requirement identifiers. A stale
|
|
1628
1640
|
cited dependency transitively invalidates dependent service/package summaries and readiness.
|
|
1629
1641
|
|
|
1642
|
+
MIGRATION ARTIFACT SAFETY
|
|
1643
|
+
Migration JSON is size-limited, secret-material scanned, version checked, and written through exclusive
|
|
1644
|
+
locks plus atomic rename. Mutating manifests retain a recoverable .bak copy. Validate or recover locally:
|
|
1645
|
+
ductape_cli("migration-artifact validate --file <artifact.json> --json")
|
|
1646
|
+
ductape_cli("migration-artifact recover --file <artifact.json> --json")
|
|
1647
|
+
Controlled legacy upgrades never rewrite the source artifact:
|
|
1648
|
+
ductape_cli("migration-artifact migrate --file <legacy.json> --output <v1.json> --json")
|
|
1649
|
+
Inspect the machine-readable schema catalog:
|
|
1650
|
+
ductape_cli("migration-artifact schemas --json")
|
|
1651
|
+
Errors include stable codes such as ARTIFACT_TOO_LARGE, ARTIFACT_SECRET_MATERIAL, ARTIFACT_LOCKED,
|
|
1652
|
+
ARTIFACT_VERSION_UNSUPPORTED, and ARTIFACT_RECOVERY_FAILED. Never bypass these checks with direct JSON edits.
|
|
1653
|
+
|
|
1630
1654
|
PARITY-GATED MIGRATION SLICES
|
|
1631
1655
|
Create a JSON array containing the reviewed repository-relative files for one vertical slice, then:
|
|
1632
1656
|
ductape_cli("migration-slice init --ledger <ledger> --tag <tag> --name <name> --files <files.json> --json")
|
|
@@ -2277,6 +2301,18 @@ An App must be fully set up in Ductape before any code can use it:
|
|
|
2277
2301
|
4. Action endpoints must be defined (each action = one HTTP endpoint spec: method, path, body/query/header shape, response shape)
|
|
2278
2302
|
5. The App must be connected to the product (product.apps.add) and its envs mapped
|
|
2279
2303
|
|
|
2304
|
+
DISCOVER BEFORE CREATING:
|
|
2305
|
+
ductape_cli("marketplace search payments --json")
|
|
2306
|
+
ductape_cli("marketplace search paystack --json")
|
|
2307
|
+
ductape_cli("marketplace categories --json")
|
|
2308
|
+
ductape_cli("marketplace get <app_tag> --json")
|
|
2309
|
+
|
|
2310
|
+
marketplace search matches capability terms against public app names, tags, descriptions,
|
|
2311
|
+
categories, actions, and webhooks. marketplace get returns the complete public app definition,
|
|
2312
|
+
including the exact current-version action tags and body/query/header/param schemas. Never infer
|
|
2313
|
+
Paystack action names such as "initialize" or "verify": inspect the marketplace record first.
|
|
2314
|
+
If no suitable app exists, create one or import Paystack's OpenAPI/Postman definition.
|
|
2315
|
+
|
|
2280
2316
|
ONLY after all five steps can any code call:
|
|
2281
2317
|
ctx.api.run({ app: '<app_tag>', event: '<action_tag>', input: { ... } }) ← in a feature handler
|
|
2282
2318
|
actions.run([{ product, env, app: '<app_tag>', action: '<action_tag>', input }]) ← at runtime
|
|
@@ -2339,6 +2375,22 @@ Run an action at runtime:
|
|
|
2339
2375
|
ductape_execute("actions.run", [{ product, env, app, action, input: { "body:field": value } }])
|
|
2340
2376
|
ductape_execute("actions.dispatch", [{ product, env, app, action, input, schedule? }])
|
|
2341
2377
|
|
|
2378
|
+
In a Ductape feature handler, call the registered action through:
|
|
2379
|
+
await ctx.api.run({ app: "<app_tag>", event: "<action_tag>", input: { ... } })
|
|
2380
|
+
ctx.api is the supported feature-context surface (also described as ctx.action in older code).
|
|
2381
|
+
There is no ctx.apps, ctx.integrations, or generic external-HTTP feature surface.
|
|
2382
|
+
|
|
2383
|
+
PAYSTACK CONFIGURATION:
|
|
2384
|
+
- Store the secret key as a workspace secret such as PAYSTACK_SECRET_KEY.
|
|
2385
|
+
- Reference it from app auth as: Authorization = "Bearer $Secret{PAYSTACK_SECRET_KEY}".
|
|
2386
|
+
- Never place the key in feature input, source code, logs, or marketplace app metadata.
|
|
2387
|
+
- Initialization and verification are raw app actions unless the inspected app explicitly
|
|
2388
|
+
publishes a higher-level contract. Ductape has no universal application payment abstraction.
|
|
2389
|
+
- Model inbound events as app webhook events. Verify x-paystack-signature against the raw
|
|
2390
|
+
request body using HMAC-SHA512 and PAYSTACK_SECRET_KEY before processing.
|
|
2391
|
+
- Acknowledge quickly, process asynchronously, deduplicate by event/reference, and verify the
|
|
2392
|
+
transaction through the inspected verification action before granting value.
|
|
2393
|
+
|
|
2342
2394
|
Auth schemes (how the app authenticates outbound requests):
|
|
2343
2395
|
Setup types: header | bearer | basic | oauth2 | apikey
|
|
2344
2396
|
Configure auth in Workbench (administrative).
|
|
@@ -2995,9 +3047,90 @@ PAYLOAD RECIPES
|
|
|
2995
3047
|
features: `
|
|
2996
3048
|
DUCTAPE FEATURES
|
|
2997
3049
|
|
|
2998
|
-
A
|
|
2999
|
-
|
|
3000
|
-
|
|
3050
|
+
A Feature is a named, reusable product capability with a stable input/output contract that
|
|
3051
|
+
benefits from managed execution, composition, observability, retries, versioning, policy
|
|
3052
|
+
enforcement, or explicit execution steps.
|
|
3053
|
+
|
|
3054
|
+
A Feature may be synchronous or asynchronous and may be entirely local. Signals, Events, waits,
|
|
3055
|
+
schedules, checkpoints, retries, compensation, and rollback are optional capabilities—not
|
|
3056
|
+
prerequisites. Asynchronous behavior is not the primary definition of a Feature.
|
|
3057
|
+
|
|
3058
|
+
Common Feature patterns:
|
|
3059
|
+
- synchronous capability
|
|
3060
|
+
- multi-step computation
|
|
3061
|
+
- event-driven orchestration
|
|
3062
|
+
- signal-driven human workflow
|
|
3063
|
+
- scheduled capability
|
|
3064
|
+
- parent/child Feature composition
|
|
3065
|
+
|
|
3066
|
+
━━━ CAPABILITY CLASSIFICATION — explain the evidence for every classification ━━━
|
|
3067
|
+
|
|
3068
|
+
Use exactly these categories while reviewing application code:
|
|
3069
|
+
FEATURE
|
|
3070
|
+
An independently meaningful product/domain capability with a useful managed-execution boundary.
|
|
3071
|
+
Recommendation: "Make this a standalone Ductape Feature."
|
|
3072
|
+
FEATURE_STEP
|
|
3073
|
+
A meaningful stage inside a larger capability, but not a useful independent execution boundary.
|
|
3074
|
+
Recommendation: "Expose this as a named ctx.step(...) inside another Feature."
|
|
3075
|
+
DOMAIN_SERVICE
|
|
3076
|
+
Reusable domain logic without a useful independent managed-execution boundary.
|
|
3077
|
+
Recommendation: "Keep this as ordinary domain logic called by a Feature."
|
|
3078
|
+
UTILITY
|
|
3079
|
+
A low-level helper such as hashing, formatting, redaction, normalization, conversion, or a type guard.
|
|
3080
|
+
Recommendation: "Keep this as a utility."
|
|
3081
|
+
INFRASTRUCTURE_ADAPTER
|
|
3082
|
+
Database, Event, HTTP, cache, storage, provider, transport, or framework integration code.
|
|
3083
|
+
Recommendation: "Keep this as an infrastructure adapter."
|
|
3084
|
+
|
|
3085
|
+
TypeScript export is only evidence of reuse. It is neither sufficient nor necessary for Feature
|
|
3086
|
+
classification. Never classify every exported function as a Feature.
|
|
3087
|
+
|
|
3088
|
+
Evaluate a candidate by asking:
|
|
3089
|
+
- Does it represent a recognizable product or domain capability?
|
|
3090
|
+
- Does it have a coherent responsibility?
|
|
3091
|
+
- Can it have a stable, typed input/output contract?
|
|
3092
|
+
- Is it reused across entry points, services, or other Features?
|
|
3093
|
+
- Would independent execution or composition be useful?
|
|
3094
|
+
- Would execution history or step-level observability be valuable?
|
|
3095
|
+
- Does it need explicit versioning, authorization, quotas, retries, or policy?
|
|
3096
|
+
- Does it contain several meaningful stages?
|
|
3097
|
+
- Would users or developers naturally name it as a product feature?
|
|
3098
|
+
A positive answer to several questions makes it a Feature candidate even when it is synchronous
|
|
3099
|
+
and local. No single answer is sufficient, and signals, Events, or long runtime are never required.
|
|
3100
|
+
|
|
3101
|
+
Keep low-level deterministic rules as ordinary domain functions when they do not form a useful
|
|
3102
|
+
independent capability boundary. Wrap or compose them into Features when the combined operation
|
|
3103
|
+
represents a reusable product capability.
|
|
3104
|
+
|
|
3105
|
+
When inspecting a TypeScript repository, examine:
|
|
3106
|
+
exported functions; public service methods; controller entry points; Event consumers; scheduled
|
|
3107
|
+
jobs; repeated orchestration sequences; domain operations reused in several locations; functions
|
|
3108
|
+
with substantial typed inputs/outputs; functions composing several stages; and product terminology
|
|
3109
|
+
in documentation and API routes. Do not restrict discovery to *.feature.ts or features.define calls.
|
|
3110
|
+
|
|
3111
|
+
Group related low-level operations into one coherent capability candidate. For example,
|
|
3112
|
+
resolveNationOrders, applyProvinceStockpileProduction, applyProvinceStockpileTransfers, and
|
|
3113
|
+
resolveFormationCommands may collectively suggest resolve-match-boundary or resolve-nation-turn.
|
|
3114
|
+
They must not automatically become four separate Features.
|
|
3115
|
+
|
|
3116
|
+
For repository analysis, return a structured inventory for every recommendation:
|
|
3117
|
+
{
|
|
3118
|
+
"candidate": "resolve-nation-turn",
|
|
3119
|
+
"classification": "FEATURE",
|
|
3120
|
+
"executionStyle": "synchronous-multistep",
|
|
3121
|
+
"evidence": [
|
|
3122
|
+
"Represents a recognizable game capability",
|
|
3123
|
+
"Has a stable input/output boundary",
|
|
3124
|
+
"Composes validation, production, resolution, and reporting",
|
|
3125
|
+
"Useful as an independently observable execution"
|
|
3126
|
+
],
|
|
3127
|
+
"suggestedSteps": ["validate-orders", "apply-production", "resolve-orders", "build-reports"],
|
|
3128
|
+
"signalsRequired": false,
|
|
3129
|
+
"eventsRequired": false,
|
|
3130
|
+
"recommendation": "Make this a standalone Ductape Feature."
|
|
3131
|
+
}
|
|
3132
|
+
Every classification needs concrete code, caller, contract, or product-language evidence. If the
|
|
3133
|
+
boundary remains ambiguous, report both plausible categories and the missing evidence; do not guess.
|
|
3001
3134
|
|
|
3002
3135
|
━━━ AI DESIGN WORKFLOW — follow this process every time a user asks you to build or plan a feature ━━━
|
|
3003
3136
|
|
|
@@ -3033,12 +3166,14 @@ STEP 2 — INVENTORY existing Ductape components
|
|
|
3033
3166
|
|
|
3034
3167
|
STEP 3 — PLAN each step
|
|
3035
3168
|
For every logical step:
|
|
3036
|
-
a. Identify
|
|
3169
|
+
a. Identify whether it is local domain logic, a child Feature, or an existing Ductape component.
|
|
3170
|
+
Local typed domain logic may run inside ctx.step; it does not require an Event or App.
|
|
3037
3171
|
If a step calls an external service, it MUST go through a registered Ductape App.
|
|
3038
3172
|
If no App for that service exists in the product → mark it "App to create: <service name>".
|
|
3039
3173
|
DO NOT plan a raw HTTP call, a direct dispatch to a URL, or any workaround in place of a missing App.
|
|
3040
3174
|
b. Note how inputs flow: ctx.input fields, or return values from earlier steps (plain JS variables — no special notation needed)
|
|
3041
|
-
c. Decide if a rollback handler is needed (e.g. charge → refund on later failure)
|
|
3175
|
+
c. Decide if a rollback handler is needed (e.g. charge → refund on later failure).
|
|
3176
|
+
Rollback is optional and is not a Feature qualification requirement.
|
|
3042
3177
|
d. Decide allow_fail: true for non-critical steps (email, analytics, audit logs)
|
|
3043
3178
|
|
|
3044
3179
|
STEP 4 — PRESENT the plan and get approval BEFORE writing any code or creating anything
|
|
@@ -3092,8 +3227,40 @@ STEP 8 — SET rollbacks for reversible steps
|
|
|
3092
3227
|
async (result) => ctx.api.run({ app: 'stripe', event: 'refund', input: { chargeId: result.id } })
|
|
3093
3228
|
);
|
|
3094
3229
|
|
|
3095
|
-
Step types: action | database | graph | notification | storage | produce | quota |
|
|
3096
|
-
vector | child_feature | sleep | wait_for_signal | checkpoint
|
|
3230
|
+
Step types: local_domain | action | database | graph | notification | storage | produce | quota |
|
|
3231
|
+
fallback | vector | child_feature | sleep | wait_for_signal | checkpoint
|
|
3232
|
+
|
|
3233
|
+
Valid synchronous Feature candidates include generate-world, resolve-nation-turn,
|
|
3234
|
+
calculate-route-capacity, price-subscription, evaluate-entitlement, and build-replay.
|
|
3235
|
+
|
|
3236
|
+
Synchronous multi-step Feature (no Event, schedule, sleep, signal, or external system):
|
|
3237
|
+
await ductape.features.define({
|
|
3238
|
+
product: 'example-product',
|
|
3239
|
+
tag: 'resolve-nation-turn',
|
|
3240
|
+
name: 'Resolve Nation Turn',
|
|
3241
|
+
input: {
|
|
3242
|
+
nationId: { type: 'string', required: true },
|
|
3243
|
+
tick: { type: 'number', required: true },
|
|
3244
|
+
},
|
|
3245
|
+
output: {
|
|
3246
|
+
acceptedOrders: { type: 'number' },
|
|
3247
|
+
rejectedOrders: { type: 'number' },
|
|
3248
|
+
},
|
|
3249
|
+
handler: async (ctx) => {
|
|
3250
|
+
const validated = await ctx.step('validate-orders', async () => {
|
|
3251
|
+
return validateOrders(ctx.input);
|
|
3252
|
+
});
|
|
3253
|
+
const resolved = await ctx.step('resolve-orders', async () => {
|
|
3254
|
+
return resolveOrders(validated);
|
|
3255
|
+
});
|
|
3256
|
+
return ctx.step('build-result', async () => {
|
|
3257
|
+
return buildResult(resolved);
|
|
3258
|
+
});
|
|
3259
|
+
},
|
|
3260
|
+
});
|
|
3261
|
+
This is a valid Feature despite requiring no signal and producing no Event. Its qualification comes
|
|
3262
|
+
from the named capability, stable contract, meaningful stages, reuse/composition value, and useful
|
|
3263
|
+
step-level execution history.
|
|
3097
3264
|
|
|
3098
3265
|
Define a feature (write this into the project's source files — do NOT use features.create):
|
|
3099
3266
|
// src/features/onboard-user.ts (or the equivalent path/language for the project)
|
|
@@ -3166,12 +3333,16 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
3166
3333
|
outer handler body. Code in the outer body runs during recording with proxy values and
|
|
3167
3334
|
may behave unexpectedly (e.g. typeof proxy === 'object' is true but .someField is a proxy).
|
|
3168
3335
|
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3336
|
+
A ctx.step callback may call ordinary local domain functions and injected/application services
|
|
3337
|
+
available to the registration scope. This is the normal shape for a synchronous capability such
|
|
3338
|
+
as pricing, entitlement evaluation, route-capacity calculation, or turn resolution. Keep the
|
|
3339
|
+
meaningful work inside ctx.step callbacks so recording does not execute it.
|
|
3340
|
+
|
|
3341
|
+
Use an Event when the operation genuinely crosses an asynchronous process/service boundary,
|
|
3342
|
+
needs broker delivery semantics, or must be consumed independently. Do not produce an Event merely
|
|
3343
|
+
to reach local domain logic. When an Event is appropriate, use ctx.events.produce in the currently
|
|
3344
|
+
published SDK and consume it in the NestJS service. ctx.publish is deprecated; do not use it.
|
|
3345
|
+
Do not assume a ctx.messaging alias exists unless installed SDK types explicitly expose it.
|
|
3175
3346
|
|
|
3176
3347
|
━━━ ORCHESTRATION DECISION RULE ━━━
|
|
3177
3348
|
|
|
@@ -3181,7 +3352,10 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
3181
3352
|
e.g. ductape.api.dispatch({ ..., schedule: { start_at: ... } })
|
|
3182
3353
|
e.g. ductape.database.dispatch({ ..., schedule: { start_at: ... } })
|
|
3183
3354
|
|
|
3184
|
-
|
|
3355
|
+
A named synchronous or asynchronous product capability with meaningful managed steps:
|
|
3356
|
+
→ define a Feature; execute it directly when immediate, or dispatch it when scheduled/background
|
|
3357
|
+
|
|
3358
|
+
Several durable Ductape component operations in sequence (with optional rollback / retry / state):
|
|
3185
3359
|
→ define a Feature, then features.dispatch to schedule it
|
|
3186
3360
|
|
|
3187
3361
|
Invoke internal application business logic (your own NestJS/backend service code):
|
|
@@ -4204,13 +4378,7 @@ async function main() {
|
|
|
4204
4378
|
const firstWord = args.command.trim().split(/\s+/)[0];
|
|
4205
4379
|
const isAuthCommand = firstWord === 'login' || firstWord === 'logout';
|
|
4206
4380
|
const isLocalMigrationGuidance = (firstWord === 'migrate-codebase' && !args.command.includes('--ensure-product')) ||
|
|
4207
|
-
firstWord
|
|
4208
|
-
firstWord === 'migration-slice' ||
|
|
4209
|
-
firstWord === 'migration-portfolio' ||
|
|
4210
|
-
firstWord === 'migration-database' ||
|
|
4211
|
-
firstWord === 'migration-environments' ||
|
|
4212
|
-
firstWord === 'migration-products' ||
|
|
4213
|
-
firstWord === 'migration-secrets';
|
|
4381
|
+
firstWord.startsWith('migration-');
|
|
4214
4382
|
if (!isAuthCommand && !isLocalMigrationGuidance) {
|
|
4215
4383
|
// Cache successful authentication, but re-check a missing/expired session on every call.
|
|
4216
4384
|
// The user may complete `ductape login` in another terminal while this MCP process remains
|
|
@@ -4268,6 +4436,7 @@ async function main() {
|
|
|
4268
4436
|
isError: true,
|
|
4269
4437
|
};
|
|
4270
4438
|
}
|
|
4439
|
+
const client = server.server?.getClientVersion?.();
|
|
4271
4440
|
const command = [
|
|
4272
4441
|
'migrate-codebase',
|
|
4273
4442
|
'--source', shellArgument(args.source),
|
|
@@ -4282,6 +4451,9 @@ async function main() {
|
|
|
4282
4451
|
...(args.exclude.length ? ['--exclude', shellArgument(args.exclude.join(','))] : []),
|
|
4283
4452
|
...(args.ensure_product ? ['--ensure-product'] : []),
|
|
4284
4453
|
...(args.write ? ['--write'] : []),
|
|
4454
|
+
...(client?.name && client?.version
|
|
4455
|
+
? ['--mcp-client-name', shellArgument(client.name), '--mcp-client-version', shellArgument(client.version)]
|
|
4456
|
+
: []),
|
|
4285
4457
|
'--json',
|
|
4286
4458
|
].join(' ');
|
|
4287
4459
|
return cliHandler({ command });
|
|
@@ -4480,6 +4652,10 @@ async function main() {
|
|
|
4480
4652
|
title: 'Ductape AI Migration Guidance',
|
|
4481
4653
|
description: 'Inspect a TypeScript, Go, Java, or .NET repository without exposing secret values. ' +
|
|
4482
4654
|
'Builds a relevant-file review queue, secret-name inventory, checksummed migration evidence, and low-confidence navigation hints. ' +
|
|
4655
|
+
'The review standards classify capability candidates as FEATURE, FEATURE_STEP, DOMAIN_SERVICE, UTILITY, or INFRASTRUCTURE_ADAPTER; ' +
|
|
4656
|
+
'they inspect exports, public methods, entry points, consumers, jobs, repeated orchestration, typed operations, routes, and product terminology. ' +
|
|
4657
|
+
'Synchronous local multi-step capabilities may be Features, while related low-level functions must be grouped rather than promoted one-by-one. ' +
|
|
4658
|
+
'Every recommendation must return classification, execution style, evidence, suggested steps, and whether signals or Events are actually required. ' +
|
|
4483
4659
|
'The AI must review files contextually and maintain an evidence ledger before proposing components or schemas. ' +
|
|
4484
4660
|
'It never generates or rewrites application code or executable assets. ' +
|
|
4485
4661
|
'Supports in-place and new-codebase guidance destinations. Read-only unless write or ensure_product is explicitly enabled.',
|
package/docs/TOOLS.md
CHANGED
|
@@ -4,6 +4,20 @@ The Ductape MCP server exposes **one tool**. All operations go through the backe
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## Marketplace discovery
|
|
8
|
+
|
|
9
|
+
Use the `ductape_cli` tool before creating an integration or guessing action names:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
ductape_cli("marketplace search payments --json")
|
|
13
|
+
ductape_cli("marketplace search paystack --json")
|
|
14
|
+
ductape_cli("marketplace get <app_tag> --json")
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The detail response is the authority for action tags and their body, query, header, and path
|
|
18
|
+
inputs. After an app is connected to a product, call `ductape_generate_payload` for the selected
|
|
19
|
+
action and then execute it through `actions.run`.
|
|
20
|
+
|
|
7
21
|
## Tool: `ductape_execute`
|
|
8
22
|
|
|
9
23
|
Executes a Ductape SDK operation via the backend proxy. Use this for databases, graph, storage, vector, caches, webhooks, jobs, and all other supported modules.
|