@ductape/mcp 0.2.3 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -981,7 +981,8 @@ const snippetGenerateInputSchema = payloadGenerateInputSchema.extend({
981
981
  language: z.enum(['typescript', 'python']).default('typescript'),
982
982
  });
983
983
  const schemaInputSchema = z.object({
984
- module: z.enum(['app', 'product']).optional().describe('Optional. Scope the result to a single module ("app" or "product"). Omit to get the full manifest including enums.'),
984
+ module: z.enum(['app', 'product']).optional().describe('Optional. Scope the result to one module. With no method, returns only the compact list of available methods.'),
985
+ method: z.string().optional().describe('Optional method key such as "databases.create" or "notifications.update". Use with module to return only that method schema.'),
985
986
  });
986
987
  function toPrettyJson(value) {
987
988
  return JSON.stringify(value ?? {}, null, 2);
@@ -2844,6 +2845,13 @@ FALLBACKS — automatic provider switching on failure:
2844
2845
  fallback.dispatch [{ product, env, tag, input, schedule? }]
2845
2846
 
2846
2847
  HEALTHCHECKS — continuous probe with failure notifications:
2848
+ Scheduled probes have a platform-owned fallback runner in the Ductape proxy. A local SDK monitor
2849
+ may also run them: while it consistently persists a fresh lastChecked record, the proxy defers
2850
+ that product/env/check. The proxy freshness window accounts for the SDK's batched backend status
2851
+ flush (currently five minutes), not only the shorter probe interval. If records stop arriving and
2852
+ the freshness window expires, the proxy automatically takes over. Do not instruct users to
2853
+ disable the proxy fallback when using a local monitor.
2854
+
2847
2855
  Workbench definition shape:
2848
2856
  {
2849
2857
  tag: "payment-health",
@@ -2851,7 +2859,7 @@ HEALTHCHECKS — continuous probe with failure notifications:
2851
2859
  probe: { type: "app", app: "stripe-app", event: "ping" },
2852
2860
  interval: 30000, // ms between checks
2853
2861
  retries: 3,
2854
- envs: [{ slug: "prd", input: {} }],
2862
+ envs: [{ slug: "prd", input: { path: "/health" } }],
2855
2863
  onFailure: {
2856
2864
  notifications: [{ notification: "ops-alerts", message: "payment-down",
2857
2865
  channels: { email: { recipients: ["ops@example.com"] } } }],
@@ -2862,8 +2870,37 @@ HEALTHCHECKS — continuous probe with failure notifications:
2862
2870
  health.check [{ product, env, tag }] → same as run
2863
2871
  health.status [{ product, env, tag }] → current health status
2864
2872
 
2865
- Probe types: app | database | feature | graph | message_broker | storage
2866
- Failure actions: notification channels, HTTP webhooks, and/or message broker emit — all can
2873
+ Probe types: app | database | feature | graph | events | storage
2874
+ Canonical Events probe:
2875
+ { type: "events", events: "statecraft-events", event: "health" }
2876
+ Do not create new probes with type/field message_broker or messageBroker; those names are deprecated
2877
+ compatibility aliases.
2878
+
2879
+ APP HEALTHCHECK SETUP — REQUIRED DISCOVERY AND VALIDATION
2880
+ An app healthcheck is not a generic URL ping. It invokes one action belonging to an app already
2881
+ connected to the product. Before creating it:
2882
+ 1. Read the product's connected apps with:
2883
+ ductape_cli("products components get --product-tag <product> --type apps --json")
2884
+ 2. Select a connected app by its product access tag. Never invent or use an unconnected app tag.
2885
+ 3. Inspect that connected app's available actions/schema using the app/schema tools. Select an
2886
+ existing action intended to be safe for repeated health probes.
2887
+ 4. Build a payload matching that action's required input schema for every selected product
2888
+ environment. Payloads belong in envs[].input and may differ by environment.
2889
+ 5. Create the resource with:
2890
+ ductape_cli("resources health create --tag <product> -f <healthcheck.json> --json")
2891
+ 6. Fetch the created healthcheck and verify probe.app, probe.event, and every env payload target;
2892
+ then run one immediate check and inspect status before relying on the schedule.
2893
+
2894
+ Required app probe shape:
2895
+ {
2896
+ probe: { type: "app", app: "<connected-app-access-tag>", event: "<existing-action-tag>" },
2897
+ envs: [{ slug: "<product-env>", input: { ...actionPayload } }]
2898
+ }
2899
+ Do not create an app healthcheck when the app, action, or required payload cannot be verified.
2900
+ The platform must reject missing/unconnected apps, unknown actions, and invalid action payloads;
2901
+ never interpret a successful create response alone as proof that the probe is runnable.
2902
+
2903
+ Failure actions: notification channels, HTTP webhooks, and/or Events emit — all can
2867
2904
  be configured simultaneously on the same healthcheck.
2868
2905
  Input template references: $Input{field} → maps declared input to the probe's action input.
2869
2906
  Provider status: available | unavailable
@@ -4647,8 +4684,23 @@ async function main() {
4647
4684
  };
4648
4685
  const schemaHandler = async (args) => {
4649
4686
  try {
4650
- const data = await getAssetSchemas(args.module);
4651
- return { content: [{ type: 'text', text: JSON.stringify(data ?? null, null, 2) }] };
4687
+ if (args.method && !args.module) {
4688
+ throw new Error('module is required when method is provided');
4689
+ }
4690
+ const data = await getAssetSchemas(args.module, args.method);
4691
+ const compactData = args.module &&
4692
+ !args.method &&
4693
+ data &&
4694
+ typeof data === 'object' &&
4695
+ !Array.isArray(data.methods) &&
4696
+ data.methods
4697
+ ? {
4698
+ module: args.module,
4699
+ methods: Object.keys(data.methods),
4700
+ hint: `Call ductape_schema with module="${args.module}" and one method for its complete field schema`,
4701
+ }
4702
+ : data;
4703
+ return { content: [{ type: 'text', text: JSON.stringify(compactData ?? null, null, 2) }] };
4652
4704
  }
4653
4705
  catch (err) {
4654
4706
  const message = err instanceof Error ? err.message : String(err);
@@ -4686,10 +4738,10 @@ async function main() {
4686
4738
  }, snippetGenerateHandler);
4687
4739
  server.registerTool('ductape_schema', {
4688
4740
  title: 'Ductape Asset Schema',
4689
- description: 'Returns the full field manifest for Ductape asset creation/update methods, ' +
4690
- 'derived live from the SDK Joi validators. Includes field types, required flags, ' +
4691
- 'enum values, nested structures, and all enum constants. ' +
4692
- 'Pass module="app" or module="product" to scope the result.\n\n' +
4741
+ description: 'Returns a compact method index or one targeted asset schema derived from the SDK Joi validators. ' +
4742
+ 'Call with module="app" or module="product" first to list method keys, then call again with ' +
4743
+ 'module and method (for example method="databases.create") for the complete field schema. ' +
4744
+ 'Avoid calling without module unless you explicitly need the entire manifest.\n\n' +
4693
4745
  'ALWAYS call this before constructing a file for "resources <type> create" or any cloud ' +
4694
4746
  'import/provision operation — field shapes are not guessable from context.\n\n' +
4695
4747
  'Conditional fields: some fields are returned as oneOf (an array of variant shapes). ' +
@@ -24,6 +24,6 @@ export interface IGenerateExecutablePayloadResponse {
24
24
  payload: Record<string, unknown>;
25
25
  meta: Record<string, unknown>;
26
26
  }
27
- export declare function getAssetSchemas(module?: string): Promise<unknown>;
27
+ export declare function getAssetSchemas(module?: string, method?: string): Promise<unknown>;
28
28
  export declare function generateExecutablePayload<T = IGenerateExecutablePayloadResponse>(request: IGenerateExecutablePayloadRequest): Promise<T>;
29
29
  //# sourceMappingURL=proxy-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-client.d.ts","sourceRoot":"","sources":["../src/proxy-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAEtD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,KAAK,GACL,WAAW,GACX,OAAO,GACP,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,GACN,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAUd;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,MAAM,WAAW,iCAAiC;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AASD,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AA4BD,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,kCAAkC,EACpF,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,CAAC,CAAC,CAiCZ"}
1
+ {"version":3,"file":"proxy-client.d.ts","sourceRoot":"","sources":["../src/proxy-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAEtD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,KAAK,GACL,WAAW,GACX,OAAO,GACP,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,GACN,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAUd;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,MAAM,WAAW,iCAAiC;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AASD,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBxF;AA4BD,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,kCAAkC,EACpF,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,CAAC,CAAC,CAiCZ"}
@@ -28,11 +28,22 @@ export async function executeViaProxy(publishable_key, module, method, params =
28
28
  }
29
29
  return body.data?.data;
30
30
  }
31
- export async function getAssetSchemas(module) {
32
- const path = module ? `/proxy/v1/schema/${encodeURIComponent(module)}` : '/proxy/v1/schema';
31
+ export async function getAssetSchemas(module, method) {
32
+ const path = module
33
+ ? `/proxy/v1/schema/${encodeURIComponent(module)}${method ? `/${encodeURIComponent(method)}` : ''}`
34
+ : '/proxy/v1/schema';
33
35
  const url = `${API_BASE_URL.replace(/\/$/, '')}${path}`;
34
36
  const res = await fetch(url);
35
37
  const body = (await res.json());
38
+ if (res.status === 404 && module && method) {
39
+ const fallbackUrl = `${API_BASE_URL.replace(/\/$/, '')}/proxy/v1/schema/${encodeURIComponent(module)}`;
40
+ const fallbackRes = await fetch(fallbackUrl);
41
+ const fallbackBody = (await fallbackRes.json());
42
+ const methodSchema = fallbackBody.data?.methods?.[method];
43
+ if (fallbackRes.ok && methodSchema) {
44
+ return { module, method, schema: methodSchema };
45
+ }
46
+ }
36
47
  if (!res.ok) {
37
48
  throw new Error(body.message ?? `Schema request failed: ${res.status}`);
38
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.2.3",
3
+ "version": "0.2.6",
4
4
  "description": "MCP server that exposes Ductape SDK operations via the backend proxy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",