@ductape/mcp 0.1.60 → 0.2.0
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 +8 -0
- package/README.md +5 -0
- package/dist/index.js +502 -8
- package/package.json +7 -1
- package/scripts/check-frontend-analytics-guidance.mjs +0 -88
- package/src/index.ts +0 -4280
- package/src/proxy-client.ts +0 -172
- package/tsconfig.json +0 -17
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 - 2026-07-26
|
|
4
|
+
|
|
5
|
+
- Added exhaustive AI-led migration guidance for TypeScript, Go, Java, and .NET.
|
|
6
|
+
- Added original E2E gates, contextual review, semantic database and frontend guidance, and strict verification matrices.
|
|
7
|
+
- Added dependency-aware large-repository guidance.
|
|
8
|
+
- Reinforced the administrative CLI/runtime execute boundary and access-key isolation.
|
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Ductape MCP Server
|
|
2
2
|
|
|
3
|
+
Migration guidance is available from `ductape_docs({ topic: "migration" })`. It starts with an original E2E
|
|
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 uses `ductape_cli`; `ductape_execute` remains
|
|
6
|
+
publishable-key runtime-only. MCP never accepts or forwards `DUCTAPE_ACCESS_KEY`.
|
|
7
|
+
|
|
3
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.
|
|
4
9
|
|
|
5
10
|
## Prerequisites
|
package/dist/index.js
CHANGED
|
@@ -946,7 +946,7 @@ const payloadGenerateInputSchema = z.object({
|
|
|
946
946
|
execution_context: z.enum(['user', 'delegated', 'system']).optional().default('user').describe('Actor intent for this runtime operation. "user" means an active request initiated by the authenticated user; ' +
|
|
947
947
|
'"delegated" means work acting on behalf of a user with a short-lived delegated identity or application-owned ' +
|
|
948
948
|
'immutable actor context; "system" means intentionally unattributed background work. This drives session warnings.'),
|
|
949
|
-
include_cache: z.boolean().optional().
|
|
949
|
+
include_cache: z.boolean().optional().describe('Include a cache tag inside the generated payload. Defaults to false; set true only when the runtime call should use cache explicitly.'),
|
|
950
950
|
schema_mode: z.enum(['strict', 'best_effort']).optional().default('best_effort').describe('"strict" — fail if any required field cannot be resolved. ' +
|
|
951
951
|
'"best_effort" — fill what is known, leave unknowns as null/placeholder. Use best_effort when exploring.'),
|
|
952
952
|
input_hint: z.record(z.any()).optional().describe('Optional. Partial input values you already know. These are merged into the generated payload template ' +
|
|
@@ -1135,14 +1135,28 @@ const ADMIN_SUBCOMMANDS = [
|
|
|
1135
1135
|
'events',
|
|
1136
1136
|
'cloud',
|
|
1137
1137
|
'secrets',
|
|
1138
|
+
'secrets-import-env',
|
|
1138
1139
|
'generate',
|
|
1139
1140
|
'apply',
|
|
1140
1141
|
'db',
|
|
1141
1142
|
'graph',
|
|
1143
|
+
'migrate-codebase',
|
|
1144
|
+
'migration-review',
|
|
1145
|
+
'migration-slice',
|
|
1146
|
+
'migration-portfolio',
|
|
1147
|
+
'migration-database',
|
|
1148
|
+
'migration-environments',
|
|
1149
|
+
'migration-products',
|
|
1150
|
+
'migration-secrets',
|
|
1142
1151
|
];
|
|
1143
1152
|
function checkCli() {
|
|
1144
1153
|
try {
|
|
1145
|
-
const out = execSync('ductape --version', {
|
|
1154
|
+
const out = execSync('ductape --version', {
|
|
1155
|
+
encoding: 'utf8',
|
|
1156
|
+
timeout: 5000,
|
|
1157
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1158
|
+
env: cliEnvironment(),
|
|
1159
|
+
}).trim();
|
|
1146
1160
|
return { available: true, version: out || 'unknown' };
|
|
1147
1161
|
}
|
|
1148
1162
|
catch {
|
|
@@ -1158,6 +1172,7 @@ function checkLoginState() {
|
|
|
1158
1172
|
encoding: 'utf8',
|
|
1159
1173
|
timeout: 10000,
|
|
1160
1174
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1175
|
+
env: cliEnvironment(),
|
|
1161
1176
|
});
|
|
1162
1177
|
authState = 'ok';
|
|
1163
1178
|
return 'ok';
|
|
@@ -1173,7 +1188,12 @@ function syncWorkspace() {
|
|
|
1173
1188
|
if (!target)
|
|
1174
1189
|
return;
|
|
1175
1190
|
try {
|
|
1176
|
-
execSync(`ductape workspaces use "${target}"`, {
|
|
1191
|
+
execSync(`ductape workspaces use "${target}"`, {
|
|
1192
|
+
encoding: 'utf8',
|
|
1193
|
+
timeout: 10000,
|
|
1194
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1195
|
+
env: cliEnvironment(),
|
|
1196
|
+
});
|
|
1177
1197
|
}
|
|
1178
1198
|
catch {
|
|
1179
1199
|
// best-effort; if it fails the user will see workspace-mismatch errors on subsequent commands
|
|
@@ -1200,6 +1220,7 @@ function runCli(command) {
|
|
|
1200
1220
|
// instead of this wrapper killing the CLI first and reducing it to "(no data)".
|
|
1201
1221
|
timeout: 90000,
|
|
1202
1222
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1223
|
+
env: cliEnvironment(),
|
|
1203
1224
|
});
|
|
1204
1225
|
return { success: true, output: output.trim() };
|
|
1205
1226
|
}
|
|
@@ -1243,13 +1264,431 @@ function runCli(command) {
|
|
|
1243
1264
|
return { success: false, output: msg };
|
|
1244
1265
|
}
|
|
1245
1266
|
}
|
|
1267
|
+
/**
|
|
1268
|
+
* MCP is publishable-key-only. The standalone CLI may manage its own access-key
|
|
1269
|
+
* credentials, but an access key present in the MCP host environment is never
|
|
1270
|
+
* forwarded into CLI subprocesses.
|
|
1271
|
+
*/
|
|
1272
|
+
function cliEnvironment() {
|
|
1273
|
+
const environment = { ...process.env };
|
|
1274
|
+
delete environment.DUCTAPE_ACCESS_KEY;
|
|
1275
|
+
return environment;
|
|
1276
|
+
}
|
|
1277
|
+
function shellArgument(value) {
|
|
1278
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1279
|
+
}
|
|
1246
1280
|
const docsInputSchema = z.object({
|
|
1247
1281
|
topic: z.string().describe('Feature topic to look up. Supported: ' +
|
|
1248
1282
|
'transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
1249
1283
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
1250
|
-
'notifications, resilience, features, events, logs, frontend, frontend-analytics, client, react, vue'),
|
|
1284
|
+
'notifications, resilience, features, events, logs, migration, frontend, frontend-analytics, client, react, vue'),
|
|
1285
|
+
});
|
|
1286
|
+
const migrationInputSchema = z.object({
|
|
1287
|
+
source: z.string().describe('Absolute path to the existing codebase.'),
|
|
1288
|
+
e2e_baseline: z.string().describe('Absolute path to a passing migration-e2e baseline manifest created before migration inspection.'),
|
|
1289
|
+
mode: z.enum(['in-place', 'new-codebase']).default('new-codebase').describe('Selects where advisory guidance is written. It never generates or rewrites application code.'),
|
|
1290
|
+
destination: z.string().optional().describe('Required destination path for new-codebase mode.'),
|
|
1291
|
+
product: z.string().optional().describe('Ductape product tag; defaults to a slug of the source directory name.'),
|
|
1292
|
+
name: z.string().optional().describe('Product display name.'),
|
|
1293
|
+
database: z.string().optional().describe('Target database tag recorded for the AI review; no schema is generated.'),
|
|
1294
|
+
max_file_bytes: z.number().int().positive().optional().default(2_000_000),
|
|
1295
|
+
include: z.array(z.string()).optional().default([]).describe('Repository-relative glob patterns to include.'),
|
|
1296
|
+
exclude: z.array(z.string()).optional().default([]).describe('Repository-relative glob patterns to exclude with audit evidence.'),
|
|
1297
|
+
ensure_product: z.boolean().optional().default(false).describe('Create the product through the standalone authenticated CLI when it does not exist.'),
|
|
1298
|
+
write: z.boolean().optional().default(false).describe('Write redacted advisory artifacts only. This never writes application code or executable Ductape assets.'),
|
|
1251
1299
|
});
|
|
1252
1300
|
const DOCS = {
|
|
1301
|
+
migration: `
|
|
1302
|
+
DUCTAPE CODEBASE MIGRATION GUIDE
|
|
1303
|
+
|
|
1304
|
+
NON-NEGOTIABLE AUTOMATION BOUNDARY
|
|
1305
|
+
The scanner is an evidence collector and standards engine, not a code generator or codemod.
|
|
1306
|
+
Scanner findings are evidence, not implementation instructions.
|
|
1307
|
+
It MUST NOT create, rewrite, patch, or mechanically replace application source.
|
|
1308
|
+
It MUST NOT emit executable migrations or authoritative Ductape assets.
|
|
1309
|
+
The scanner does not generate or propose a schema. Schema decisions belong to the contextual AI review.
|
|
1310
|
+
migration-evidence.json is checksummed source evidence, never an executable migration.
|
|
1311
|
+
The AI must inspect relevant source files and installed SDK APIs, explain its design, and then write
|
|
1312
|
+
code through normal editing tools. Builds, tests, rescans, inventory checks, and smoke tests verify it.
|
|
1313
|
+
|
|
1314
|
+
SUPPORTED SERVER LANGUAGES
|
|
1315
|
+
TypeScript/Node.js (including NestJS), Go, Java, and .NET.
|
|
1316
|
+
Inspect installed package exports before generating code; language APIs pursue parity but signatures differ.
|
|
1317
|
+
|
|
1318
|
+
START
|
|
1319
|
+
1. Inspect the original project and create or complete project-level E2E tests before changing application code.
|
|
1320
|
+
Run them against the original codebase. The AI executes the project test command with normal coding tools;
|
|
1321
|
+
Ductape CLI only records evidence and never executes an arbitrary command.
|
|
1322
|
+
Create a value-free definition containing command, suite_files, and passing baseline status/evidence/environment:
|
|
1323
|
+
ductape_cli("migration-e2e init --source <source> --definition <baseline-definition.json> --output <e2e-baseline.json> --json")
|
|
1324
|
+
The manifest SHA-256 binds every original test/fixture. Preserve it unchanged as the acceptance oracle.
|
|
1325
|
+
2. Call ductape_migration_plan in read-only mode with e2e_baseline set to that passing manifest.
|
|
1326
|
+
3. Present the review queue, inventory, secret NAMES, migration evidence, and low-confidence
|
|
1327
|
+
deterministic hints. Never present a hint as a component decision.
|
|
1328
|
+
4. Use the default new-codebase mode unless the user explicitly selects in-place:
|
|
1329
|
+
in-place — progressively migrate the existing repository.
|
|
1330
|
+
new-codebase — place guidance in a separate destination while preserving the source untouched.
|
|
1331
|
+
It does not generate a new application; the AI creates it deliberately.
|
|
1332
|
+
5. Call again with write=true only after confirming the destination. This writes guidance artifacts only.
|
|
1333
|
+
6. Call with ensure_product=true when product inventory confirms the product is absent.
|
|
1334
|
+
|
|
1335
|
+
FINAL E2E ACCEPTANCE GATE
|
|
1336
|
+
End the migration by running the exact original E2E command against the migrated codebase while retaining
|
|
1337
|
+
the original checksum-bound suite. Do not silently edit, delete, skip, quarantine, or weaken baseline tests.
|
|
1338
|
+
Record the passing result in a value-free evidence JSON containing the command, status, evidence,
|
|
1339
|
+
environment, and absolute suite_root of the migrated codebase, then:
|
|
1340
|
+
ductape_cli("migration-e2e final --manifest <e2e-baseline.json> --evidence <final-evidence.json> --json")
|
|
1341
|
+
ductape_cli("migration-e2e validate --manifest <e2e-baseline.json> --strict --json")
|
|
1342
|
+
The final command must exactly equal the baseline command. Every suite file under suite_root must match
|
|
1343
|
+
its original checksum, proving the migrated codebase is tested with the same original tests and fixtures.
|
|
1344
|
+
New migration-specific tests supplement the baseline; they never replace it. A failing original E2E case blocks
|
|
1345
|
+
readiness unless the user explicitly authorizes a product behavior change and the exception is separately audited.
|
|
1346
|
+
|
|
1347
|
+
SECURITY
|
|
1348
|
+
Never read secret values into MCP arguments or output. Discovery reports names and locations only.
|
|
1349
|
+
The MCP server accepts publishable keys only and never accepts an access key.
|
|
1350
|
+
Secret values must be imported by the standalone CLI reading local files directly. Assets reference
|
|
1351
|
+
$Secret{tag}; manifests never embed credentials. Keep snd/stg/prd values separate.
|
|
1352
|
+
Use ductape_cli("secrets-import-env --env-file <local-file> --source-key <ENV_KEY> --key <secret-tag> --env <slug> --json").
|
|
1353
|
+
The command reads the value locally and redacts it from output; never place the value in an MCP argument.
|
|
1354
|
+
secret_references are names-only navigation evidence from Docker Compose, Kubernetes secretKeyRef,
|
|
1355
|
+
GitHub/GitLab/Jenkins, Spring, .NET configuration, Terraform, and AWS/GCP/Azure secret managers.
|
|
1356
|
+
Their value is always [NOT_READ]. Inspect context before deciding whether a reference is sensitive,
|
|
1357
|
+
environment-specific, shared, or suitable for a Ductape secret; never resolve it through MCP.
|
|
1358
|
+
Classify and reconcile every discovered reference through a value-free artifact:
|
|
1359
|
+
ductape_cli("migration-secrets init --analysis <analysis.json> --definition <secret-map-definition.json> --output <secret-map.json> --json")
|
|
1360
|
+
ductape_cli("migration-secrets validate --file <secret-map.json> --strict --json")
|
|
1361
|
+
Each classification requires environment, service, provider, sensitivity, rotation owner,
|
|
1362
|
+
Ductape secret tag, authenticated inventory action/evidence, and rotation validation/rollback.
|
|
1363
|
+
The validator rejects value, password, credential, private-key, and access-token fields.
|
|
1364
|
+
potential_secret_exposures are low-confidence security-review findings only. They contain source,
|
|
1365
|
+
line, category, and a truncated SHA-256 fingerprint; matched material is always [NOT_RETURNED].
|
|
1366
|
+
Never ask the scanner, CLI, user, or MCP to reveal a finding. Ask the user/security owner to rotate
|
|
1367
|
+
and remediate confirmed exposure through trusted local processes.
|
|
1368
|
+
|
|
1369
|
+
ENVIRONMENTS
|
|
1370
|
+
Detect environments from .env variants, deployment files, CI, Docker, Kubernetes, Terraform,
|
|
1371
|
+
framework configuration, and existing database/provider configuration. Normalize common aliases
|
|
1372
|
+
(production→prd, sandbox→snd, staging→stg) but present uncertain mappings for confirmation.
|
|
1373
|
+
Before creating any asset, list product environments and require complete per-environment coverage.
|
|
1374
|
+
Missing environments can be created idempotently through the authenticated standalone CLI:
|
|
1375
|
+
ductape_cli("products environments create <product-tag> -f <environment.json> --json")
|
|
1376
|
+
The JSON requires env_name, description, and a three-character slug. The CLI fetches first, creates only
|
|
1377
|
+
when absent, then fetches again to verify persistence. Update and verify with:
|
|
1378
|
+
ductape_cli("products environments update <product-tag> <slug> -f <patch.json> --json")
|
|
1379
|
+
Export authenticated inventory with ductape_cli("products environments list <product-tag> --json"),
|
|
1380
|
+
save it as evidence, then reconcile locally:
|
|
1381
|
+
ductape_cli("migration-environments --analysis <analysis.json> --inventory <inventory.json> --strict --json")
|
|
1382
|
+
Report matched, missing, extra, and ambiguous normalized aliases. Never guess an ambiguous mapping.
|
|
1383
|
+
Environment mutation is administrative CLI work and must never be routed through ductape_execute.
|
|
1384
|
+
|
|
1385
|
+
PRODUCT AND ASSET BOOTSTRAP
|
|
1386
|
+
Product creation is idempotent: fetch by tag, create only when absent, then link the destination.
|
|
1387
|
+
Use ductape_cli for products, apps, resources, cloud connections, secrets, apply, and migrations.
|
|
1388
|
+
Use ductape_execute only for runtime calls with a publishable key.
|
|
1389
|
+
For monorepos, define explicit service ownership, product boundaries, asset environment coverage,
|
|
1390
|
+
and environment promotion evidence:
|
|
1391
|
+
ductape_cli("migration-products init --analysis <analysis.json> --definition <product-map-definition.json> --output <product-map.json> --json")
|
|
1392
|
+
ductape_cli("migration-products validate --file <product-map.json> --strict --json")
|
|
1393
|
+
Every discovered workspace-unit manifest must have exactly one service owner. Each service records
|
|
1394
|
+
its product and target environments. Every required asset records authenticated inventory evidence
|
|
1395
|
+
and configured environments. Every mapped product requires promotion entry conditions, validation,
|
|
1396
|
+
and rollback; never assume repository, service, and product boundaries are identical.
|
|
1397
|
+
|
|
1398
|
+
DATABASE SCHEMAS AND MIGRATIONS
|
|
1399
|
+
For every database migration, create a definition containing baseline, data, and cutover sections:
|
|
1400
|
+
ductape_cli("migration-database init --definition <database-definition.json> --output <guidance-dir> --json")
|
|
1401
|
+
ductape_cli("migration-database validate --directory <guidance-dir> --strict --json")
|
|
1402
|
+
Baseline evidence covers code/live/applied schemas, drift, views/triggers/procedures/indexes/constraints,
|
|
1403
|
+
permissions/RLS/encryption, tenancy/sharding/partitioning, provider compatibility, IDs/timezones/collation,
|
|
1404
|
+
and query-performance baselines. Data planning covers transformations, batching, checkpoints, resumability,
|
|
1405
|
+
idempotency, PII/retention, seed data, validation and reconciliation. Cutover uses expand/backfill/
|
|
1406
|
+
dual-compatibility/contract phases with deployment ordering, locks, backup, tested restore, rollback,
|
|
1407
|
+
irreversible-change disclosure, monitoring, reconciliation, and explicit approval.
|
|
1408
|
+
All three artifacts require the same migration_id and database_tag. Baseline schema_snapshots cover
|
|
1409
|
+
code, migration, applied, live, and proposed structures with source-file SHA-256, structure hash,
|
|
1410
|
+
timestamp, and evidence; stale source evidence blocks readiness. structural_comparison must be matched
|
|
1411
|
+
or contain explicit approved differences. Data transformations require versioned source/target field
|
|
1412
|
+
mappings, positive batch/concurrency/memory/timeout limits, and an atomic persistent checkpoint with
|
|
1413
|
+
replay-test evidence. Cutover phases require unique positive order and valid prerequisite IDs.
|
|
1414
|
+
Inventory Prisma, TypeORM, Sequelize, Mongoose, SQL, Flyway, Liquibase, Hibernate/JPA,
|
|
1415
|
+
Entity Framework, golang-migrate, Goose, and other migration/schema sources.
|
|
1416
|
+
The planner only identifies possible schema and migration source files. It does not parse them into
|
|
1417
|
+
a proposed Ductape schema. The AI must inspect models, relations, indexes, constraints, migrations,
|
|
1418
|
+
repository behavior, tests, live/provider semantics, and applied history before proposing or writing
|
|
1419
|
+
ductape/database/schema.json.
|
|
1420
|
+
Existing migrations are recorded in migration-imports.json with order and SHA-256 checksums. Review
|
|
1421
|
+
their intent, then generate portable reversible files under ductape/database/migrations/<db-tag>/.
|
|
1422
|
+
Raw source SQL is never silently executed or wrapped because Ductape migrations deliberately use
|
|
1423
|
+
provider-portable operations and require honest rollback behavior.
|
|
1424
|
+
Preserve applied order, identifiers, indexes, constraints, defaults, nullability, and rollback semantics.
|
|
1425
|
+
Never mark converted migrations applied merely because source files exist. Compare live schema in snd,
|
|
1426
|
+
run db schema generate, inspect the diff, then db migrate --dry-run before applying.
|
|
1427
|
+
Composite/partial/provider-specific indexes remain explicit Ductape migration operations.
|
|
1428
|
+
|
|
1429
|
+
THIRD-PARTY APIS
|
|
1430
|
+
Group repeated HTTP calls by stable base host into one reusable Ductape App. Model stable operations as
|
|
1431
|
+
Actions with auth, headers, input mapping, output mapping, retry/timeout policy, and environment-specific
|
|
1432
|
+
base URLs. Prefer OpenAPI/Postman import when available. Do not create one App per call site and do not
|
|
1433
|
+
route internal application services through fake HTTP Apps; use Events for internal boundaries.
|
|
1434
|
+
|
|
1435
|
+
COMPONENT DECISIONS
|
|
1436
|
+
Databases/transactions → Ductape Database; brokers/queues → Events; object stores → Storage;
|
|
1437
|
+
SMTP/SMS/push/callbacks → Notifications; Redis/cache → Cache; Neo4j/Neptune/Arango/Memgraph → Graph;
|
|
1438
|
+
Pinecone/Qdrant/Weaviate/OpenSearch → Vector; JWT/session middleware → Sessions.
|
|
1439
|
+
Multi-step durable/scheduled/signal-driven work → code-first Features.
|
|
1440
|
+
Retries, health checks, fallbacks, quotas, circuit breakers → Resilience.
|
|
1441
|
+
Keep deterministic calculations, validation, domain rules, and ordinary synchronous services as code.
|
|
1442
|
+
|
|
1443
|
+
LANGUAGE RUNTIME SHAPES
|
|
1444
|
+
TypeScript: @ductape/sdk; NestJS uses @ductape/nestjs, @Events.Consumer, and request-scoped context.
|
|
1445
|
+
Go: explicit services, context.Context, cancellation, typed errors, and owned worker shutdown.
|
|
1446
|
+
Java: DI/Spring integration where present, executor ownership, CompletableFuture boundaries.
|
|
1447
|
+
.NET: DI, hosted services, async/await, CancellationToken, configuration binding.
|
|
1448
|
+
|
|
1449
|
+
SESSIONS AND DURABLE ACTORS
|
|
1450
|
+
Immediate user work passes the original full session token. Delayed work must not persist raw JWTs
|
|
1451
|
+
indefinitely; use system context or an approved delegated actor plus immutable non-secret metadata.
|
|
1452
|
+
|
|
1453
|
+
ROLLOUT
|
|
1454
|
+
The AI migrates one vertical slice end-to-end, test snd, introduce a feature flag/dual path where safe,
|
|
1455
|
+
verify idempotency, concurrency, retries, duplicate delivery, logs, and rollback, then progressively cut over.
|
|
1456
|
+
|
|
1457
|
+
AI EDITING STANDARD
|
|
1458
|
+
Before every edit, inspect the relevant source, dependencies, installed SDK types, configuration, tests,
|
|
1459
|
+
and neighboring architecture. Preserve domain behavior and public contracts unless explicitly authorized.
|
|
1460
|
+
Do not change or invent public or internal interfaces, method signatures, types, DTOs, event schemas,
|
|
1461
|
+
serialized formats, error contracts, or lifecycle contracts unless the user explicitly authorizes that
|
|
1462
|
+
exact change. An SDK mismatch is a finding to report and resolve, not permission to reshape application code.
|
|
1463
|
+
Do not assume functionality from filenames, symbols, patterns, comments, documentation, or scanner hints.
|
|
1464
|
+
Trace the implementation, callers, callees, tests, configuration, persisted data, and runtime effects.
|
|
1465
|
+
If behavior remains unclear, run or add characterization tests and record the uncertainty. Never fabricate
|
|
1466
|
+
behavior, compatibility, defaults, rollback guarantees, idempotency, or provider support.
|
|
1467
|
+
Maintain full functional parity:
|
|
1468
|
+
- accepted inputs, returned outputs, validation, domain results, state changes, external side effects,
|
|
1469
|
+
serialized data, errors, events, and user-visible behavior.
|
|
1470
|
+
Maintain full operational parity:
|
|
1471
|
+
- ordering, timing-sensitive guarantees, concurrency, transactions, retries, duplicate delivery,
|
|
1472
|
+
idempotency, authorization, privacy, observability, performance-sensitive behavior, startup,
|
|
1473
|
+
shutdown, cancellation, recovery, and degraded/failure behavior.
|
|
1474
|
+
Compilation and happy-path tests alone do not demonstrate parity. Use existing tests, characterization
|
|
1475
|
+
tests, contract tests, integration tests, failure injection, and snd smoke tests appropriate to the slice.
|
|
1476
|
+
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 rules in code.
|
|
1478
|
+
Immediate work propagates the full session; durable work uses approved actor metadata or system context.
|
|
1479
|
+
Consumers are idempotent, retry ownership is singular and bounded, and external effects are not duplicated.
|
|
1480
|
+
After each slice: format, build, test, rescan, reconcile assets through ductape_cli, smoke-test in snd,
|
|
1481
|
+
and report unresolved findings. A clean scanner result alone never proves a correct migration.
|
|
1482
|
+
|
|
1483
|
+
CONTEXTUAL FILE REVIEW PROTOCOL
|
|
1484
|
+
Use review_queue as a coverage aid. Review relevant files individually, starting with repository
|
|
1485
|
+
instructions, manifests, entrypoints, configuration, dependency injection, tests, and deployment files.
|
|
1486
|
+
For each file record: purpose; imports/dependencies; callers/callees; configuration and secret-name
|
|
1487
|
+
references; interfaces/types/signatures/DTOs/event schemas/serialized contracts; database behavior;
|
|
1488
|
+
events/background work; external APIs; sessions/authorization;
|
|
1489
|
+
cache/storage/notifications/graph/vector use; failure policy; tests/invariants; and follow-up files.
|
|
1490
|
+
Follow wrappers and references until the actual external effect and domain intent are understood.
|
|
1491
|
+
Classify each ledger finding:
|
|
1492
|
+
observed — directly supported by source/configuration
|
|
1493
|
+
inferred — likely, but requires more context
|
|
1494
|
+
proposed — possible Ductape design, not yet approved
|
|
1495
|
+
confirmed — verified through source, installed SDK types, tests, inventory, or user confirmation
|
|
1496
|
+
Do not claim coverage until every relevant queue item is reviewed or excluded with a written reason.
|
|
1497
|
+
Do not read .env secret values into MCP context: record names only and use standalone CLI import.
|
|
1498
|
+
|
|
1499
|
+
AUDITABLE REVIEW LEDGER
|
|
1500
|
+
After write=true creates migration-guidance/analysis.json, initialize the ledger:
|
|
1501
|
+
ductape_cli("migration-review init --analysis <path>/analysis.json --json")
|
|
1502
|
+
Record contextual evidence through a validated JSON input file:
|
|
1503
|
+
ductape_cli("migration-review record --ledger <ledger> --file <relative-file> --data <evidence.json> --json")
|
|
1504
|
+
The evidence file may contain purpose, dependencies, follow_up_files, interfaces, findings, and
|
|
1505
|
+
references. Reference kinds are import | caller | callee | implements | event | test | config | schema.
|
|
1506
|
+
Every finding requires location: { start_line, end_line } with positive, ordered source lines.
|
|
1507
|
+
Every finding also requires symbol: { kind, name, qualified_name? } so evidence identifies the
|
|
1508
|
+
affected module/class/interface/function/method/field/route/event/schema rather than only a filename.
|
|
1509
|
+
Internal references must point to reviewed/excluded ledger files before readiness.
|
|
1510
|
+
Add a newly discovered repository file without dropping review coverage:
|
|
1511
|
+
ductape_cli("migration-review follow-up --ledger <ledger> --file <source> --follow-up <target> --json")
|
|
1512
|
+
Record parity with structured validation:
|
|
1513
|
+
ductape_cli("migration-review parity --ledger <ledger> --file <file> --concern interface --status verified --evidence <evidence> --json")
|
|
1514
|
+
ductape_cli("migration-review parity --ledger <ledger> --file <file> --concern functional --status verified --evidence <evidence> --json")
|
|
1515
|
+
ductape_cli("migration-review parity --ledger <ledger> --file <file> --concern operational --status verified --evidence <evidence> --json")
|
|
1516
|
+
For a genuine not-applicable concern, use --status not_applicable --reason <reason>.
|
|
1517
|
+
For each entry the ledger records purpose, dependencies, follow-up files, references, interfaces,
|
|
1518
|
+
findings, exclusion metadata where applicable, and:
|
|
1519
|
+
interface_parity, functional_parity, operational_parity
|
|
1520
|
+
Each parity status is pending | verified | not_applicable.
|
|
1521
|
+
verified requires concrete evidence. not_applicable requires a reason.
|
|
1522
|
+
After completing a file, snapshot the exact reviewed content:
|
|
1523
|
+
ductape_cli("migration-review snapshot --ledger <path>/review-ledger.json --file <relative-file> --json")
|
|
1524
|
+
A later checksum change makes that review stale. Follow-up files must also exist in the ledger;
|
|
1525
|
+
never silently omit a referenced file. Reopen a review explicitly when needed:
|
|
1526
|
+
ductape_cli("migration-review reopen --ledger <ledger> --file <relative-file> --json")
|
|
1527
|
+
Exclude only with a classification and reason:
|
|
1528
|
+
ductape_cli("migration-review exclude --ledger <ledger> --file <file> --classification <type> --reason <reason> --json")
|
|
1529
|
+
Types: generated | vendor | build | snapshot | other. Generated exclusions additionally require
|
|
1530
|
+
--generator and --regeneration-test so generated contracts are not silently ignored.
|
|
1531
|
+
If a reviewed file disappears, validation reports checksum-matched probable_moves without changing
|
|
1532
|
+
history. Accept a verified move only when content is identical:
|
|
1533
|
+
ductape_cli("migration-review move --ledger <ledger> --from <old-file> --to <new-file> --json")
|
|
1534
|
+
A stale file transitively invalidates reviewed entries that reference it through internal references,
|
|
1535
|
+
follow-up files, or finding follow-ups. Re-review the dependency chain before readiness.
|
|
1536
|
+
Every structured ledger mutation uses an exclusive lock, checks the expected revision, appends an
|
|
1537
|
+
actor/tool/version/timestamp operation event, chains it to the previous SHA-256 hash, and binds the
|
|
1538
|
+
newest event to the current ledger-entry state. Never edit review-ledger.json directly after audit
|
|
1539
|
+
events exist: validation treats that as tampering. A concurrent conflict must be retried after re-reading
|
|
1540
|
+
the latest ledger; never overwrite another reviewer.
|
|
1541
|
+
For parallel branches, merge only against an explicit common base:
|
|
1542
|
+
ductape_cli("migration-review merge --base <base.json> --current <current.json> --incoming <incoming.json> --output <merged.json> --json")
|
|
1543
|
+
Non-overlapping file reviews merge into a new ledger; divergent edits to the same file return conflicts
|
|
1544
|
+
and never overwrite either input. For trusted release attestation, sign outside MCP with a protected
|
|
1545
|
+
Ed25519 private-key file and verify using the independently distributed public key:
|
|
1546
|
+
ductape_cli("migration-review sign --ledger <ledger> --private-key <private.pem> --key-id <identity> --json")
|
|
1547
|
+
ductape_cli("migration-review verify-signature --ledger <ledger> --signature <ledger.sig.json> --public-key <public.pem> --json")
|
|
1548
|
+
Never pass private-key contents through MCP or prompts.
|
|
1549
|
+
Check progress without claiming readiness:
|
|
1550
|
+
ductape_cli("migration-review validate --ledger <path>/review-ledger.json --json")
|
|
1551
|
+
Before proposing cutover, require strict validation:
|
|
1552
|
+
ductape_cli("migration-review validate --ledger <path>/review-ledger.json --strict --json")
|
|
1553
|
+
Strict readiness requires no pending or stale files, reasoned exclusions, complete follow-ups,
|
|
1554
|
+
covered internal references, recorded file purpose, and verified or reasoned-not-applicable
|
|
1555
|
+
interface/functional/operational parity.
|
|
1556
|
+
|
|
1557
|
+
GENERATED, VENDORED, AND SNAPSHOT CONTRACTS
|
|
1558
|
+
Scanner generated_source_hints are navigation evidence, never permission to ignore a file. Contextually
|
|
1559
|
+
classify every hint and any discovered generated or vendored file in a definition, then:
|
|
1560
|
+
ductape_cli("migration-generated init --analysis <analysis.json> --definition <generated-vendor-definition.json> --json")
|
|
1561
|
+
ductape_cli("migration-generated validate --file <generated-vendor-evidence.json> --strict --json")
|
|
1562
|
+
For generated files record contract_kind (public_api | generated_client | schema | ui_snapshot | internal),
|
|
1563
|
+
owner, generator name/version/command, repository-relative generator inputs, passing clean-workspace
|
|
1564
|
+
regeneration evidence, the regenerated output file, and compatibility_tests. The CLI records SHA-256
|
|
1565
|
+
input/checked-in/regenerated checksums and compares output; it never executes an arbitrary generator command.
|
|
1566
|
+
public_api, generated_client, schema, and ui_snapshot are contracts and require compatibility tests.
|
|
1567
|
+
A clean-regenerated mismatch or changed generator input blocks readiness.
|
|
1568
|
+
For vendored source record upstream source/version/SHA-256 checksum, owner, locally_modified, diff_evidence,
|
|
1569
|
+
and compatibility tests. The validator derives modification from current versus upstream checksum; it rejects
|
|
1570
|
+
a false classification, and locally modified vendor source requires owned diff evidence.
|
|
1571
|
+
Never overwrite or normalize checked-in generated/vendor output to make validation pass. Re-run the real
|
|
1572
|
+
generator in an isolated clean workspace using normal development tools, inspect the diff, and record evidence.
|
|
1573
|
+
|
|
1574
|
+
REPOSITORY-WIDE ASSURANCE MATRIX
|
|
1575
|
+
Create a version:1, artifact_kind:"ductape_migration_assurance" JSON artifact and validate it with:
|
|
1576
|
+
ductape_cli("migration-assurance --file <assurance.json> --strict --json")
|
|
1577
|
+
This is an evidence gate, not a test runner. The AI runs the referenced tests with normal development tools.
|
|
1578
|
+
It requires tested session flows from frontend through backend, Events, Features, and scheduled work, including
|
|
1579
|
+
refresh, revocation, logout, account switching, expiry, and actor-audit evidence that is not authorization.
|
|
1580
|
+
It requires Feature duplicate-delivery, signal, compensation, restart, layered retry-budget, fallback, quota,
|
|
1581
|
+
and health-check evidence.
|
|
1582
|
+
Every third_party_calls entry records the inspected wrapper chain and client family (Axios, Fetch, Java, .NET,
|
|
1583
|
+
Go, GraphQL, gRPC, or generated), base URL, auth, headers, timeout, retries, pagination, rate limits, normalized
|
|
1584
|
+
errors, webhook/replay behavior, parity evidence, and tests.
|
|
1585
|
+
Component matrices require:
|
|
1586
|
+
graph — schema, edges, indexes, traversal, reconciliation
|
|
1587
|
+
vector — dimensions, metric, embedding version, metadata schema, batching, quality
|
|
1588
|
+
storage — object keys, metadata, ACL, encryption, retention, multipart, checksums
|
|
1589
|
+
cache — keys, TTL, invalidation, stampede, consistency, fallback
|
|
1590
|
+
notifications — templates, channels, providers, suppression, retry, delivery, privacy
|
|
1591
|
+
analytics — event schema, identity, consent, masking, delivery, dashboard parity
|
|
1592
|
+
Provider migrations require tested resumability evidence.
|
|
1593
|
+
Runtime evidence covers safe procedures for TypeScript, Go, Java, and .NET; request/query/Event/Feature/external
|
|
1594
|
+
effect correlation; trace/log compatibility; load/concurrency/retry/duplicate delivery; lifecycle/restart;
|
|
1595
|
+
redaction; dashboards and alert thresholds.
|
|
1596
|
+
The sdk_matrix requires each supported language's exact package/version, installed capability evidence,
|
|
1597
|
+
equivalent parity tests, lifecycle and error-mapping requirements, examples, anti-patterns, and an explicit
|
|
1598
|
+
block/escalate policy for unsupported capabilities. Never silently emulate a missing SDK capability.
|
|
1599
|
+
|
|
1600
|
+
COMPREHENSIVE VERIFICATION MATRIX
|
|
1601
|
+
Record automation that the AI actually ran with normal project tools in a version:1,
|
|
1602
|
+
artifact_kind:"ductape_migration_verification_matrix" file, then:
|
|
1603
|
+
ductape_cli("migration-verification --file <verification-matrix.json> --strict --json")
|
|
1604
|
+
This command validates evidence; it never executes the recorded commands. Every one of 63 requirements
|
|
1605
|
+
must be passed and include tests, structured details, automation tool/command/result/environment, and
|
|
1606
|
+
source citations containing absolute repository, relative file, exact line range, and current SHA-256.
|
|
1607
|
+
A changed or missing cited file invalidates readiness.
|
|
1608
|
+
Categories cover multi-repository summaries/checkpoints/contracts; normalized before/after parity,
|
|
1609
|
+
nondeterminism, test strength, mutation and safe shadow signals; frontend browser/accessibility/visual/
|
|
1610
|
+
performance/security/mobile evidence; complete database modeling, data movement and cutover drills;
|
|
1611
|
+
component asset design/inventory/environment/provider/payload/dependency evidence; and contextual
|
|
1612
|
+
third-party client and App/Action designs.
|
|
1613
|
+
Dependency records require nodes, edges, and an evidenced order. Before/after records require explicit
|
|
1614
|
+
normalization and comparison. Nondeterminism requires named fields and approved differences. Visual,
|
|
1615
|
+
irreversible, and residual-uncertainty decisions require actor, authority, and approval evidence.
|
|
1616
|
+
Never manufacture an automation result or approval to satisfy the matrix. A blocked or failed record
|
|
1617
|
+
remains a blocker and must be reported as residual risk.
|
|
1618
|
+
|
|
1619
|
+
DEPENDENCY-AWARE LARGE-REPOSITORY PROPOSAL
|
|
1620
|
+
After contextual references exist in the review ledger, generate a non-authoritative proposal:
|
|
1621
|
+
ductape_cli("migration-portfolio propose --ledger <ledger> --max-bytes <bytes> --max-tokens <tokens> --json")
|
|
1622
|
+
The proposer builds the internal reference graph, condenses strongly connected components so cyclic files
|
|
1623
|
+
stay together, topologically orders dependencies before consumers, and records byte plus ceil(bytes/4)
|
|
1624
|
+
token estimates. An indivisible SCC over either configured limit is marked oversized_scc for human/AI
|
|
1625
|
+
review; it is never split unsafely. The output authority is advisory_only and must be contextually reviewed
|
|
1626
|
+
before it becomes a portfolio definition.
|
|
1627
|
+
Verification-matrix records may declare details.depends_on using category.requirement identifiers. A stale
|
|
1628
|
+
cited dependency transitively invalidates dependent service/package summaries and readiness.
|
|
1629
|
+
|
|
1630
|
+
PARITY-GATED MIGRATION SLICES
|
|
1631
|
+
Create a JSON array containing the reviewed repository-relative files for one vertical slice, then:
|
|
1632
|
+
ductape_cli("migration-slice init --ledger <ledger> --tag <tag> --name <name> --files <files.json> --json")
|
|
1633
|
+
Complete the generated slice manifest with:
|
|
1634
|
+
product_boundary, sdk_capabilities,
|
|
1635
|
+
interface_contracts, functional_requirements, operational_requirements,
|
|
1636
|
+
required_assets, tests, failure_tests, runtime_evidence, smoke_checks,
|
|
1637
|
+
cutover_conditions, rollback_conditions, deployment_cutover.
|
|
1638
|
+
Apply those fields through a validated definition JSON file:
|
|
1639
|
+
ductape_cli("migration-slice define --slice <slice.json> --data <definition.json> --json")
|
|
1640
|
+
Each required asset records kind, tag, action (reuse | create | update | blocked), and inventory_evidence.
|
|
1641
|
+
Inventory evidence must come from ductape_cli administrative inventory, never an assumed asset.
|
|
1642
|
+
product_boundary records product_tag, included services, target environments, and repository/inventory
|
|
1643
|
+
evidence. Never assume one repository equals one service or one Ductape product.
|
|
1644
|
+
sdk_capabilities records language, installed package, exact version, capability, and evidence from
|
|
1645
|
+
installed exports/types or version-matched primary documentation. Never assume cross-language parity.
|
|
1646
|
+
runtime_evidence and failure_tests cover behavior static review cannot prove: external effects,
|
|
1647
|
+
transactions, ordering, concurrency, retry/duplicate delivery, startup/shutdown, and degraded behavior.
|
|
1648
|
+
deployment_cutover records the implementation commit, per-environment deployed versions, feature-flag/
|
|
1649
|
+
dual-run/traffic state, explicit no-return points and mitigations, a timed observation window with success
|
|
1650
|
+
thresholds, dashboard/alert evidence, and a passing executed rollback rehearsal. Unrecorded deployment
|
|
1651
|
+
state or an untested rollback blocks strict readiness.
|
|
1652
|
+
Validate during work:
|
|
1653
|
+
ductape_cli("migration-slice validate --slice <slice.json> --json")
|
|
1654
|
+
Gate cutover:
|
|
1655
|
+
ductape_cli("migration-slice validate --slice <slice.json> --strict --json")
|
|
1656
|
+
A slice cannot be ready with stale/unreviewed files, incomplete parity, missing tests/smoke checks,
|
|
1657
|
+
missing failure/runtime evidence, an unproven product boundary or SDK capability, missing cutover or
|
|
1658
|
+
rollback conditions, incomplete asset evidence, or blocked reconciliation.
|
|
1659
|
+
|
|
1660
|
+
LARGE CODEBASES AND CONTEXT BOUNDARIES
|
|
1661
|
+
Never load a huge repository into one model context or rely on conversational memory for coverage.
|
|
1662
|
+
Partition reviewed files into bounded, non-overlapping groups with an explicit context_budget,
|
|
1663
|
+
durable summary, and file-checksum provenance. Define partitions, slice paths, and cross-slice contracts:
|
|
1664
|
+
ductape_cli("migration-portfolio init --ledger <ledger> --definition <portfolio-definition.json> --json")
|
|
1665
|
+
The CLI computes provenance checksums; changed files stale the affected partition summary.
|
|
1666
|
+
Validate resumable repository-wide coverage:
|
|
1667
|
+
ductape_cli("migration-portfolio validate --portfolio <portfolio.json> --json")
|
|
1668
|
+
Gate repository cutover:
|
|
1669
|
+
ductape_cli("migration-portfolio validate --portfolio <portfolio.json> --strict --json")
|
|
1670
|
+
Strict portfolio validation requires every ledger file in exactly one partition, current provenance,
|
|
1671
|
+
every slice ready, and evidenced provider/consumer cross-slice contracts. Summaries are navigation
|
|
1672
|
+
aids only; reopen source review whenever provenance becomes stale.
|
|
1673
|
+
|
|
1674
|
+
FRONTEND MIGRATION PARITY
|
|
1675
|
+
Mark frontend slices with surfaces: ["frontend"] (or include backend/worker for a mixed slice).
|
|
1676
|
+
Frontend strict readiness requires evidence for routes/navigation, rendered loading/empty/error/success
|
|
1677
|
+
states, forms/validation, accessibility, responsive behavior, browser storage, authentication transitions,
|
|
1678
|
+
SSR/hydration, realtime reconnect/resubscription, analytics/privacy, performance budgets,
|
|
1679
|
+
visual regression, and cross-browser behavior.
|
|
1680
|
+
Inspect installed @ductape/client, @ductape/react, or @ductape/vue exports before editing. Preserve UI
|
|
1681
|
+
contracts and application state semantics; do not replace domain state with analytics. Verify full-session
|
|
1682
|
+
identify/clearSession lifecycle, route pageviews, privacy masking, hidden-state exclusion, trace correlation,
|
|
1683
|
+
unsubscribe/teardown, reconnect duplication, SSR browser boundaries, and accessibility behavior.
|
|
1684
|
+
|
|
1685
|
+
PARITY CLAIMS
|
|
1686
|
+
Never promise or report "100% parity" merely because gates pass. The gates require the strongest available
|
|
1687
|
+
evidence and make unverified behavior explicit; arbitrary software cannot receive a mathematical parity
|
|
1688
|
+
guarantee from static review and finite tests. Each slice records before/after evidence from appropriate
|
|
1689
|
+
characterization, contract, golden, side-effect, database-state, event-order, failure-injection,
|
|
1690
|
+
load/concurrency, or safe shadow-comparison checks. Report residual uncertainty honestly.
|
|
1691
|
+
`.trim(),
|
|
1253
1692
|
frontend: `
|
|
1254
1693
|
DUCTAPE FRONTEND SDK GUIDE
|
|
1255
1694
|
|
|
@@ -3764,7 +4203,15 @@ async function main() {
|
|
|
3764
4203
|
}
|
|
3765
4204
|
const firstWord = args.command.trim().split(/\s+/)[0];
|
|
3766
4205
|
const isAuthCommand = firstWord === 'login' || firstWord === 'logout';
|
|
3767
|
-
|
|
4206
|
+
const isLocalMigrationGuidance = (firstWord === 'migrate-codebase' && !args.command.includes('--ensure-product')) ||
|
|
4207
|
+
firstWord === 'migration-review' ||
|
|
4208
|
+
firstWord === 'migration-slice' ||
|
|
4209
|
+
firstWord === 'migration-portfolio' ||
|
|
4210
|
+
firstWord === 'migration-database' ||
|
|
4211
|
+
firstWord === 'migration-environments' ||
|
|
4212
|
+
firstWord === 'migration-products' ||
|
|
4213
|
+
firstWord === 'migration-secrets';
|
|
4214
|
+
if (!isAuthCommand && !isLocalMigrationGuidance) {
|
|
3768
4215
|
// Cache successful authentication, but re-check a missing/expired session on every call.
|
|
3769
4216
|
// The user may complete `ductape login` in another terminal while this MCP process remains
|
|
3770
4217
|
// alive; caching "none" would otherwise make the MCP blind to the newly written session.
|
|
@@ -3814,6 +4261,31 @@ async function main() {
|
|
|
3814
4261
|
...(result.success ? {} : { isError: true }),
|
|
3815
4262
|
};
|
|
3816
4263
|
};
|
|
4264
|
+
const migrationHandler = async (args) => {
|
|
4265
|
+
if (args.mode === 'new-codebase' && !args.destination) {
|
|
4266
|
+
return {
|
|
4267
|
+
content: [{ type: 'text', text: 'Error: destination is required for new-codebase mode.' }],
|
|
4268
|
+
isError: true,
|
|
4269
|
+
};
|
|
4270
|
+
}
|
|
4271
|
+
const command = [
|
|
4272
|
+
'migrate-codebase',
|
|
4273
|
+
'--source', shellArgument(args.source),
|
|
4274
|
+
'--e2e-baseline', shellArgument(args.e2e_baseline),
|
|
4275
|
+
'--mode', args.mode,
|
|
4276
|
+
...(args.destination ? ['--destination', shellArgument(args.destination)] : []),
|
|
4277
|
+
...(args.product ? ['--product', shellArgument(args.product)] : []),
|
|
4278
|
+
...(args.name ? ['--name', shellArgument(args.name)] : []),
|
|
4279
|
+
...(args.database ? ['--database', shellArgument(args.database)] : []),
|
|
4280
|
+
'--max-file-bytes', String(args.max_file_bytes),
|
|
4281
|
+
...(args.include.length ? ['--include', shellArgument(args.include.join(','))] : []),
|
|
4282
|
+
...(args.exclude.length ? ['--exclude', shellArgument(args.exclude.join(','))] : []),
|
|
4283
|
+
...(args.ensure_product ? ['--ensure-product'] : []),
|
|
4284
|
+
...(args.write ? ['--write'] : []),
|
|
4285
|
+
'--json',
|
|
4286
|
+
].join(' ');
|
|
4287
|
+
return cliHandler({ command });
|
|
4288
|
+
};
|
|
3817
4289
|
const executeHandler = async (args) => {
|
|
3818
4290
|
try {
|
|
3819
4291
|
const runtimeMutationMethods = {
|
|
@@ -3834,7 +4306,8 @@ async function main() {
|
|
|
3834
4306
|
}
|
|
3835
4307
|
const key = args.publishable_key || process.env.DUCTAPE_PUBLISHABLE_KEY;
|
|
3836
4308
|
if (!key) {
|
|
3837
|
-
throw new Error('
|
|
4309
|
+
throw new Error('Runtime authentication is missing. Set DUCTAPE_PUBLISHABLE_KEY in the MCP server environment ' +
|
|
4310
|
+
'or pass publishable_key to ductape_execute. The MCP server never accepts access keys.');
|
|
3838
4311
|
}
|
|
3839
4312
|
// The TS SDK uses ductape.events.* for broker operations; the backend proxy uses messageBrokers.
|
|
3840
4313
|
const proxyModule = args.module === 'events' ? 'messageBrokers' : args.module;
|
|
@@ -3857,7 +4330,18 @@ async function main() {
|
|
|
3857
4330
|
return p;
|
|
3858
4331
|
});
|
|
3859
4332
|
}
|
|
3860
|
-
|
|
4333
|
+
let result;
|
|
4334
|
+
try {
|
|
4335
|
+
result = await executeViaProxy(key, proxyModule, args.method, params);
|
|
4336
|
+
}
|
|
4337
|
+
catch (error) {
|
|
4338
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4339
|
+
if (/authentication failed|unauthorized|invalid.*key/i.test(message)) {
|
|
4340
|
+
throw new Error('The DUCTAPE_PUBLISHABLE_KEY was rejected by the runtime proxy. ' +
|
|
4341
|
+
'Use a publishable key for the same workspace/product. The MCP server never accepts or forwards access keys.');
|
|
4342
|
+
}
|
|
4343
|
+
throw error;
|
|
4344
|
+
}
|
|
3861
4345
|
return { content: [{ type: 'text', text: JSON.stringify(result ?? null, null, 2) }] };
|
|
3862
4346
|
}
|
|
3863
4347
|
catch (err) {
|
|
@@ -3989,9 +4473,18 @@ async function main() {
|
|
|
3989
4473
|
'index strategy, operation types) that should be confirmed with the user first.\n\n' +
|
|
3990
4474
|
'Available topics: transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
3991
4475
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
3992
|
-
'notifications, resilience, features, events, logs, frontend, frontend-analytics, client, react, vue',
|
|
4476
|
+
'notifications, resilience, features, events, logs, migration, frontend, frontend-analytics, client, react, vue',
|
|
3993
4477
|
inputSchema: docsInputSchema,
|
|
3994
4478
|
}, docsHandler);
|
|
4479
|
+
server.registerTool('ductape_migration_plan', {
|
|
4480
|
+
title: 'Ductape AI Migration Guidance',
|
|
4481
|
+
description: 'Inspect a TypeScript, Go, Java, or .NET repository without exposing secret values. ' +
|
|
4482
|
+
'Builds a relevant-file review queue, secret-name inventory, checksummed migration evidence, and low-confidence navigation hints. ' +
|
|
4483
|
+
'The AI must review files contextually and maintain an evidence ledger before proposing components or schemas. ' +
|
|
4484
|
+
'It never generates or rewrites application code or executable assets. ' +
|
|
4485
|
+
'Supports in-place and new-codebase guidance destinations. Read-only unless write or ensure_product is explicitly enabled.',
|
|
4486
|
+
inputSchema: migrationInputSchema,
|
|
4487
|
+
}, migrationHandler);
|
|
3995
4488
|
server.registerTool('ductape_cli', {
|
|
3996
4489
|
title: 'Ductape CLI',
|
|
3997
4490
|
description: 'Run a Ductape CLI command for administrative operations.\n\n' +
|
|
@@ -4101,6 +4594,7 @@ async function main() {
|
|
|
4101
4594
|
server.tool('ductape_generate_snippet', snippetGenerateInputSchema.shape, snippetGenerateHandler);
|
|
4102
4595
|
server.tool('ductape_schema', schemaInputSchema.shape, schemaHandler);
|
|
4103
4596
|
server.tool('ductape_docs', docsInputSchema.shape, docsHandler);
|
|
4597
|
+
server.tool('ductape_migration_plan', migrationInputSchema.shape, migrationHandler);
|
|
4104
4598
|
server.tool('ductape_cli', cliInputSchema.shape, cliHandler);
|
|
4105
4599
|
}
|
|
4106
4600
|
else {
|