@ductape/mcp 0.2.1 → 0.2.2

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.
Files changed (2) hide show
  1. package/dist/index.js +58 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35,7 +35,24 @@ There are THREE categories of operations. Use the right tool for each:
35
35
  ductape_cli("cloud connections list")
36
36
  ductape_cli("link --product my-product --env dev")
37
37
  If the CLI is not installed, ductape_cli will return install instructions automatically.
38
- NOTE: Environments and app actions are configured in the Workbench UI — there are no CLI commands for them.
38
+ NOTE: App actions are configured in the Workbench UI — there is no CLI command for them.
39
+ Environments DO have CLI commands: ductape_cli("products environments list/get/create/update ...").
40
+
41
+ RESOLVING "No linked project" ERRORS:
42
+ Some commands (declarative sync below, db migrate/schema, products environments *) need a
43
+ linked project — a local .ductape/config.json with a product tag and env slug. The "link"
44
+ command does NOT validate against the server: it just writes that local file. This means you
45
+ can run ductape_cli("link --product <tag> --env <slug>") even before that environment exists on
46
+ the product yet — do not treat "no linked environment exists server-side" as a reason to avoid
47
+ linking first. If the failing command already takes the product tag as an explicit argument
48
+ (e.g. products environments create/update/list/get), linking is not even required for it —
49
+ only commands that need to *infer* the product/env from local project state require a link.
50
+ Also: this MCP server runs the CLI subprocess in the directory named by the DUCTAPE_PROJECT_DIR
51
+ env var (falls back to this server process's own cwd if unset). If a command inexplicably
52
+ reports "no linked project" right after a successful "link" call, the project directory the
53
+ link was written to and the directory this server is running the CLI from may not match — set
54
+ DUCTAPE_PROJECT_DIR explicitly in this server's env (e.g. in the consuming project's .mcp.json)
55
+ to the target project's absolute path.
39
56
 
40
57
  DECLARATIVE SYNC (apply sessions, notifications, events from code; run DB migrations)
41
58
  → Also use ductape_cli. The project must be linked first (ductape init --link).
@@ -123,9 +140,10 @@ There are THREE categories of operations. Use the right tool for each:
123
140
  ductape_cli("resources storage list")
124
141
  ductape_cli("resources database create -f db-config.json")
125
142
  This applies to: products, apps, and resources (databases, storage, caches, etc.),
126
- cloud connections, and secrets. Environments, app actions, auths, quotas, fallbacks,
127
- jobs, and healthchecks are configured in the Workbench UI. Features have no CLI create
128
- command because their definitions are code-first through features.define.
143
+ cloud connections, and secrets. Environments have their own CLI commands (see below);
144
+ app actions, auths, quotas, fallbacks, jobs, and healthchecks are configured in the
145
+ Workbench UI. Features have no CLI create command because their definitions are code-first
146
+ through features.define.
129
147
 
130
148
  ⚠ MULTI-ENV REQUIREMENT — applies to ALL product assets (storage, database, cache,
131
149
  messageBroker, graph, vector, and any other resource with an envs array):
@@ -324,9 +342,9 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
324
342
  IMPORTANT: ALL product.* methods require the access key and will return 403 with a publishable key.
325
343
  Use ductape_cli for ALL product operations — never ductape_execute:
326
344
  ductape_cli("products get --tag <tag> --json") ← fetch product + full inventory
327
- ductape_cli("products components list --tag <tag> --json") ← compact non-secret inventory
328
- ductape_cli("products components get --tag <tag> --type notifications --json")
329
- ductape_cli("products components get --tag <tag> --type events --json")
345
+ ductape_cli("products components list --product-tag <tag> --json") ← compact non-secret inventory
346
+ ductape_cli("products components get --product-tag <tag> --type notifications --json")
347
+ ductape_cli("products components get --product-tag <tag> --type events --json")
330
348
  ductape_cli("products create --name <name> --tag <tag>")
