@ductape/mcp 0.1.30 → 0.1.32

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 (3) hide show
  1. package/dist/index.js +31 -10
  2. package/package.json +1 -1
  3. package/src/index.ts +35 -10
package/dist/index.js CHANGED
@@ -522,11 +522,20 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
522
522
  databases.connect [{ product, env, database }]
523
523
  databases.testConnection [{ product, env, database }]
524
524
  databases.disconnect []
525
- databases.query [{ product, env, database, entity, where?: {field: {$eq|$gt|$lt|$in: value}}, select?: string[], orderBy?: [{field, order:"ASC"|"DESC"}], limit?, offset? }]
526
- databases.insert [{ product, env, database, entity, data: {key: value}|{key:value}[], returning? }]
527
- databases.update [{ product, env, database, entity, data: {key:value}, where: {key: {$eq: value}}, returning? }]
528
- databases.delete [{ product, env, database, entity, where: {key: {$eq: value}}, returning? }]
529
- databases.upsert [{ product, env, database, entity, data: {key:value}, conflictKeys: string[], returning? }]
525
+ databases.query [{ product, env, database, table, where?: {field: value}, select?: string[], orderBy?: [{field, order:"ASC"|"DESC"}], limit?, offset?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="query", targets={database, table})
526
+ databases.insert [{ product, env, database, table, data: {key: value}|{key:value}[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="insert", targets={database, table})
527
+ databases.update [{ product, env, database, table, data: {key:value}, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="update", targets={database, table})
528
+ databases.delete [{ product, env, database, table, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="delete", targets={database, table})
529
+ databases.upsert [{ product, env, database, table, data: {key:value}, conflictKeys: string[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="upsert", targets={database, table})
530
+ NOTE: ductape_generate_payload for databases returns:
531
+ payload.input — ready-to-use input with real field names in where/data, plus session and cache inside input
532
+ meta.schema_context.database.fields — { fieldName: { type, required, description?, sample? } } for the table
533
+ meta.schema_context.database.available_tables — list of all tables that have configured actions
534
+ meta.schema_warnings — array of warning strings; if it contains "No table schema discovered..." it means no
535
+ migrations or schema have been synced to the server yet. To fix this, tell the user:
536
+ "Run: ductape db schema push --db <database_tag>
537
+ This reads the live table schema from the database and syncs it to the Ductape server,
538
+ enabling accurate field guidance for AI operations. Once complete, retry your request."
530
539
  databases.count [{ product, env, database, entity, where? }]
531
540
  databases.sum [{ product, env, database, entity, field, where? }]
532
541
  databases.avg [{ product, env, database, entity, field, where? }]
@@ -558,8 +567,8 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
558
567
  databases.action.fetch [action_tag]
559
568
  databases.action.list [database_tag]
560
569
  databases.action.delete [action_tag]
561
- databases.action.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database, action})
562
- databases.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch")
570
+ databases.action.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database: "db_tag", table: "table_name"})
571
+ databases.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database: "db_tag", table: "table_name"})
563
572
  databases.beginTransaction [{ product, env, database, isolationLevel?: "READ_COMMITTED"|"REPEATABLE_READ"|"SERIALIZABLE" }]
564
573
  → returns a transaction object; pass it to insert/update/delete/upsert/query calls as the last argument.
565
574
  Commit with: transaction.commit() Rollback with: transaction.rollback()
@@ -891,14 +900,26 @@ const payloadGenerateInputSchema = z.object({
891
900
  targets: z.record(z.any()).optional().describe('Identifies the specific operation to generate a payload for. ' +
892
901
  'For actions: { app: "app_tag", action: "action_tag" }. ' +
893
902
  'For features: { feature: "feature_tag" }. ' +
894
- 'For databases: { database: "db_tag", action?: "action_tag" }. ' +
903
+ 'For databases: { database: "db_tag", table: "table_or_collection_name" }. ' +
904
+ ' Providing table is strongly recommended — the generator scans all actions configured for that table, ' +
905
+ ' aggregates field definitions (name, type, required, sample value), and returns them in ' +
906
+ ' meta.schema_context.database.fields. The where/data placeholders in the payload are also ' +
907
+ ' pre-filled with the real field names. meta.schema_context.database.available_tables lists ' +
908
+ ' every table the database has actions configured for, so you can discover table names first. ' +
909
+ 'For graphs: { graph: "graph_tag", node_label?: "NodeLabel", edge_type?: "REL_TYPE" }. ' +
910
+ ' node_label and edge_type pre-fill the Cypher template; omit to get generic placeholders. ' +
911
+ ' meta.schema_context.graph.type tells you the engine (neo4j, neptune, etc.). ' +
912
+ 'For vectors: { vector: "vector_tag", namespace?: "ns" }. ' +
913
+ ' meta.schema_context.vector surfaces dimensions, metric, and index so you know what size ' +
914
+ ' embedding to pass and which distance function is used. ' +
895
915
  'For sessions: { session: "session_tag" }. ' +
896
916
  'For notifications: { notification: "notif_tag" }. ' +
897
917
  'For quotas/fallbacks: { tag: "resource_tag" }. ' +
898
918
  'For storage: { storage: "storage_tag" }. ' +
899
919
  'For messaging: { broker: "broker_tag", topic?: "topic_tag" }.'),
900
- include_session: z.boolean().optional().default(true).describe('Include session field in the generated payload template.'),
901
- include_cache: z.boolean().optional().default(true).describe('Include cache field in the generated payload template.'),
920
+ include_session: z.boolean().optional().default(true).describe('Include a session placeholder inside the generated input object. ' +
921
+ 'The placeholder is named "<session_tag_token>" to indicate it expects the runtime JWT, not the tag name.'),
922
+ include_cache: z.boolean().optional().default(true).describe('Include the cache tag inside the generated input object so the caller knows which cache to reference for this query.'),
902
923
  schema_mode: z.enum(['strict', 'best_effort']).optional().default('best_effort').describe('"strict" — fail if any required field cannot be resolved. ' +
903
924
  '"best_effort" — fill what is known, leave unknowns as null/placeholder. Use best_effort when exploring.'),
904
925
  input_hint: z.record(z.any()).optional().describe('Optional. Partial input values you already know. These are merged into the generated payload template ' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
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
@@ -533,11 +533,20 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
533
533
  databases.connect [{ product, env, database }]
534
534
  databases.testConnection [{ product, env, database }]
535
535
  databases.disconnect []
536
- databases.query [{ product, env, database, entity, where?: {field: {$eq|$gt|$lt|$in: value}}, select?: string[], orderBy?: [{field, order:"ASC"|"DESC"}], limit?, offset? }]
537
- databases.insert [{ product, env, database, entity, data: {key: value}|{key:value}[], returning? }]
538
- databases.update [{ product, env, database, entity, data: {key:value}, where: {key: {$eq: value}}, returning? }]
539
- databases.delete [{ product, env, database, entity, where: {key: {$eq: value}}, returning? }]
540
- databases.upsert [{ product, env, database, entity, data: {key:value}, conflictKeys: string[], returning? }]
536
+ databases.query [{ product, env, database, table, where?: {field: value}, select?: string[], orderBy?: [{field, order:"ASC"|"DESC"}], limit?, offset?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="query", targets={database, table})
537
+ databases.insert [{ product, env, database, table, data: {key: value}|{key:value}[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="insert", targets={database, table})
538
+ databases.update [{ product, env, database, table, data: {key:value}, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="update", targets={database, table})
539
+ databases.delete [{ product, env, database, table, where: {field: value}, returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="delete", targets={database, table})
540
+ databases.upsert [{ product, env, database, table, data: {key:value}, conflictKeys: string[], returning?, session?, cache? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="upsert", targets={database, table})
541
+ NOTE: ductape_generate_payload for databases returns:
542
+ payload.input — ready-to-use input with real field names in where/data, plus session and cache inside input
543
+ meta.schema_context.database.fields — { fieldName: { type, required, description?, sample? } } for the table
544
+ meta.schema_context.database.available_tables — list of all tables that have configured actions
545
+ meta.schema_warnings — array of warning strings; if it contains "No table schema discovered..." it means no
546
+ migrations or schema have been synced to the server yet. To fix this, tell the user:
547
+ "Run: ductape db schema push --db <database_tag>
548
+ This reads the live table schema from the database and syncs it to the Ductape server,
549
+ enabling accurate field guidance for AI operations. Once complete, retry your request."
541
550
  databases.count [{ product, env, database, entity, where? }]
542
551
  databases.sum [{ product, env, database, entity, field, where? }]
543
552
  databases.avg [{ product, env, database, entity, field, where? }]
@@ -569,8 +578,8 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
569
578
  databases.action.fetch [action_tag]
570
579
  databases.action.list [database_tag]
571
580
  databases.action.delete [action_tag]
572
- databases.action.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database, action})
573
- databases.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch")
581
+ databases.action.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database: "db_tag", table: "table_name"})
582
+ databases.dispatch [{ product, env, database, action, input, schedule? }] ← CALL ductape_generate_payload FIRST (operation_family="database", method="dispatch", targets={database: "db_tag", table: "table_name"})
574
583
  databases.beginTransaction [{ product, env, database, isolationLevel?: "READ_COMMITTED"|"REPEATABLE_READ"|"SERIALIZABLE" }]
575
584
  → returns a transaction object; pass it to insert/update/delete/upsert/query calls as the last argument.
576
585
  Commit with: transaction.commit() Rollback with: transaction.rollback()
@@ -913,15 +922,31 @@ const payloadGenerateInputSchema = z.object({
913
922
  'Identifies the specific operation to generate a payload for. ' +
914
923
  'For actions: { app: "app_tag", action: "action_tag" }. ' +
915
924
  'For features: { feature: "feature_tag" }. ' +
916
- 'For databases: { database: "db_tag", action?: "action_tag" }. ' +
925
+ 'For databases: { database: "db_tag", table: "table_or_collection_name" }. ' +
926
+ ' Providing table is strongly recommended — the generator scans all actions configured for that table, ' +
927
+ ' aggregates field definitions (name, type, required, sample value), and returns them in ' +
928
+ ' meta.schema_context.database.fields. The where/data placeholders in the payload are also ' +
929
+ ' pre-filled with the real field names. meta.schema_context.database.available_tables lists ' +
930
+ ' every table the database has actions configured for, so you can discover table names first. ' +
931
+ 'For graphs: { graph: "graph_tag", node_label?: "NodeLabel", edge_type?: "REL_TYPE" }. ' +
932
+ ' node_label and edge_type pre-fill the Cypher template; omit to get generic placeholders. ' +
933
+ ' meta.schema_context.graph.type tells you the engine (neo4j, neptune, etc.). ' +
934
+ 'For vectors: { vector: "vector_tag", namespace?: "ns" }. ' +
935
+ ' meta.schema_context.vector surfaces dimensions, metric, and index so you know what size ' +
936
+ ' embedding to pass and which distance function is used. ' +
917
937
  'For sessions: { session: "session_tag" }. ' +
918
938
  'For notifications: { notification: "notif_tag" }. ' +
919
939
  'For quotas/fallbacks: { tag: "resource_tag" }. ' +
920
940
  'For storage: { storage: "storage_tag" }. ' +
921
941
  'For messaging: { broker: "broker_tag", topic?: "topic_tag" }.'
922
942
  ),
923
- include_session: z.boolean().optional().default(true).describe('Include session field in the generated payload template.'),
924
- include_cache: z.boolean().optional().default(true).describe('Include cache field in the generated payload template.'),
943
+ include_session: z.boolean().optional().default(true).describe(
944
+ 'Include a session placeholder inside the generated input object. ' +
945
+ 'The placeholder is named "<session_tag_token>" to indicate it expects the runtime JWT, not the tag name.'
946
+ ),
947
+ include_cache: z.boolean().optional().default(true).describe(
948
+ 'Include the cache tag inside the generated input object so the caller knows which cache to reference for this query.'
949
+ ),
925
950
  schema_mode: z.enum(['strict', 'best_effort']).optional().default('best_effort').describe(
926
951
  '"strict" — fail if any required field cannot be resolved. ' +
927
952
  '"best_effort" — fill what is known, leave unknowns as null/placeholder. Use best_effort when exploring.'