@jaypie/dynamodb 0.2.0 → 0.4.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.
@@ -1,5 +1,5 @@
1
- import { registerMcpTool } from '@jaypie/vocabulary/mcp';
2
- import { getModelIndexes, populateIndexKeys, SEPARATOR, serviceHandler, ARCHIVED_SUFFIX, DELETED_SUFFIX, DEFAULT_INDEXES, getAllRegisteredIndexes } from '@jaypie/vocabulary';
1
+ import { fabricMcp } from '@jaypie/fabric/mcp';
2
+ import { getModelIndexes, populateIndexKeys, SEPARATOR, fabricService, ARCHIVED_SUFFIX, DELETED_SUFFIX, DEFAULT_INDEXES, getAllRegisteredIndexes } from '@jaypie/fabric';
3
3
  import { DynamoDBClient, DescribeTableCommand, CreateTableCommand } from '@aws-sdk/client-dynamodb';
4
4
  import { DynamoDBDocumentClient, GetCommand, PutCommand, DeleteCommand, QueryCommand } from '@aws-sdk/lib-dynamodb';
5
5
  import { ConfigurationError } from '@jaypie/errors';
@@ -75,11 +75,11 @@ function isInitialized() {
75
75
  return docClient !== null && tableName !== null;
76
76
  }
77
77
 
78
- // Re-export shared constants from vocabulary
78
+ // Re-export shared constants from fabric
79
79
  // GSI names (derived from DEFAULT_INDEXES)
80
80
  const INDEX_ALIAS = "indexAlias";
81
81
  const INDEX_CLASS = "indexClass";
82
- const INDEX_OU = "indexOu";
82
+ const INDEX_SCOPE = "indexScope";
83
83
  const INDEX_TYPE = "indexType";
84
84
  const INDEX_XID = "indexXid";
85
85
 
@@ -87,53 +87,53 @@ const INDEX_XID = "indexXid";
87
87
  // Key Builders
88
88
  // =============================================================================
89
89
  /**
90
- * Build the indexOu key for hierarchical queries
91
- * @param ou - The organizational unit (APEX or "{parent.model}#{parent.id}")
90
+ * Build the indexScope key for hierarchical queries
91
+ * @param scope - The scope (APEX or "{parent.model}#{parent.id}")
92
92
  * @param model - The entity model name
93
- * @returns Composite key: "{ou}#{model}"
93
+ * @returns Composite key: "{scope}#{model}"
94
94
  */