331
349
  ductape_cli("products environments list <tag> --json")
332
350
  ductape_cli("products environments get <tag> <slug> --json")
@@ -1160,6 +1178,7 @@ function checkCli() {
1160
1178
  timeout: 5000,
1161
1179
  stdio: ['pipe', 'pipe', 'pipe'],
1162
1180
  env: cliEnvironment(),
1181
+ cwd: cliCwd(),
1163
1182
  }).trim();
1164
1183
  return { available: true, version: out || 'unknown' };
1165
1184
  }
@@ -1177,6 +1196,7 @@ function checkLoginState() {
1177
1196
  timeout: 10000,
1178
1197
  stdio: ['pipe', 'pipe', 'pipe'],
1179
1198
  env: cliEnvironment(),
1199
+ cwd: cliCwd(),
1180
1200
  });
1181
1201
  authState = 'ok';
1182
1202
  return 'ok';
@@ -1197,6 +1217,7 @@ function syncWorkspace() {
1197
1217
  timeout: 10000,
1198
1218
  stdio: ['pipe', 'pipe', 'pipe'],
1199
1219
  env: cliEnvironment(),
1220
+ cwd: cliCwd(),
1200
1221
  });
1201
1222
  }
1202
1223
  catch {
@@ -1225,6 +1246,7 @@ function runCli(command) {
1225
1246
  timeout: 90000,
1226
1247
  stdio: ['pipe', 'pipe', 'pipe'],
1227
1248
  env: cliEnvironment(),
1249
+ cwd: cliCwd(),
1228
1250
  });
1229
1251
  return { success: true, output: output.trim() };
1230
1252
  }
@@ -1278,6 +1300,19 @@ function cliEnvironment() {
1278
1300
  delete environment.DUCTAPE_ACCESS_KEY;
1279
1301
  return environment;
1280
1302
  }
