@ductape/mcp 0.1.59 → 0.1.60

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
@@ -723,47 +723,10 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
723
723
  vector.count [{ product, env, vector, namespace? }]
724
724
 
725
725
  ━━━ MODULE: features ━━━
726
- features.create [product_tag, data: {
727
- tag: string,
728
- name: string,
729
- description?: string,
730
-
731
- // INPUT SCHEMA (top-level): declares what fields this feature accepts when executed at runtime.
732
- // These are the fields callers will pass to features.execute / features.dispatch.
733
- // Construct this yourself — it is a schema declaration, not a runtime value.
734
- input?: { fieldName: { type: string, required?: boolean } },
735
-
736
- output?: object,
737
- envs?: [{ slug: string, active?: boolean }],
738
- steps: [
739
- {
740
- tag: string, // unique step id
741
- name?: string,
742
- type: "action"|"database"|"graph"|"notification"|"storage"|"publish"|"feature"|"sleep"|"wait_signal",
743
- app?: string, // for type=action
744
- event?: string, // action/event tag
745
- database?: string, // for type=database
746
- graph?: string, // for type=graph
747
- notification?: string, // for type=notification
748
- storage?: string, // for type=storage
749
- broker?: string, // for type=publish
750
- feature?: string, // for type=feature (child feature)
751
-
752
- // STEP INPUT: maps this feature's declared input fields (or prior step outputs) → the step's underlying action/event fields.
753
- // ← CALL ductape_generate_payload (operation_family matching step type, method="run", targets={app/event/database/etc.})
754
- // to discover what fields the target accepts, then wire them with "$Input{fieldName}" or "$Step{stepTag}{field}" references.
755
- input?: { "body:field": "$Input{fieldName}" | "$Step{stepTag}{field}" | literal },
756
-
757
- condition?: string, // e.g. "$Step{validate}{valid} == true"
758
- dependsOn?: string[],
759
- options?: { retries?: number, timeout?: number, allow_fail?: boolean, critical?: boolean }
760
- }
761
- ]
762
- }]
763
- features.update [product_tag, feature_tag, data: { name?: string, description?: string, steps?: array, envs?: array }]
726
+ Feature definitions are code-first. Use features.define in application source; do not call
727
+ administrative create/update/delete methods through ductape_execute.
764
728
  features.fetch [product_tag, feature_tag]
765
729
  features.fetchAll [product_tag]
766
- features.delete [product_tag, feature_tag]
767
730
 