95
- function buildIndexOu(ou, model) {
96
- return `${ou}${SEPARATOR}${model}`;
95
+ function buildIndexScope(scope, model) {
96
+ return `${scope}${SEPARATOR}${model}`;
97
97
  }
98
98
  /**
99
99
  * Build the indexAlias key for human-friendly lookups
100
- * @param ou - The organizational unit
100
+ * @param scope - The scope
101
101
  * @param model - The entity model name
102
102
  * @param alias - The human-friendly alias
103
- * @returns Composite key: "{ou}#{model}#{alias}"
103
+ * @returns Composite key: "{scope}#{model}#{alias}"
104
104
  */
105
- function buildIndexAlias(ou, model, alias) {
106
- return `${ou}${SEPARATOR}${model}${SEPARATOR}${alias}`;
105
+ function buildIndexAlias(scope, model, alias) {
106
+ return `${scope}${SEPARATOR}${model}${SEPARATOR}${alias}`;
107
107
  }
108
108
  /**
109
109
  * Build the indexClass key for category filtering
110
- * @param ou - The organizational unit
110
+ * @param scope - The scope
111
111
  * @param model - The entity model name
112
112
  * @param recordClass - The category classification
113
- * @returns Composite key: "{ou}#{model}#{class}"
113
+ * @returns Composite key: "{scope}#{model}#{class}"
114
114
  */
115
- function buildIndexClass(ou, model, recordClass) {
116
- return `${ou}${SEPARATOR}${model}${SEPARATOR}${recordClass}`;
115
+ function buildIndexClass(scope, model, recordClass) {
116
+ return `${scope}${SEPARATOR}${model}${SEPARATOR}${recordClass}`;
117
117
  }
118
118
  /**
119
119
  * Build the indexType key for type filtering
120
- * @param ou - The organizational unit
120
+ * @param scope - The scope
121
121
  * @param model - The entity model name
122
122
  * @param type - The type classification
123
- * @returns Composite key: "{ou}#{model}#{type}"
123
+ * @returns Composite key: "{scope}#{model}#{type}"
124
124
  */
125
- function buildIndexType(ou, model, type) {
126
- return `${ou}${SEPARATOR}${model}${SEPARATOR}${type}`;
125
+ function buildIndexType(scope, model, type) {
126
+ return `${scope}${SEPARATOR}${model}${SEPARATOR}${type}`;
127
127
  }
128
128
  /**
129
129
  * Build the indexXid key for external ID lookups
130
- * @param ou - The organizational unit
130
+ * @param scope - The scope
131
131
  * @param model - The entity model name
132
132
  * @param xid - The external ID
133
- * @returns Composite key: "{ou}#{model}#{xid}"
133
+ * @returns Composite key: "{scope}#{model}#{xid}"
134
134
  */
135
- function buildIndexXid(ou, model, xid) {
136
- return `${ou}${SEPARATOR}${model}${SEPARATOR}${xid}`;
135
+ function buildIndexXid(scope, model, xid) {
136
+ return `${scope}${SEPARATOR}${model}${SEPARATOR}${xid}`;
137
137
  }
138
138
  /**
139
139
  * Auto-populate GSI index keys on an entity
@@ -141,7 +141,7 @@ function buildIndexXid(ou, model, xid) {
141
141
  * Uses the model's registered indexes (from vocabulary registry) or
142
142
  * DEFAULT_INDEXES if no custom indexes are registered.
143
143
  *
144
- * - indexOu is always populated from ou + model
144
+ * - indexScope is always populated from scope + model
145
145
  * - indexAlias is populated only when alias is present
146
146
  * - indexClass is populated only when class is present
147
147
  * - indexType is populated only when type is present
@@ -153,7 +153,7 @@ function buildIndexXid(ou, model, xid) {
153
153
  */
154
154
  function indexEntity(entity, suffix = "") {
155
155
  const indexes = getModelIndexes(entity.model);
156
- // Cast through unknown to bridge the type gap between StorableEntity and IndexableEntity
156
+ // Cast through unknown to bridge the type gap between StorableEntity and IndexableModel
157
157
  return populateIndexKeys(entity, indexes, suffix);
158
158
  }
159
159
 
@@ -177,7 +177,7 @@ function calculateEntitySuffix(entity) {
177
177
  /**
178
178
  * Get a single entity by primary key
179
179
  */
180
- const getEntity = serviceHandler({
180
+ const getEntity = fabricService({
181
181
  alias: "getEntity",
182
182
  description: "Get a single entity by primary key",
183
183
  input: {
@@ -199,7 +199,7 @@ const getEntity = serviceHandler({
199
199
  * Put (create or replace) an entity
200
200
  * Auto-populates GSI index keys via indexEntity
201
201
  *
202
- * Note: This is a regular async function (not serviceHandler) because it accepts
202
+ * Note: This is a regular async function (not fabricService) because it accepts
203
203
  * complex StorableEntity objects that can't be coerced by vocabulary's type system.
204
204
  */
205
205
  async function putEntity({ entity, }) {
@@ -218,7 +218,7 @@ async function putEntity({ entity, }) {
218
218
  * Update an existing entity
219
219
  * Auto-populates GSI index keys and sets updatedAt
220
220
  *
221
- * Note: This is a regular async function (not serviceHandler) because it accepts
221
+ * Note: This is a regular async function (not fabricService) because it accepts
222
222
  * complex StorableEntity objects that can't be coerced by vocabulary's type system.
223
223
  */
224
224
  async function updateEntity({ entity, }) {
@@ -240,7 +240,7 @@ async function updateEntity({ entity, }) {
240
240
  * Soft delete an entity by setting deletedAt timestamp
241
241
  * Re-indexes with appropriate suffix based on archived/deleted state
242
242
  */
243
- const deleteEntity = serviceHandler({
243
+ const deleteEntity = fabricService({
244
244
  alias: "deleteEntity",
245
245
  description: "Soft delete an entity (sets deletedAt timestamp)",
246
246
  input: {
@@ -277,7 +277,7 @@ const deleteEntity = serviceHandler({
277
277
  * Archive an entity by setting archivedAt timestamp
278
278
  * Re-indexes with appropriate suffix based on archived/deleted state
279
279
  */
280
- const archiveEntity = serviceHandler({
280
+ const archiveEntity = fabricService({
281
281
  alias: "archiveEntity",
282
282
  description: "Archive an entity (sets archivedAt timestamp)",
283
283
  input: {
@@ -314,7 +314,7 @@ const archiveEntity = serviceHandler({
314
314
  * Hard delete an entity (permanently removes from table)
315
315
  * Use with caution - prefer deleteEntity for soft delete
316
316
  */
317
- const destroyEntity = serviceHandler({
317
+ const destroyEntity = fabricService({
318
318
  alias: "destroyEntity",
319
319
  description: "Hard delete an entity (permanently removes from table)",
320
320
  input: {
@@ -377,16 +377,16 @@ async function executeQuery(indexName, keyValue, options = {}) {
377
377
  };
378
378
  }
379
379
  /**
380
- * Query entities by organizational unit (parent hierarchy)
381
- * Uses indexOu GSI
380
+ * Query entities by scope (parent hierarchy)
381
+ * Uses indexScope GSI
382
382
  *
383
- * Note: This is a regular async function (not serviceHandler) because it accepts
383
+ * Note: This is a regular async function (not fabricService) because it accepts
384
384
  * complex startKey objects that can't be coerced by vocabulary's type system.
385
385
  */
386
- async function queryByOu({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, }) {
386
+ async function queryByScope({ archived = false, ascending = false, deleted = false, limit, model, scope, startKey, }) {
387
387
  const suffix = calculateSuffix({ archived, deleted });
388
- const keyValue = buildIndexOu(ou, model) + suffix;
389
- return executeQuery(INDEX_OU, keyValue, {
388
+ const keyValue = buildIndexScope(scope, model) + suffix;
389
+ return executeQuery(INDEX_SCOPE, keyValue, {
390
390
  ascending,
391
391
  limit,
392
392
  startKey,
@@ -396,7 +396,7 @@ async function queryByOu({ archived = false, ascending = false, deleted = false,
396
396
  * Query a single entity by human-friendly alias
397
397
  * Uses indexAlias GSI
398
398
  */
399
- const queryByAlias = serviceHandler({
399
+ const queryByAlias = fabricService({
400
400
  alias: "queryByAlias",
401
401
  description: "Query a single entity by human-friendly alias",
402
402
  input: {
@@ -414,16 +414,19 @@ const queryByAlias = serviceHandler({
414
414
  description: "Query deleted entities instead of active ones",
415
415
  },
416
416
  model: { type: String, description: "Entity model name" },
417
- ou: { type: String, description: "Organizational unit (@ for root)" },
417
+ scope: { type: String, description: "Scope (@ for root)" },
418
418
  },
419
- service: async ({ alias, archived, deleted, model, ou, }) => {
419
+ service: async ({ alias, archived, deleted, model, scope, }) => {
420
420
  const aliasStr = alias;
421
421
  const archivedBool = archived;
422
422
  const deletedBool = deleted;
423
423
  const modelStr = model;
424
- const ouStr = ou;
425
- const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
426
- const keyValue = buildIndexAlias(ouStr, modelStr, aliasStr) + suffix;
424
+ const scopeStr = scope;
425
+ const suffix = calculateSuffix({
426
+ archived: archivedBool,
427
+ deleted: deletedBool,
428
+ });
429
+ const keyValue = buildIndexAlias(scopeStr, modelStr, aliasStr) + suffix;
427
430
  const result = await executeQuery(INDEX_ALIAS, keyValue, {
428
431
  limit: 1,
429
432
  });
@@ -434,12 +437,12 @@ const queryByAlias = serviceHandler({
434
437
  * Query entities by category classification
435
438
  * Uses indexClass GSI
436
439
  *
437
- * Note: This is a regular async function (not serviceHandler) because it accepts
440
+ * Note: This is a regular async function (not fabricService) because it accepts
438
441
  * complex startKey objects that can't be coerced by vocabulary's type system.
439
442
  */
440
- async function queryByClass({ archived = false, ascending = false, deleted = false, limit, model, ou, recordClass, startKey, }) {
443
+ async function queryByClass({ archived = false, ascending = false, deleted = false, limit, model, scope, recordClass, startKey, }) {
441
444
  const suffix = calculateSuffix({ archived, deleted });
442
- const keyValue = buildIndexClass(ou, model, recordClass) + suffix;
445
+ const keyValue = buildIndexClass(scope, model, recordClass) + suffix;
443
446
  return executeQuery(INDEX_CLASS, keyValue, {
444
447
  ascending,
445
448
  limit,
@@ -450,12 +453,12 @@ async function queryByClass({ archived = false, ascending = false, deleted = fal
450
453
  * Query entities by type classification
451
454
  * Uses indexType GSI
452
455
  *
453
- * Note: This is a regular async function (not serviceHandler) because it accepts
456
+ * Note: This is a regular async function (not fabricService) because it accepts
454
457
  * complex startKey objects that can't be coerced by vocabulary's type system.
455
458
  */
456
- async function queryByType({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, type, }) {
459
+ async function queryByType({ archived = false, ascending = false, deleted = false, limit, model, scope, startKey, type, }) {
457
460
  const suffix = calculateSuffix({ archived, deleted });
458
- const keyValue = buildIndexType(ou, model, type) + suffix;
461
+ const keyValue = buildIndexType(scope, model, type) + suffix;
459
462
  return executeQuery(INDEX_TYPE, keyValue, {
460
463
  ascending,
461
464
  limit,
@@ -466,7 +469,7 @@ async function queryByType({ archived = false, ascending = false, deleted = fals
466
469
  * Query a single entity by external ID
467
470
  * Uses indexXid GSI
468
471
  */
469
- const queryByXid = serviceHandler({
472
+ const queryByXid = fabricService({
470
473
  alias: "queryByXid",
471
474
  description: "Query a single entity by external ID",
472
475
  input: {
@@ -483,17 +486,20 @@ const queryByXid = serviceHandler({
483
486
  description: "Query deleted entities instead of active ones",
484
487
  },
485
488
  model: { type: String, description: "Entity model name" },
486
- ou: { type: String, description: "Organizational unit (@ for root)" },
489
+ scope: { type: String, description: "Scope (@ for root)" },
487
490
  xid: { type: String, description: "External ID" },
488
491
  },
489
- service: async ({ archived, deleted, model, ou, xid, }) => {
492
+ service: async ({ archived, deleted, model, scope, xid, }) => {
490
493
  const archivedBool = archived;
491
494
  const deletedBool = deleted;
492
495
  const modelStr = model;
493
- const ouStr = ou;
496
+ const scopeStr = scope;
494
497
  const xidStr = xid;
495
- const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
496
- const keyValue = buildIndexXid(ouStr, modelStr, xidStr) + suffix;
498
+ const suffix = calculateSuffix({
499
+ archived: archivedBool,
500
+ deleted: deletedBool,
501
+ });
502
+ const keyValue = buildIndexXid(scopeStr, modelStr, xidStr) + suffix;
497
503
  const result = await executeQuery(INDEX_XID, keyValue, {
498
504
  limit: 1,
499
505
  });
@@ -614,7 +620,7 @@ function createTableParams(tableName, billingMode) {
614
620
  /**
615
621
  * Create DynamoDB table with Jaypie GSI schema
616
622
  */
617
- const createTableHandler = serviceHandler({
623
+ const createTableHandler = fabricService({
618
624
  alias: "dynamodb_create_table",
619
625
  description: "Create DynamoDB table with Jaypie GSI schema",
620
626
  input: {
@@ -678,7 +684,7 @@ const DEFAULT_TABLE_NAME = "jaypie-local";
678
684
  /**
679
685
  * Generate docker-compose.yml for local DynamoDB development
680
686
  */
681
- const dockerComposeHandler = serviceHandler({
687
+ const dockerComposeHandler = fabricService({
682
688
  alias: "dynamodb_generate_docker_compose",
683
689
  description: "Generate docker-compose.yml for local DynamoDB development",
684
690
  input: {
@@ -776,7 +782,7 @@ function ensureInitialized() {
776
782
  /**
777
783
  * Check DynamoDB connection status and configuration
778
784
  */
779
- const statusHandler = serviceHandler({
785
+ const statusHandler = fabricService({
780
786
  alias: "dynamodb_status",
781
787
  description: "Check DynamoDB connection status and configuration",
782
788
  service: async () => {
@@ -807,12 +813,12 @@ function wrapWithInit(handler) {
807
813
  return wrapped;
808
814
  }
809
815
  // MCP-specific serviceHandler wrappers for functions with complex inputs
810
- // Note: These wrap the regular async functions to make them work with registerMcpTool
816
+ // Note: These wrap the regular async functions to make them work with fabricMcp
811
817
  /**
812
818
  * MCP wrapper for putEntity
813
819
  * Accepts entity JSON directly from LLM
814
820
  */
815
- const mcpPutEntity = serviceHandler({
821
+ const mcpPutEntity = fabricService({
816
822
  alias: "dynamodb_put",
817
823
  description: "Create or replace an entity in DynamoDB (auto-indexes GSI keys)",
818
824
  input: {
@@ -820,10 +826,18 @@ const mcpPutEntity = serviceHandler({
820
826
  id: { type: String, description: "Entity ID (sort key)" },
821
827
  model: { type: String, description: "Entity model name (partition key)" },
822
828
  name: { type: String, description: "Entity name" },
823
- ou: { type: String, description: "Organizational unit (@ for root)" },
829
+ scope: { type: String, description: "Scope (@ for root)" },
824
830
  // Optional fields
825
- alias: { type: String, required: false, description: "Human-friendly alias" },
826
- class: { type: String, required: false, description: "Category classification" },
831
+ alias: {
832
+ type: String,
833
+ required: false,
834
+ description: "Human-friendly alias",
835
+ },
836
+ class: {
837
+ type: String,
838
+ required: false,
839
+ description: "Category classification",
840
+ },
827
841
  type: { type: String, required: false, description: "Type classification" },
828
842
  xid: { type: String, required: false, description: "External ID" },
829
843
  },
@@ -836,7 +850,7 @@ const mcpPutEntity = serviceHandler({
836
850
  id: input.id,
837
851
  model: input.model,
838
852
  name: input.name,
839
- ou: input.ou,
853
+ scope: input.scope,
840
854
  sequence: Date.now(),
841
855
  type: input.type,
842
856
  updatedAt: now,
@@ -849,7 +863,7 @@ const mcpPutEntity = serviceHandler({
849
863
  * MCP wrapper for updateEntity
850
864
  * Accepts entity JSON directly from LLM
851
865
  */
852
- const mcpUpdateEntity = serviceHandler({
866
+ const mcpUpdateEntity = fabricService({
853
867
  alias: "dynamodb_update",
854
868
  description: "Update an entity in DynamoDB (sets updatedAt, re-indexes GSI keys)",
855
869
  input: {
@@ -858,9 +872,17 @@ const mcpUpdateEntity = serviceHandler({
858
872
  model: { type: String, description: "Entity model name (partition key)" },
859
873
  // Fields that can be updated
860
874
  name: { type: String, required: false, description: "Entity name" },
861
- ou: { type: String, required: false, description: "Organizational unit" },
862
- alias: { type: String, required: false, description: "Human-friendly alias" },
863
- class: { type: String, required: false, description: "Category classification" },
875
+ scope: { type: String, required: false, description: "Scope" },
876
+ alias: {
877
+ type: String,
878
+ required: false,
879
+ description: "Human-friendly alias",
880
+ },
881
+ class: {
882
+ type: String,
883
+ required: false,
884
+ description: "Category classification",
885
+ },
864
886
  type: { type: String, required: false, description: "Type classification" },
865
887
  xid: { type: String, required: false, description: "External ID" },
866
888
  },
@@ -879,7 +901,7 @@ const mcpUpdateEntity = serviceHandler({
879
901
  ...(input.alias !== undefined && { alias: input.alias }),
880
902
  ...(input.class !== undefined && { class: input.class }),
881
903
  ...(input.name !== undefined && { name: input.name }),
882
- ...(input.ou !== undefined && { ou: input.ou }),
904
+ ...(input.scope !== undefined && { scope: input.scope }),
883
905
  ...(input.type !== undefined && { type: input.type }),
884
906
  ...(input.xid !== undefined && { xid: input.xid }),
885
907
  };
@@ -887,15 +909,15 @@ const mcpUpdateEntity = serviceHandler({
887
909
  },
888
910
  });
889
911
  /**
890
- * MCP wrapper for queryByOu
912
+ * MCP wrapper for queryByScope
891
913
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
892
914
  */
893
- const mcpQueryByOu = serviceHandler({
894
- alias: "dynamodb_query_ou",
895
- description: "Query entities by organizational unit (parent hierarchy)",
915
+ const mcpQueryByScope = fabricService({
916
+ alias: "dynamodb_query_scope",
917
+ description: "Query entities by scope (parent hierarchy)",
896
918
  input: {
897
919
  model: { type: String, description: "Entity model name" },
898
- ou: { type: String, description: "Organizational unit (@ for root)" },
920
+ scope: { type: String, description: "Scope (@ for root)" },
899
921
  archived: {
900
922
  type: Boolean,
901
923
  default: false,
@@ -921,13 +943,13 @@ const mcpQueryByOu = serviceHandler({
921
943
  },
922
944
  },
923
945
  service: async (input) => {
924
- return queryByOu({
946
+ return queryByScope({
925
947
  archived: input.archived,
926
948
  ascending: input.ascending,
927
949
  deleted: input.deleted,
928
950
  limit: input.limit,
929
951
  model: input.model,
930
- ou: input.ou,
952
+ scope: input.scope,
931
953
  });
932
954
  },
933
955
  });
@@ -935,12 +957,12 @@ const mcpQueryByOu = serviceHandler({
935
957
  * MCP wrapper for queryByClass
936
958
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
937
959
  */
938
- const mcpQueryByClass = serviceHandler({
960
+ const mcpQueryByClass = fabricService({
939
961
  alias: "dynamodb_query_class",
940
962
  description: "Query entities by category classification",
941
963
  input: {
942
964
  model: { type: String, description: "Entity model name" },
943
- ou: { type: String, description: "Organizational unit (@ for root)" },
965
+ scope: { type: String, description: "Scope (@ for root)" },
944
966
  recordClass: { type: String, description: "Category classification" },
945
967
  archived: {
946
968
  type: Boolean,
@@ -973,7 +995,7 @@ const mcpQueryByClass = serviceHandler({
973
995
  deleted: input.deleted,
974
996
  limit: input.limit,
975
997
  model: input.model,
976
- ou: input.ou,
998
+ scope: input.scope,
977
999
  recordClass: input.recordClass,
978
1000
  });
979
1001
  },
@@ -982,12 +1004,12 @@ const mcpQueryByClass = serviceHandler({
982
1004
  * MCP wrapper for queryByType
983
1005
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
984
1006
  */
985
- const mcpQueryByType = serviceHandler({
1007
+ const mcpQueryByType = fabricService({
986
1008
  alias: "dynamodb_query_type",
987
1009
  description: "Query entities by type classification",
988
1010
  input: {
989
1011
  model: { type: String, description: "Entity model name" },
990
- ou: { type: String, description: "Organizational unit (@ for root)" },
1012
+ scope: { type: String, description: "Scope (@ for root)" },
991
1013
  type: { type: String, description: "Type classification" },
992
1014
  archived: {
993
1015
  type: Boolean,
@@ -1020,7 +1042,7 @@ const mcpQueryByType = serviceHandler({
1020
1042
  deleted: input.deleted,
1021
1043
  limit: input.limit,
1022
1044
  model: input.model,
1023
- ou: input.ou,
1045
+ scope: input.scope,
1024
1046
  type: input.type,
1025
1047
  });
1026
1048
  },
@@ -1032,80 +1054,80 @@ function registerDynamoDbTools(config) {
1032
1054
  const { includeAdmin = true, server } = config;
1033
1055
  const tools = [];
1034
1056
  // Entity operations
1035
- registerMcpTool({
1036
- handler: wrapWithInit(getEntity),
1057
+ fabricMcp({
1058
+ service: wrapWithInit(getEntity),
1037
1059
  name: "dynamodb_get",
1038
1060
  server,
1039
1061
  });
1040
1062
  tools.push("dynamodb_get");
1041
- registerMcpTool({
1042
- handler: wrapWithInit(mcpPutEntity),
1063
+ fabricMcp({
1064
+ service: wrapWithInit(mcpPutEntity),
1043
1065
  name: "dynamodb_put",
1044
1066
  server,
1045
1067
  });
1046
1068
  tools.push("dynamodb_put");
1047
- registerMcpTool({
1048
- handler: wrapWithInit(mcpUpdateEntity),
1069
+ fabricMcp({
1070
+ service: wrapWithInit(mcpUpdateEntity),
1049
1071
  name: "dynamodb_update",
1050
1072
  server,
1051
1073
  });
1052
1074
  tools.push("dynamodb_update");
1053
- registerMcpTool({
1054
- handler: wrapWithInit(deleteEntity),
1075
+ fabricMcp({
1076
+ service: wrapWithInit(deleteEntity),
1055
1077
  name: "dynamodb_delete",
1056
1078
  server,
1057
1079
  });
1058
1080
  tools.push("dynamodb_delete");
1059
- registerMcpTool({
1060
- handler: wrapWithInit(archiveEntity),
1081
+ fabricMcp({
1082
+ service: wrapWithInit(archiveEntity),
1061
1083
  name: "dynamodb_archive",
1062
1084
  server,
1063
1085
  });
1064
1086
  tools.push("dynamodb_archive");
1065
- registerMcpTool({
1066
- handler: wrapWithInit(destroyEntity),
1087
+ fabricMcp({
1088
+ service: wrapWithInit(destroyEntity),
1067
1089
  name: "dynamodb_destroy",
1068
1090
  server,
1069
1091
  });
1070
1092
  tools.push("dynamodb_destroy");
1071
1093
  // Query operations
1072
- registerMcpTool({
1073
- handler: wrapWithInit(mcpQueryByOu),
1074
- name: "dynamodb_query_ou",
1094
+ fabricMcp({
1095
+ service: wrapWithInit(mcpQueryByScope),
1096
+ name: "dynamodb_query_scope",
1075
1097
  server,
1076
1098
  });
1077
- tools.push("dynamodb_query_ou");
1078
- registerMcpTool({
1079
- handler: wrapWithInit(queryByAlias),
1099
+ tools.push("dynamodb_query_scope");
1100
+ fabricMcp({
1101
+ service: wrapWithInit(queryByAlias),
1080
1102
  name: "dynamodb_query_alias",
1081
1103
  server,
1082
1104
  });
1083
1105
  tools.push("dynamodb_query_alias");
1084
- registerMcpTool({
1085
- handler: wrapWithInit(mcpQueryByClass),
1106
+ fabricMcp({
1107
+ service: wrapWithInit(mcpQueryByClass),
1086
1108
  name: "dynamodb_query_class",
1087
1109
  server,
1088
1110
  });
1089
1111
  tools.push("dynamodb_query_class");
1090
- registerMcpTool({
1091
- handler: wrapWithInit(mcpQueryByType),
1112
+ fabricMcp({
1113
+ service: wrapWithInit(mcpQueryByType),
1092
1114
  name: "dynamodb_query_type",
1093
1115
  server,
1094
1116
  });
1095
1117
  tools.push("dynamodb_query_type");
1096
- registerMcpTool({
1097
- handler: wrapWithInit(queryByXid),
1118
+ fabricMcp({
1119
+ service: wrapWithInit(queryByXid),
1098
1120
  name: "dynamodb_query_xid",
1099
1121
  server,
1100
1122
  });
1101
1123
  tools.push("dynamodb_query_xid");
1102
1124
  // Admin tools (MCP-only)
1103
1125
  if (includeAdmin) {
1104
- registerMcpTool({ handler: statusHandler, server });
1126
+ fabricMcp({ service: statusHandler, server });
1105
1127
  tools.push("dynamodb_status");
1106
- registerMcpTool({ handler: createTableHandler, server });
1128
+ fabricMcp({ service: createTableHandler, server });
1107
1129
  tools.push("dynamodb_create_table");
1108
- registerMcpTool({ handler: dockerComposeHandler, server });
1130
+ fabricMcp({ service: dockerComposeHandler, server });
1109
1131
  tools.push("dynamodb_generate_docker_compose");
1110
1132
  }
1111
1133
  return { tools };