1303
+ /**
1304
+ * Directory the `ductape` CLI subprocess runs in. Commands that resolve a linked project
1305
+ * (findProjectConfig walking up from cwd — e.g. `products environments *`, `apply`, `db migrate`)
1306
+ * depend on this being the user's actual project directory, not wherever this MCP server process
1307
+ * itself happened to be spawned from. execSync inherits process.cwd() when no cwd is given, which
1308
+ * is only correct if this server was started from inside the target project — that doesn't hold
1309
+ * for every launch path (e.g. a host attaching this server to an already-running session whose
1310
+ * cwd is unrelated to the project). Set DUCTAPE_PROJECT_DIR explicitly in the server's env
1311
+ * (e.g. in .mcp.json) to pin it; falls back to this process's own cwd otherwise.
1312
+ */
1313
+ function cliCwd() {
1314
+ return process.env.DUCTAPE_PROJECT_DIR || process.cwd();
1315
+ }
1281
1316
  function shellArgument(value) {
1282
1317
  return `'${value.replace(/'/g, `'\\''`)}'`;
1283
1318
  }
@@ -1376,10 +1411,12 @@ ENVIRONMENTS
1376
1411
  (production→prd, sandbox→snd, staging→stg) but present uncertain mappings for confirmation.
1377
1412
  Before creating any asset, list product environments and require complete per-environment coverage.
1378
1413
  Missing environments can be created idempotently through the authenticated standalone CLI:
1379
- ductape_cli("products environments create <product-tag> -f <environment.json> --json")
1414
+ ductape_cli("products environments create <product-tag> --env-file <environment.json> --json")
1380
1415
  The JSON requires env_name, description, and a three-character slug. The CLI fetches first, creates only
1381
- when absent, then fetches again to verify persistence. Update and verify with:
1382
- ductape_cli("products environments update <product-tag> <slug> -f <patch.json> --json")
1416
+ when absent, then fetches again to verify persistence (with a short retry on the verification read to
1417
+ absorb replication lag). No linked project is required — the product tag is always the explicit argument.
1418
+ Update and verify with:
1419
+ ductape_cli("products environments update <product-tag> <slug> --env-file <patch.json> --json")
1383
1420
  Export authenticated inventory with ductape_cli("products environments list <product-tag> --json"),
1384
1421
  save it as evidence, then reconcile locally:
1385
1422
  ductape_cli("migration-environments --analysis <analysis.json> --inventory <inventory.json> --strict --json")
@@ -4294,9 +4331,11 @@ const cliInputSchema = z.object({
4294
4331
  'Use this tool for administrative operations: creating or updating products, apps, ' +
4295
4332
  'resources (databases, storage, caches…), event broker topics, cloud connections, secrets, ' +
4296
4333
  'and for apply/migrate workflows.\n\n' +
4297
- 'Note: environments, app actions, quotas, fallbacks, and jobs are configured in the ' +
4298
- 'Workbench UI. Features also have no CLI creation command: define them in application code ' +
4299
- 'with features.define so application boot/runtime registration makes them available.\n\n' +
4334
+ 'Note: environments have their own CLI commands (products environments list/get/create/update, ' +
4335
+ 'no linked project required the product tag is always an explicit argument). App actions, ' +
4336
+ 'quotas, fallbacks, and jobs are configured in the Workbench UI. Features also have no CLI ' +
4337
+ 'creation command: define them in application code with features.define so application ' +
4338
+ 'boot/runtime registration makes them available.\n\n' +
4300
4339
  'The CLI uses the user\'s local logged-in session (ductape login) — no key is required.'),
4301
4340
  });
4302
4341
  async function loadMcpSdk() {
@@ -4748,15 +4787,16 @@ async function main() {
4748
4787
  ' type field = "messageBrokers" (not "messagebrokers" or "events").\n' +
4749
4788
  ' After importing, create topics first with ductape_cli("events topics create -f topic.json") — SQS requires explicit topic creation with queueUrls. For other providers, topics auto-register on first produce but should still be created explicitly before any consumer subscribes.\n' +
4750
4789
  ' - Listing workspaces, products, focused product components, secrets\n' +
4751
- ' Prefer "products components list --tag <tag> --json" for compact inventory; use\n' +
4752
- ' "products components get --tag <tag> --type notifications|events --json" for focused detail.\n' +
4790
+ ' Prefer "products components list --product-tag <tag> --json" for compact inventory; use\n' +
4791
+ ' "products components get --product-tag <tag> --type notifications|events --json" for focused detail.\n' +
4753
4792
  ' - Managing notification components and message templates through "resources notifications" and "notifications messages"\n' +
4754
4793
  ' - Linking a project folder: "link --product <tag> --env <slug>"\n' +
4755
4794
  ' - Syncing sessions/notifications/events: "apply" or "apply sessions" etc.\n' +
4756
4795
  ' - Running database migrations: "db migrate", "db schema generate"\n\n' +
4757
- 'NOTE: Environments, app actions, auths, quotas, fallbacks, and jobs are configured ' +
4758
- 'in the Workbench UI. Features have no CLI creation command because definitions are ' +
4759
- 'code-first through features.define and registered by the application runtime.\n\n' +
4796
+ 'NOTE: Environments have their own CLI commands (products environments *). App actions, ' +
4797
+ 'auths, quotas, fallbacks, and jobs are configured in the Workbench UI. Features have no ' +
4798
+ 'CLI creation command because definitions are code-first through features.define and ' +
4799
+ 'registered by the application runtime.\n\n' +
4760
4800
  'DO NOT use ductape_execute for admin operations — it uses a publishable key which only ' +
4761
4801
  'covers runtime operations. Administrative operations will fail with "Authentication failed".\n\n' +
4762
4802
  'The CLI uses the user\'s local logged-in session (ductape login). ' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "MCP server that exposes Ductape SDK operations via the backend proxy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",