768
731
  features.define [{
769
732
  product?: string,
@@ -977,7 +940,8 @@ const payloadGenerateInputSchema = z.object({
977
940
  'For quotas/fallbacks: { tag: "resource_tag" }. ' +
978
941
  'For storage: { storage: "storage_tag" }. ' +
979
942
  'For messaging: { broker: "broker_tag", topic?: "topic_tag" }.'),
980
- include_session: z.boolean().optional().default(true).describe('Include a session placeholder inside the generated input object. ' +
943
+ include_session: z.boolean().optional().describe('Include a session placeholder inside the generated input object. ' +
944
+ 'Defaults to false for execution_context="system" and true otherwise. ' +
981
945
  'The placeholder is named "<session_tag_token>" to indicate it expects the runtime JWT, not the tag name.'),
982
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; ' +
983
947
  '"delegated" means work acting on behalf of a user with a short-lived delegated identity or application-owned ' +
@@ -1084,7 +1048,7 @@ function addSessionAwarenessMetadata(generated, args) {
1084
1048
  const acceptsSession = operationAcceptsSession(args.operation_family, args.method);
1085
1049
  const executionContext = args.execution_context ?? 'user';
1086
1050
  const payloadHasSession = Boolean(generated?.payload?.session || generated?.payload?.input?.session);
1087
- const sessionRequested = args.include_session !== false;
1051
+ const sessionRequested = args.include_session ?? executionContext !== 'system';
1088
1052
  const warnings = [];
1089
1053
  if (acceptsSession && executionContext !== 'system' && (!sessionRequested || !payloadHasSession)) {
1090
1054
  warnings.push(`Session attribution is missing for a ${executionContext}-context operation. ` +
@@ -3914,7 +3878,8 @@ async function main() {
3914
3878
  if (!key) {
3915
3879
  throw new Error('Not authenticated. Set DUCTAPE_PUBLISHABLE_KEY in your MCP server env config, or pass publishable_key on every tool call.');
3916
3880
  }
3917
- const result = addSessionAwarenessMetadata(await generateExecutablePayload({ ...args, publishable_key: key }), args);
3881
+ const includeSession = args.include_session ?? args.execution_context !== 'system';
3882
+ const result = addSessionAwarenessMetadata(await generateExecutablePayload({ ...args, include_session: includeSession, publishable_key: key }), args);
3918
3883
  let text = JSON.stringify(result ?? null, null, 2);
3919
3884
  if (args.operation_family === 'database') {
3920
3885
  const meta = result?.meta ?? {};
@@ -3941,7 +3906,8 @@ async function main() {
3941
3906
  throw new Error('Not authenticated. Set DUCTAPE_PUBLISHABLE_KEY in your MCP server env config, or pass publishable_key on every tool call.');
3942
3907
  }
3943
3908
  ensureSupportedSnippetOperation(args.operation_family, args.method);
3944
- const generated = addSessionAwarenessMetadata(await generateExecutablePayload({ ...args, publishable_key: key }), args);
3909
+ const includeSession = args.include_session ?? args.execution_context !== 'system';
3910
+ const generated = addSessionAwarenessMetadata(await generateExecutablePayload({ ...args, include_session: includeSession, publishable_key: key }), args);
3945
3911
  const payload = generated?.payload ?? {};
3946
3912
  const snippet = buildSnippet(args.language, payload, args.operation_family, args.method);
3947
3913
  return {
@@ -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,CA8BZ"}
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"}
@@ -14,7 +14,7 @@ export async function executeViaProxy(publishable_key, module, method, params =
14
14
  },
15
15
  body: JSON.stringify({
16
16
  publishable_key,
17
- module,
17
+ module: module === 'features' ? 'feature' : module,
18
18
  method,
19
19
  params,
20
20
  }),
@@ -73,6 +73,9 @@ export async function generateExecutablePayload(request) {
73
73
  const { execution_context: _executionContext, ...backendRequest } = request;
74
74
  const normalizedRequest = {
75
75
  ...backendRequest,
76
+ operation_family: backendRequest.operation_family.toLowerCase() === 'features'
77
+ ? 'feature'
78
+ : backendRequest.operation_family,
76
79
  targets: backendRequest.targets
77
80
  ? normalizeTargets(backendRequest.targets)
78
81
  : backendRequest.targets,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.1.59",
3
+ "version": "0.1.60",
4
4
  "description": "MCP server that exposes Ductape SDK operations via the backend proxy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -734,47 +734,10 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
734
734
  vector.count [{ product, env, vector, namespace? }]
735
735
 
736
736
  ━━━ MODULE: features ━━━
737
- features.create [product_tag, data: {
738
- tag: string,
739
- name: string,
740
- description?: string,
741
-
742
- // INPUT SCHEMA (top-level): declares what fields this feature accepts when executed at runtime.
743
- // These are the fields callers will pass to features.execute / features.dispatch.
744
- // Construct this yourself — it is a schema declaration, not a runtime value.
745
- input?: { fieldName: { type: string, required?: boolean } },
746
-
747
- output?: object,
748
- envs?: [{ slug: string, active?: boolean }],
749
- steps: [
750
- {
751
- tag: string, // unique step id
752
- name?: string,
753
- type: "action"|"database"|"graph"|"notification"|"storage"|"publish"|"feature"|"sleep"|"wait_signal",
754
- app?: string, // for type=action
755
- event?: string, // action/event tag
756
- database?: string, // for type=database
757
- graph?: string, // for type=graph
758
- notification?: string, // for type=notification
759
- storage?: string, // for type=storage
760
- broker?: string, // for type=publish
761
- feature?: string, // for type=feature (child feature)
762
-
763
- // STEP INPUT: maps this feature's declared input fields (or prior step outputs) → the step's underlying action/event fields.
764
- // ← CALL ductape_generate_payload (operation_family matching step type, method="run", targets={app/event/database/etc.})
765
- // to discover what fields the target accepts, then wire them with "$Input{fieldName}" or "$Step{stepTag}{field}" references.
766
- input?: { "body:field": "$Input{fieldName}" | "$Step{stepTag}{field}" | literal },
767
-
768
- condition?: string, // e.g. "$Step{validate}{valid} == true"
769
- dependsOn?: string[],
770
- options?: { retries?: number, timeout?: number, allow_fail?: boolean, critical?: boolean }
771
- }
772
- ]
773
- }]
774
- features.update [product_tag, feature_tag, data: { name?: string, description?: string, steps?: array, envs?: array }]
737
+ Feature definitions are code-first. Use features.define in application source; do not call
738
+ administrative create/update/delete methods through ductape_execute.
775
739
  features.fetch [product_tag, feature_tag]
776
740
  features.fetchAll [product_tag]
777
- features.delete [product_tag, feature_tag]
778
741
 
779
742
  features.define [{
780
743
  product?: string,
@@ -1000,8 +963,9 @@ const payloadGenerateInputSchema = z.object({
1000
963
  'For storage: { storage: "storage_tag" }. ' +
1001
964
  'For messaging: { broker: "broker_tag", topic?: "topic_tag" }.'
1002
965
  ),
1003
- include_session: z.boolean().optional().default(true).describe(
966
+ include_session: z.boolean().optional().describe(
1004
967
  'Include a session placeholder inside the generated input object. ' +
968
+ 'Defaults to false for execution_context="system" and true otherwise. ' +
1005
969
  'The placeholder is named "<session_tag_token>" to indicate it expects the runtime JWT, not the tag name.'
1006
970
  ),
1007
971
  execution_context: z.enum(['user', 'delegated', 'system']).optional().default('user').describe(
@@ -1119,7 +1083,7 @@ function addSessionAwarenessMetadata(
1119
1083
  const acceptsSession = operationAcceptsSession(args.operation_family, args.method);
1120
1084
  const executionContext = args.execution_context ?? 'user';
1121
1085
  const payloadHasSession = Boolean(generated?.payload?.session || generated?.payload?.input?.session);
1122
- const sessionRequested = args.include_session !== false;
1086
+ const sessionRequested = args.include_session ?? executionContext !== 'system';
1123
1087
  const warnings: string[] = [];
1124
1088
 
1125
1089
  if (acceptsSession && executionContext !== 'system' && (!sessionRequested || !payloadHasSession)) {
@@ -4033,8 +3997,9 @@ async function main() {
4033
3997
  if (!key) {
4034
3998
  throw new Error('Not authenticated. Set DUCTAPE_PUBLISHABLE_KEY in your MCP server env config, or pass publishable_key on every tool call.');
4035
3999
  }
4000
+ const includeSession = args.include_session ?? args.execution_context !== 'system';
4036
4001
  const result = addSessionAwarenessMetadata(
4037
- await generateExecutablePayload({ ...args, publishable_key: key }),
4002
+ await generateExecutablePayload({ ...args, include_session: includeSession, publishable_key: key }),
4038
4003
  args,
4039
4004
  );
4040
4005
 
@@ -4068,8 +4033,9 @@ async function main() {
4068
4033
  throw new Error('Not authenticated. Set DUCTAPE_PUBLISHABLE_KEY in your MCP server env config, or pass publishable_key on every tool call.');
4069
4034
  }
4070
4035
  ensureSupportedSnippetOperation(args.operation_family, args.method);
4036
+ const includeSession = args.include_session ?? args.execution_context !== 'system';
4071
4037
  const generated = addSessionAwarenessMetadata(
4072
- await generateExecutablePayload({ ...args, publishable_key: key }),
4038
+ await generateExecutablePayload({ ...args, include_session: includeSession, publishable_key: key }),
4073
4039
  args,
4074
4040
  );
4075
4041
  const payload = (generated as any)?.payload ?? {};
@@ -52,7 +52,7 @@ export async function executeViaProxy<T = unknown>(
52
52
  },
53
53
  body: JSON.stringify({
54
54
  publishable_key,
55
- module,
55
+ module: module === 'features' ? 'feature' : module,
56
56
  method,
57
57
  params,
58
58
  }),
@@ -143,6 +143,9 @@ export async function generateExecutablePayload<T = IGenerateExecutablePayloadRe
143
143
  const { execution_context: _executionContext, ...backendRequest } = request;
144
144
  const normalizedRequest = {
145
145
  ...backendRequest,
146
+ operation_family: backendRequest.operation_family.toLowerCase() === 'features'
147
+ ? 'feature'
148
+ : backendRequest.operation_family,
146
149
  targets: backendRequest.targets
147
150
  ? normalizeTargets(backendRequest.targets as Record<string, unknown>)
148
151
  : backendRequest.targets,