@documentation-robotics/cli 0.1.13 → 0.2.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.
Files changed (181) hide show
  1. package/README.md +38 -0
  2. package/dist/analyzers/verify-engine.js +22 -19
  3. package/dist/analyzers/verify-engine.js.map +2 -2
  4. package/dist/cli.js +101 -27
  5. package/dist/cli.js.map +3 -3
  6. package/dist/coding-agents/agents/claude-code.js +3 -1
  7. package/dist/coding-agents/agents/claude-code.js.map +2 -2
  8. package/dist/coding-agents/claude-code-client.js +2 -1
  9. package/dist/coding-agents/claude-code-client.js.map +2 -2
  10. package/dist/coding-agents/copilot-client.js +17 -12
  11. package/dist/coding-agents/copilot-client.js.map +2 -2
  12. package/dist/coding-agents/default-permissions.js +122 -0
  13. package/dist/coding-agents/default-permissions.js.map +7 -0
  14. package/dist/commands/add.js +10 -6
  15. package/dist/commands/add.js.map +2 -2
  16. package/dist/commands/analyzer.js +18 -10
  17. package/dist/commands/analyzer.js.map +2 -2
  18. package/dist/commands/audit.js +6 -6
  19. package/dist/commands/audit.js.map +2 -2
  20. package/dist/commands/changeset.js +238 -145
  21. package/dist/commands/changeset.js.map +2 -2
  22. package/dist/commands/delete.js +45 -18
  23. package/dist/commands/delete.js.map +3 -3
  24. package/dist/commands/element.js +3 -2
  25. package/dist/commands/element.js.map +2 -2
  26. package/dist/commands/farm.js +657 -0
  27. package/dist/commands/farm.js.map +7 -0
  28. package/dist/commands/init.js +11 -1
  29. package/dist/commands/init.js.map +2 -2
  30. package/dist/commands/mcp.js +107 -0
  31. package/dist/commands/mcp.js.map +7 -0
  32. package/dist/commands/relationship.js +53 -30
  33. package/dist/commands/relationship.js.map +2 -2
  34. package/dist/commands/reports.js +1 -1
  35. package/dist/commands/reports.js.map +2 -2
  36. package/dist/commands/update.js +19 -6
  37. package/dist/commands/update.js.map +2 -2
  38. package/dist/commands/validate.js +41 -3
  39. package/dist/commands/validate.js.map +2 -2
  40. package/dist/commands/version.js +2 -2
  41. package/dist/commands/version.js.map +2 -2
  42. package/dist/config.js +83 -0
  43. package/dist/config.js.map +7 -0
  44. package/dist/core/annotation-store.js +138 -0
  45. package/dist/core/annotation-store.js.map +7 -0
  46. package/dist/core/farm-manifest.js +134 -0
  47. package/dist/core/farm-manifest.js.map +7 -0
  48. package/dist/core/farm-sync-engine.js +346 -0
  49. package/dist/core/farm-sync-engine.js.map +7 -0
  50. package/dist/core/farm-sync-state.js +159 -0
  51. package/dist/core/farm-sync-state.js.map +7 -0
  52. package/dist/core/manifest.js +6 -3
  53. package/dist/core/manifest.js.map +2 -2
  54. package/dist/core/migration-registry.js +55 -1
  55. package/dist/core/migration-registry.js.map +2 -2
  56. package/dist/core/model.js +177 -16
  57. package/dist/core/model.js.map +3 -3
  58. package/dist/core/virtual-projection.js +1 -0
  59. package/dist/core/virtual-projection.js.map +2 -2
  60. package/dist/generated/node-types.js +1 -1
  61. package/dist/generated/node-types.js.map +2 -2
  62. package/dist/generated/relationship-index.js +45 -9
  63. package/dist/generated/relationship-index.js.map +2 -2
  64. package/dist/integrations/claude_code/docs/MCP_SERVER.md +55 -0
  65. package/dist/integrations/claude_code/docs/README.md +4 -0
  66. package/dist/mcp/api-key-manager.js +98 -0
  67. package/dist/mcp/api-key-manager.js.map +7 -0
  68. package/dist/mcp/http-transport.js +176 -0
  69. package/dist/mcp/http-transport.js.map +7 -0
  70. package/dist/mcp/resource-registry.js +97 -0
  71. package/dist/mcp/resource-registry.js.map +7 -0
  72. package/dist/mcp/tool-registry.js +44 -0
  73. package/dist/mcp/tool-registry.js.map +7 -0
  74. package/dist/mcp/tools/annotation-create.js +39 -0
  75. package/dist/mcp/tools/annotation-create.js.map +7 -0
  76. package/dist/mcp/tools/annotation-delete.js +29 -0
  77. package/dist/mcp/tools/annotation-delete.js.map +7 -0
  78. package/dist/mcp/tools/annotation-get.js +29 -0
  79. package/dist/mcp/tools/annotation-get.js.map +7 -0
  80. package/dist/mcp/tools/annotation-list.js +24 -0
  81. package/dist/mcp/tools/annotation-list.js.map +7 -0
  82. package/dist/mcp/tools/annotation-reply.js +34 -0
  83. package/dist/mcp/tools/annotation-reply.js.map +7 -0
  84. package/dist/mcp/tools/annotation-shared.js +10 -0
  85. package/dist/mcp/tools/annotation-shared.js.map +7 -0
  86. package/dist/mcp/tools/annotation-update.js +39 -0
  87. package/dist/mcp/tools/annotation-update.js.map +7 -0
  88. package/dist/mcp/tools/changeset-list.js +33 -0
  89. package/dist/mcp/tools/changeset-list.js.map +7 -0
  90. package/dist/mcp/tools/changeset-show.js +39 -0
  91. package/dist/mcp/tools/changeset-show.js.map +7 -0
  92. package/dist/mcp/tools/chat-launch.js +50 -0
  93. package/dist/mcp/tools/chat-launch.js.map +7 -0
  94. package/dist/mcp/tools/chat-status.js +26 -0
  95. package/dist/mcp/tools/chat-status.js.map +7 -0
  96. package/dist/mcp/tools/index.js +47 -0
  97. package/dist/mcp/tools/index.js.map +7 -0
  98. package/dist/mcp/tools/model-add.js +106 -0
  99. package/dist/mcp/tools/model-add.js.map +7 -0
  100. package/dist/mcp/tools/model-delete.js +99 -0
  101. package/dist/mcp/tools/model-delete.js.map +7 -0
  102. package/dist/mcp/tools/model-export.js +72 -0
  103. package/dist/mcp/tools/model-export.js.map +7 -0
  104. package/dist/mcp/tools/model-info.js +51 -0
  105. package/dist/mcp/tools/model-info.js.map +7 -0
  106. package/dist/mcp/tools/model-list.js +53 -0
  107. package/dist/mcp/tools/model-list.js.map +7 -0
  108. package/dist/mcp/tools/model-reload.js +34 -0
  109. package/dist/mcp/tools/model-reload.js.map +7 -0
  110. package/dist/mcp/tools/model-search.js +88 -0
  111. package/dist/mcp/tools/model-search.js.map +7 -0
  112. package/dist/mcp/tools/model-show.js +41 -0
  113. package/dist/mcp/tools/model-show.js.map +7 -0
  114. package/dist/mcp/tools/model-stats.js +22 -0
  115. package/dist/mcp/tools/model-stats.js.map +7 -0
  116. package/dist/mcp/tools/model-trace.js +55 -0
  117. package/dist/mcp/tools/model-trace.js.map +7 -0
  118. package/dist/mcp/tools/model-update.js +105 -0
  119. package/dist/mcp/tools/model-update.js.map +7 -0
  120. package/dist/mcp/tools/model-validate.js +78 -0
  121. package/dist/mcp/tools/model-validate.js.map +7 -0
  122. package/dist/mcp/tools/shared.js +103 -0
  123. package/dist/mcp/tools/shared.js.map +7 -0
  124. package/dist/reports/model-layer-report-generator.js +5 -3
  125. package/dist/reports/model-layer-report-generator.js.map +2 -2
  126. package/dist/reports/model-readme-generator.js +116 -0
  127. package/dist/reports/model-readme-generator.js.map +7 -0
  128. package/dist/reports/model-report-data.js +37 -1
  129. package/dist/reports/model-report-data.js.map +2 -2
  130. package/dist/reports/model-report-orchestrator.js +29 -6
  131. package/dist/reports/model-report-orchestrator.js.map +2 -2
  132. package/dist/reports/model-report-utils.js +9 -0
  133. package/dist/reports/model-report-utils.js.map +7 -0
  134. package/dist/schemas/bundled/analyzers/cbm.json +2 -2
  135. package/dist/schemas/bundled/analyzers/manifest.json +2 -2
  136. package/dist/schemas/bundled/api.json +1 -1
  137. package/dist/schemas/bundled/apm.json +1 -1
  138. package/dist/schemas/bundled/application.json +12 -1
  139. package/dist/schemas/bundled/base.json +1 -1
  140. package/dist/schemas/bundled/business.json +1 -1
  141. package/dist/schemas/bundled/data-model.json +38 -2
  142. package/dist/schemas/bundled/data-store.json +1 -1
  143. package/dist/schemas/bundled/manifest.json +4 -4
  144. package/dist/schemas/bundled/motivation.json +1 -1
  145. package/dist/schemas/bundled/navigation.json +1 -1
  146. package/dist/schemas/bundled/product.json +1 -1
  147. package/dist/schemas/bundled/security.json +1 -1
  148. package/dist/schemas/bundled/technology.json +1 -1
  149. package/dist/schemas/bundled/testing.json +1 -1
  150. package/dist/schemas/bundled/ux.json +1 -1
  151. package/dist/server/server.js +22 -3
  152. package/dist/server/server.js.map +2 -2
  153. package/dist/telemetry/config.js +2 -40
  154. package/dist/telemetry/config.js.map +2 -2
  155. package/dist/telemetry/index.js +1 -1
  156. package/dist/types/index.js.map +2 -2
  157. package/dist/utils/ansi-suppressor.js +25 -0
  158. package/dist/utils/ansi-suppressor.js.map +7 -0
  159. package/dist/utils/color-utils.js +34 -0
  160. package/dist/utils/color-utils.js.map +7 -0
  161. package/dist/utils/element-reference-shape.js +15 -1
  162. package/dist/utils/element-reference-shape.js.map +3 -3
  163. package/dist/utils/errors.js +69 -10
  164. package/dist/utils/errors.js.map +2 -2
  165. package/dist/utils/globals.js +17 -1
  166. package/dist/utils/globals.js.map +2 -2
  167. package/dist/utils/project-paths.js +24 -2
  168. package/dist/utils/project-paths.js.map +2 -2
  169. package/dist/utils/reference-path-parser.js +49 -0
  170. package/dist/utils/reference-path-parser.js.map +7 -0
  171. package/dist/utils/source-reference.js +5 -0
  172. package/dist/utils/source-reference.js.map +2 -2
  173. package/dist/utils/spec-version.js +10 -2
  174. package/dist/utils/spec-version.js.map +2 -2
  175. package/dist/validators/composed-reference-validator.js +262 -0
  176. package/dist/validators/composed-reference-validator.js.map +7 -0
  177. package/dist/validators/reference-validator.js +59 -8
  178. package/dist/validators/reference-validator.js.map +3 -3
  179. package/dist/validators/relationship-schema-validator.js +30 -2
  180. package/dist/validators/relationship-schema-validator.js.map +3 -3
  181. package/package.json +6 -3
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-add.ts"],
4
+ "sourcesContent": ["/**\n * model_add \u2014 add an element to a layer. Mirrors `dr add`, operating through\n * the shared MutationHandler so staging and base-model persistence stay\n * consistent with the CLI.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Element } from \"../../core/element.js\";\nimport { Layer } from \"../../core/layer.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { getNodeTypesForLayer, isValidNodeType, normalizeNodeType } from \"../../generated/node-types.js\";\nimport { generateElementId, generateUUID } from \"../../utils/id-generator.js\";\nimport { buildSourceReference, validateSourceReferenceOptions } from \"../../utils/source-reference.js\";\nimport { SchemaValidator } from \"../../validators/schema-validator.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n layer: z.string().describe(\"Canonical layer name (e.g. 'api', 'data-model').\"),\n type: z.string().describe(\"Element type within the layer (e.g. 'operation', 'entity').\"),\n name: z.string().describe(\"Human-readable element name; used to derive the element ID.\"),\n description: z.string().optional(),\n attributes: z.record(z.string(), z.unknown()).optional().describe(\"Type-specific attributes, validated against the element's spec schema.\"),\n sourceFile: z.string().optional().describe(\"Source file path relative to the repository root.\"),\n sourceSymbol: z.string().optional(),\n sourceProvenance: z.enum([\"extracted\", \"manual\", \"inferred\", \"generated\"]).optional(),\n sourceRepoRemote: z.string().optional(),\n sourceRepoCommit: z.string().optional().describe(\"Full 40-character Git commit SHA.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelAddArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelAddHandler(args: ModelAddArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (!isValidLayer(args.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(args.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (!isValidNodeType(args.layer, args.type)) {\n const validNodeTypes = getNodeTypesForLayer(args.layer);\n const typeNames = validNodeTypes.map((t) => t.type).sort();\n const similar = findSimilar(args.type, typeNames, 3);\n const suggestions: string[] = [`Valid types for ${args.layer}: ${formatValidOptions(typeNames)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Invalid element type \"${args.type}\" for layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n const resolvedType = normalizeNodeType(args.layer, args.type);\n const elementPath = generateElementId(args.layer, resolvedType, args.name);\n const elementUUID = generateUUID();\n\n const slugPart = elementPath.split(\".\")[2];\n if (!slugPart) {\n throw new CLIError(`Cannot generate a valid element ID from name \"${args.name}\"`, ErrorCategory.USER, [\n \"Element names must contain at least one letter or digit\",\n ]);\n }\n\n validateSourceReferenceOptions(args);\n\n const model = await loadModel(args.rootPath);\n\n let layerObj = await model.getLayer(args.layer);\n let isNewLayer = false;\n if (!layerObj) {\n layerObj = new Layer(args.layer);\n isNewLayer = true;\n }\n\n const now = new Date().toISOString();\n const element = new Element({\n id: elementUUID,\n path: elementPath,\n spec_node_id: `${args.layer}.${resolvedType}`,\n layer_id: args.layer,\n type: resolvedType,\n name: args.name,\n description: args.description,\n attributes: args.attributes ?? {},\n metadata: {\n created_at: now,\n updated_at: now,\n version: 1,\n },\n layer: args.layer,\n });\n\n const sourceRef = buildSourceReference(args);\n if (sourceRef) {\n element.setSourceReference(sourceRef);\n }\n\n {\n const schemaValidator = new SchemaValidator();\n const tempLayer = new Layer(args.layer);\n tempLayer.addElement(element);\n const attrValidation = await schemaValidator.validateLayer(tempLayer);\n if (!attrValidation.isValid()) {\n const errorMessages = attrValidation.errors.map((e) => ` ${e.message}`).join(\"\\n\");\n throw new CLIError(`Element ${elementPath} has invalid attributes:\\n${errorMessages}`, ErrorCategory.USER, [\n `Use \"model_info\" with layer \"${args.layer}\" and the spec resource for \"${args.type}\" to see the required attributes`,\n ]);\n }\n }\n\n if (layerObj.getElement(elementPath)) {\n throw new CLIError(`Element ${elementPath} already exists in ${args.layer} layer`, ErrorCategory.USER, [\n `Use \"model_show\" to view the existing element`,\n `Use \"model_update\" to modify it`,\n `Use \"model_delete\" to remove it first if you want to recreate it`,\n ]);\n }\n\n if (isNewLayer) {\n model.addLayer(layerObj);\n }\n\n const mutationHandler = new MutationHandler(model, elementPath, args.layer);\n await mutationHandler.executeAdd(element, (elem) => {\n layerObj!.addElement(elem);\n });\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n\n return jsonResult({\n status: staged ? \"staged\" : \"added\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: elementPath,\n layer: args.layer,\n type: resolvedType,\n name: args.name,\n });\n });\n}\n\nexport const modelAddTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_add\",\n description: \"Add a new element to a layer, validated against its spec schema.\",\n inputSchema,\n handler: modelAddHandler,\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,99 @@
1
+ import { z } from "zod";
2
+ import { DependencyTracker, TraceDirection } from "../../core/dependency-tracker.js";
3
+ import { MutationHandler } from "../../core/mutation-handler.js";
4
+ import { ReferenceRegistry } from "../../core/reference-registry.js";
5
+ import { findElementLayer } from "../../utils/element-utils.js";
6
+ import { CLIError, ErrorCategory, getErrorMessage } from "../../utils/errors.js";
7
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
8
+ const inputSchema = {
9
+ id: z.string().describe("Element ID or path to delete."),
10
+ cascade: z.boolean().optional().describe("Also delete elements that depend on this one."),
11
+ force: z.boolean().optional().describe("Skip the dependency check and delete only this element, even if others depend on it."),
12
+ dryRun: z.boolean().optional().describe("Preview what would be deleted without making changes."),
13
+ rootPath: rootPathSchema
14
+ };
15
+ async function modelDeleteHandler(args) {
16
+ return runTool(async () => {
17
+ const model = await loadModel(args.rootPath), layerName = await findElementLayer(model, args.id);
18
+ if (!layerName)
19
+ throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [
20
+ 'Use "model_search" to find similar elements'
21
+ ]);
22
+ const element = (await model.getLayer(layerName)).getElement(args.id);
23
+ if (!element)
24
+ throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [
25
+ 'Use "model_search" to find similar elements'
26
+ ]);
27
+ const registry = new ReferenceRegistry();
28
+ for (const l of model.layers.values())
29
+ for (const el of l.listElements())
30
+ registry.registerElement(el);
31
+ const dependents = new DependencyTracker(registry, model).traceDependencies(args.id, TraceDirection.DOWN, null);
32
+ if (dependents.length > 0 && !args.cascade && !args.force)
33
+ throw new CLIError("Element has dependencies", ErrorCategory.USER, [
34
+ "Use cascade=true to remove all dependent elements",
35
+ "Use dryRun=true with cascade=true to preview what would be deleted",
36
+ "Or use force=true to remove only this element (dependencies will reference a non-existent element)"
37
+ ]);
38
+ const elementsToRemove = args.cascade ? [args.id, ...dependents] : [args.id];
39
+ if (args.dryRun)
40
+ return jsonResult({
41
+ status: "dry-run",
42
+ id: args.id,
43
+ layer: layerName,
44
+ elementsToRemove
45
+ });
46
+ let deletedCount = 0;
47
+ const skippedDependents = [], cascadeDeleted = [];
48
+ if (args.cascade && dependents.length > 0)
49
+ for (const depId of [...dependents].reverse()) {
50
+ const depLayerName = await findElementLayer(model, depId);
51
+ if (!depLayerName) {
52
+ console.error(`[mcp] model_delete: cascade dependent "${depId}" not found, skipping`), skippedDependents.push(depId);
53
+ continue;
54
+ }
55
+ const depElement = (await model.getLayer(depLayerName)).getElement(depId);
56
+ if (!depElement) {
57
+ console.error(`[mcp] model_delete: cascade dependent "${depId}" not found, skipping`), skippedDependents.push(depId);
58
+ continue;
59
+ }
60
+ const depHandler = new MutationHandler(model, depId, depLayerName);
61
+ try {
62
+ await depHandler.executeDelete(depElement);
63
+ } catch (error) {
64
+ throw new CLIError(`Failed to delete dependent element "${depId}": ${getErrorMessage(error)}`, ErrorCategory.SYSTEM, [
65
+ `${cascadeDeleted.length} dependent element(s) were deleted before the error`,
66
+ 'Use "model_validate" to check the model for broken references',
67
+ `"${args.id}" was not deleted \u2014 you can retry the operation once dependents are resolved`
68
+ ], {
69
+ operation: "model_delete (cascade)",
70
+ relatedElements: cascadeDeleted,
71
+ partialProgress: { completed: cascadeDeleted.length, total: dependents.length }
72
+ });
73
+ }
74
+ cascadeDeleted.push(depId), deletedCount++;
75
+ }
76
+ const mutationHandler = new MutationHandler(model, args.id, layerName);
77
+ await mutationHandler.executeDelete(element);
78
+ const activeChangeset = await mutationHandler.getStagingManager().getActive(), staged = !!(activeChangeset && activeChangeset.status === "staged");
79
+ return jsonResult({
80
+ status: staged ? "staged" : "deleted",
81
+ changeset: staged ? activeChangeset.name : void 0,
82
+ id: args.id,
83
+ layer: layerName,
84
+ cascadedDeletes: deletedCount,
85
+ ...skippedDependents.length > 0 ? { skippedDependents } : {}
86
+ });
87
+ });
88
+ }
89
+ const modelDeleteTool = {
90
+ name: "model_delete",
91
+ description: "Delete an element, optionally cascading to elements that depend on it.",
92
+ inputSchema,
93
+ handler: modelDeleteHandler
94
+ };
95
+ export {
96
+ modelDeleteHandler,
97
+ modelDeleteTool
98
+ };
99
+ //# sourceMappingURL=model-delete.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-delete.ts"],
4
+ "sourcesContent": ["/**\n * model_delete \u2014 delete an element (optionally cascading to dependents).\n * Mirrors `dr delete`, but since an MCP session has no interactive confirmation\n * channel, the caller must pass `force` or `cascade` explicitly when dependents\n * exist rather than being prompted; operates through the shared MutationHandler.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { DependencyTracker, TraceDirection } from \"../../core/dependency-tracker.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { ReferenceRegistry } from \"../../core/reference-registry.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { CLIError, ErrorCategory, getErrorMessage } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path to delete.\"),\n cascade: z.boolean().optional().describe(\"Also delete elements that depend on this one.\"),\n force: z.boolean().optional().describe(\"Skip the dependency check and delete only this element, even if others depend on it.\"),\n dryRun: z.boolean().optional().describe(\"Preview what would be deleted without making changes.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelDeleteArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelDeleteHandler(args: ModelDeleteArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n const layer = (await model.getLayer(layerName))!;\n const element = layer.getElement(args.id);\n if (!element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n // Cascade is scoped to cross-layer references only, matching `dr delete`. This is\n // narrower than \"model_trace\", which also follows intra-layer relationships.yaml\n // edges \u2014 a dependent found by model_trace may not be included in a cascade delete.\n const registry = new ReferenceRegistry();\n for (const l of model.layers.values()) {\n for (const el of l.listElements()) {\n registry.registerElement(el);\n }\n }\n const tracker = new DependencyTracker(registry, model);\n const dependents = tracker.traceDependencies(args.id, TraceDirection.DOWN, null);\n\n if (dependents.length > 0 && !args.cascade && !args.force) {\n throw new CLIError(\"Element has dependencies\", ErrorCategory.USER, [\n \"Use cascade=true to remove all dependent elements\",\n \"Use dryRun=true with cascade=true to preview what would be deleted\",\n \"Or use force=true to remove only this element (dependencies will reference a non-existent element)\",\n ]);\n }\n\n const elementsToRemove = args.cascade ? [args.id, ...dependents] : [args.id];\n\n if (args.dryRun) {\n return jsonResult({\n status: \"dry-run\",\n id: args.id,\n layer: layerName,\n elementsToRemove,\n });\n }\n\n let deletedCount = 0;\n const skippedDependents: string[] = [];\n const cascadeDeleted: string[] = [];\n if (args.cascade && dependents.length > 0) {\n for (const depId of [...dependents].reverse()) {\n const depLayerName = await findElementLayer(model, depId);\n if (!depLayerName) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depLayer = (await model.getLayer(depLayerName))!;\n const depElement = depLayer.getElement(depId);\n if (!depElement) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depHandler = new MutationHandler(model, depId, depLayerName);\n try {\n await depHandler.executeDelete(depElement);\n } catch (error) {\n throw new CLIError(\n `Failed to delete dependent element \"${depId}\": ${getErrorMessage(error)}`,\n ErrorCategory.SYSTEM,\n [\n `${cascadeDeleted.length} dependent element(s) were deleted before the error`,\n 'Use \"model_validate\" to check the model for broken references',\n `\"${args.id}\" was not deleted \u2014 you can retry the operation once dependents are resolved`,\n ],\n {\n operation: \"model_delete (cascade)\",\n relatedElements: cascadeDeleted,\n partialProgress: { completed: cascadeDeleted.length, total: dependents.length },\n }\n );\n }\n cascadeDeleted.push(depId);\n deletedCount++;\n }\n }\n\n const mutationHandler = new MutationHandler(model, args.id, layerName);\n await mutationHandler.executeDelete(element);\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n\n return jsonResult({\n status: staged ? \"staged\" : \"deleted\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: args.id,\n layer: layerName,\n cascadedDeletes: deletedCount,\n ...(skippedDependents.length > 0 ? { skippedDependents } : {}),\n });\n });\n}\n\nexport const modelDeleteTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_delete\",\n description: \"Delete an element, optionally cascading to elements that depend on it.\",\n inputSchema,\n handler: modelDeleteHandler,\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ import { ArchiMateExporter, ExportManager, GraphMLExporter, JsonSchemaExporter, MarkdownExporter, MermaidMarkdownExporter, OpenAPIExporter, PlantUMLExporter } from "../../export/index.js";
3
+ import { Validator } from "../../validators/validator.js";
4
+ import { CLIError, ErrorCategory } from "../../utils/errors.js";
5
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
6
+ const inputSchema = {
7
+ format: z.string().describe("Export format: archimate, openapi, json-schema, plantuml, graphml, markdown, or mermaid-markdown."),
8
+ layers: z.array(z.string()).optional().describe("Restrict export to these layers (must be supported by the chosen format)."),
9
+ includeSources: z.boolean().optional().describe("Include source_reference provenance in the export, where supported."),
10
+ rootPath: rootPathSchema
11
+ };
12
+ function buildExportManager() {
13
+ const manager = new ExportManager();
14
+ return manager.register("archimate", new ArchiMateExporter(), {
15
+ description: "ArchiMate 3.2 XML format",
16
+ mimeType: "application/xml"
17
+ }), manager.register("openapi", new OpenAPIExporter(), {
18
+ description: "OpenAPI 3.0 specification",
19
+ mimeType: "application/json"
20
+ }), manager.register("json-schema", new JsonSchemaExporter(), {
21
+ description: "JSON Schema Draft 7",
22
+ mimeType: "application/json"
23
+ }), manager.register("jsonschema", new JsonSchemaExporter(), {
24
+ description: "JSON Schema Draft 7",
25
+ mimeType: "application/json"
26
+ }), manager.register("plantuml", new PlantUMLExporter(), {
27
+ description: "PlantUML diagram format",
28
+ mimeType: "text/plain"
29
+ }), manager.register("graphml", new GraphMLExporter(), {
30
+ description: "GraphML graph format",
31
+ mimeType: "application/xml"
32
+ }), manager.register("markdown", new MarkdownExporter(), {
33
+ description: "Markdown documentation",
34
+ mimeType: "text/markdown"
35
+ }), manager.register("mermaid-markdown", new MermaidMarkdownExporter(), {
36
+ description: "Markdown with Mermaid diagrams and formatted tables",
37
+ mimeType: "text/markdown"
38
+ }), manager;
39
+ }
40
+ const SEMANTIC_FORMATS = /* @__PURE__ */ new Set(["openapi", "archimate", "jsonschema", "json-schema"]);
41
+ async function modelExportHandler(args) {
42
+ return runTool(async () => {
43
+ const model = await loadModel(args.rootPath), manager = buildExportManager(), format = args.format.toLowerCase();
44
+ if (!manager.hasFormat(format)) {
45
+ const available = manager.getAllFormats().map((f) => f.format);
46
+ throw new CLIError(`Unknown export format: ${args.format}`, ErrorCategory.USER, [
47
+ `Available formats: ${available.join(", ")}`
48
+ ]);
49
+ }
50
+ const warnings = [];
51
+ if (SEMANTIC_FORMATS.has(format)) {
52
+ const validationResult = await new Validator().validateModel(model);
53
+ validationResult.isValid() || warnings.push(`Model has ${validationResult.errors.length} validation error(s). Export output may be incomplete or incorrect.`);
54
+ }
55
+ const content = await manager.export(model, format, {
56
+ layers: args.layers,
57
+ includeSources: args.includeSources
58
+ });
59
+ return jsonResult({ format, warnings, content });
60
+ });
61
+ }
62
+ const modelExportTool = {
63
+ name: "model_export",
64
+ description: "Export the architecture model to ArchiMate, OpenAPI, JSON Schema, PlantUML, GraphML, Markdown, or Markdown with Mermaid diagrams.",
65
+ inputSchema,
66
+ handler: modelExportHandler
67
+ };
68
+ export {
69
+ modelExportHandler,
70
+ modelExportTool
71
+ };
72
+ //# sourceMappingURL=model-export.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-export.ts"],
4
+ "sourcesContent": ["/**\n * model_export \u2014 export the model to a documentation/interchange format.\n * Mirrors `dr export`, reusing the shared ExportManager and exporters.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n ArchiMateExporter,\n ExportManager,\n GraphMLExporter,\n JsonSchemaExporter,\n MarkdownExporter,\n MermaidMarkdownExporter,\n OpenAPIExporter,\n PlantUMLExporter,\n} from \"../../export/index.js\";\nimport { Validator } from \"../../validators/validator.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n format: z\n .string()\n .describe(\"Export format: archimate, openapi, json-schema, plantuml, graphml, markdown, or mermaid-markdown.\"),\n layers: z.array(z.string()).optional().describe(\"Restrict export to these layers (must be supported by the chosen format).\"),\n includeSources: z.boolean().optional().describe(\"Include source_reference provenance in the export, where supported.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelExportArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nfunction buildExportManager(): ExportManager {\n const manager = new ExportManager();\n manager.register(\"archimate\", new ArchiMateExporter(), {\n description: \"ArchiMate 3.2 XML format\",\n mimeType: \"application/xml\",\n });\n manager.register(\"openapi\", new OpenAPIExporter(), {\n description: \"OpenAPI 3.0 specification\",\n mimeType: \"application/json\",\n });\n manager.register(\"json-schema\", new JsonSchemaExporter(), {\n description: \"JSON Schema Draft 7\",\n mimeType: \"application/json\",\n });\n manager.register(\"jsonschema\", new JsonSchemaExporter(), {\n description: \"JSON Schema Draft 7\",\n mimeType: \"application/json\",\n });\n manager.register(\"plantuml\", new PlantUMLExporter(), {\n description: \"PlantUML diagram format\",\n mimeType: \"text/plain\",\n });\n manager.register(\"graphml\", new GraphMLExporter(), {\n description: \"GraphML graph format\",\n mimeType: \"application/xml\",\n });\n manager.register(\"markdown\", new MarkdownExporter(), {\n description: \"Markdown documentation\",\n mimeType: \"text/markdown\",\n });\n manager.register(\"mermaid-markdown\", new MermaidMarkdownExporter(), {\n description: \"Markdown with Mermaid diagrams and formatted tables\",\n mimeType: \"text/markdown\",\n });\n return manager;\n}\n\nconst SEMANTIC_FORMATS = new Set([\"openapi\", \"archimate\", \"jsonschema\", \"json-schema\"]);\n\nexport async function modelExportHandler(args: ModelExportArgs): Promise<CallToolResult> {\n return runTool(async () => {\n // Unlike \"model_validate\", this exports the base model as-is and does not project\n // the active changeset onto it \u2014 matching `dr export`. A staged-but-uncommitted\n // change will not appear in the export output.\n const model = await loadModel(args.rootPath);\n const manager = buildExportManager();\n const format = args.format.toLowerCase();\n\n if (!manager.hasFormat(format)) {\n const available = manager.getAllFormats().map((f) => f.format);\n throw new CLIError(`Unknown export format: ${args.format}`, ErrorCategory.USER, [\n `Available formats: ${available.join(\", \")}`,\n ]);\n }\n\n const warnings: string[] = [];\n if (SEMANTIC_FORMATS.has(format)) {\n const validator = new Validator();\n const validationResult = await validator.validateModel(model);\n if (!validationResult.isValid()) {\n warnings.push(\n `Model has ${validationResult.errors.length} validation error(s). Export output may be incomplete or incorrect.`\n );\n }\n }\n\n const content = await manager.export(model, format, {\n layers: args.layers,\n includeSources: args.includeSources,\n });\n\n return jsonResult({ format, warnings, content });\n });\n}\n\nexport const modelExportTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_export\",\n description:\n \"Export the architecture model to ArchiMate, OpenAPI, JSON Schema, PlantUML, GraphML, Markdown, or Markdown with Mermaid diagrams.\",\n inputSchema,\n handler: modelExportHandler,\n};\n"],
5
+ "mappings": "AAKA,SAAS,SAAS;AAElB,SACE,mBACA,eACA,iBACA,oBACA,kBACA,yBACA,iBACA,wBACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,QAAQ,EACL,OAAM,EACN,SAAS,mGAAmG;EAC/G,QAAQ,EAAE,MAAM,EAAE,OAAM,CAAE,EAAE,SAAQ,EAAG,SAAS,2EAA2E;EAC3H,gBAAgB,EAAE,QAAO,EAAG,SAAQ,EAAG,SAAS,qEAAqE;EACrH,UAAU;;AAKZ,SAAS,qBAAkB;AACzB,QAAM,UAAU,IAAI,cAAa;AACjC,iBAAQ,SAAS,aAAa,IAAI,kBAAiB,GAAI;IACrD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,WAAW,IAAI,gBAAe,GAAI;IACjD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,eAAe,IAAI,mBAAkB,GAAI;IACxD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,cAAc,IAAI,mBAAkB,GAAI;IACvD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,YAAY,IAAI,iBAAgB,GAAI;IACnD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,WAAW,IAAI,gBAAe,GAAI;IACjD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,YAAY,IAAI,iBAAgB,GAAI;IACnD,aAAa;IACb,UAAU;GACX,GACD,QAAQ,SAAS,oBAAoB,IAAI,wBAAuB,GAAI;IAClE,aAAa;IACb,UAAU;GACX,GACM;AACT;AAEA,MAAM,mBAAmB,oBAAI,IAAI,CAAC,WAAW,aAAa,cAAc,aAAa,CAAC;AAEtF,eAAsB,mBAAmB,MAAqB;AAC5D,SAAO,QAAQ,YAAW;AAIxB,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GACrC,UAAU,mBAAkB,GAC5B,SAAS,KAAK,OAAO,YAAW;AAEtC,QAAI,CAAC,QAAQ,UAAU,MAAM,GAAG;AAC9B,YAAM,YAAY,QAAQ,cAAa,EAAG,IAAI,CAAC,MAAM,EAAE,MAAM;AAC7D,YAAM,IAAI,SAAS,0BAA0B,KAAK,MAAM,IAAI,cAAc,MAAM;QAC9E,sBAAsB,UAAU,KAAK,IAAI,CAAC;OAC3C;IACH;AAEA,UAAM,WAAqB,CAAA;AAC3B,QAAI,iBAAiB,IAAI,MAAM,GAAG;AAEhC,YAAM,mBAAmB,MADP,IAAI,UAAS,EACU,cAAc,KAAK;AAC5D,MAAK,iBAAiB,QAAO,KAC3B,SAAS,KACP,aAAa,iBAAiB,OAAO,MAAM,qEAAqE;IAGtH;AAEA,UAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,QAAQ;MAClD,QAAQ,KAAK;MACb,gBAAgB,KAAK;KACtB;AAED,WAAO,WAAW,EAAE,QAAQ,UAAU,QAAO,CAAE;EACjD,CAAC;AACH;AAEO,MAAM,kBAAyD;EACpE,MAAM;EACN,aACE;EACF;EACA,SAAS;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ import { CLIError, ErrorCategory } from "../../utils/errors.js";
3
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
4
+ const inputSchema = {
5
+ layer: z.string().optional().describe("Show details for a single layer instead of the whole-model summary."),
6
+ rootPath: rootPathSchema
7
+ };
8
+ async function modelInfoHandler(args) {
9
+ return runTool(async () => {
10
+ const model = await loadModel(args.rootPath), manifest = model.manifest, modelSummary = {
11
+ name: manifest.name,
12
+ version: manifest.version,
13
+ specVersion: manifest.specVersion,
14
+ description: manifest.description,
15
+ author: manifest.author,
16
+ created: manifest.created,
17
+ modified: manifest.modified
18
+ };
19
+ if (args.layer) {
20
+ const layer = await model.getLayer(args.layer);
21
+ if (!layer)
22
+ throw new CLIError(`Layer ${args.layer} not found`, ErrorCategory.NOT_FOUND, [
23
+ 'Use "model_info" (without a layer) to see all available layers'
24
+ ]);
25
+ const elements = layer.listElements(), elementsByType = {};
26
+ for (const element of elements)
27
+ elementsByType[element.type] = (elementsByType[element.type] || 0) + 1;
28
+ return jsonResult({
29
+ model: modelSummary,
30
+ layer: { name: args.layer, elementCount: elements.length, elementsByType }
31
+ });
32
+ }
33
+ const layerNames = model.getLayerNames(), layers = [];
34
+ for (const layerName of layerNames) {
35
+ const layer = await model.getLayer(layerName);
36
+ layer && layers.push({ name: layerName, elementCount: layer.listElements().length });
37
+ }
38
+ return jsonResult({ model: modelSummary, layers });
39
+ });
40
+ }
41
+ const modelInfoTool = {
42
+ name: "model_info",
43
+ description: "Get model metadata and a summary of layers (or a single layer's element type breakdown).",
44
+ inputSchema,
45
+ handler: modelInfoHandler
46
+ };
47
+ export {
48
+ modelInfoHandler,
49
+ modelInfoTool
50
+ };
51
+ //# sourceMappingURL=model-info.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-info.ts"],
4
+ "sourcesContent": ["/**\n * model_info \u2014 model or single-layer summary information. Mirrors `dr info`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n layer: z.string().optional().describe(\"Show details for a single layer instead of the whole-model summary.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelInfoArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelInfoHandler(args: ModelInfoArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n const manifest = model.manifest;\n\n const modelSummary = {\n name: manifest.name,\n version: manifest.version,\n specVersion: manifest.specVersion,\n description: manifest.description,\n author: manifest.author,\n created: manifest.created,\n modified: manifest.modified,\n };\n\n if (args.layer) {\n const layer = await model.getLayer(args.layer);\n if (!layer) {\n throw new CLIError(`Layer ${args.layer} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_info\" (without a layer) to see all available layers',\n ]);\n }\n\n const elements = layer.listElements();\n const elementsByType: Record<string, number> = {};\n for (const element of elements) {\n elementsByType[element.type] = (elementsByType[element.type] || 0) + 1;\n }\n\n return jsonResult({\n model: modelSummary,\n layer: { name: args.layer, elementCount: elements.length, elementsByType },\n });\n }\n\n const layerNames = model.getLayerNames();\n const layers: Array<{ name: string; elementCount: number }> = [];\n for (const layerName of layerNames) {\n const layer = await model.getLayer(layerName);\n if (!layer) continue;\n layers.push({ name: layerName, elementCount: layer.listElements().length });\n }\n\n return jsonResult({ model: modelSummary, layers });\n });\n}\n\nexport const modelInfoTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_info\",\n description: \"Get model metadata and a summary of layers (or a single layer's element type breakdown).\",\n inputSchema,\n handler: modelInfoHandler,\n};\n"],
5
+ "mappings": "AAIA,SAAS,SAAS;AAElB,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,OAAO,EAAE,OAAM,EAAG,SAAQ,EAAG,SAAS,qEAAqE;EAC3G,UAAU;;AAKZ,eAAsB,iBAAiB,MAAmB;AACxD,SAAO,QAAQ,YAAW;AACxB,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GACrC,WAAW,MAAM,UAEjB,eAAe;MACnB,MAAM,SAAS;MACf,SAAS,SAAS;MAClB,aAAa,SAAS;MACtB,aAAa,SAAS;MACtB,QAAQ,SAAS;MACjB,SAAS,SAAS;MAClB,UAAU,SAAS;;AAGrB,QAAI,KAAK,OAAO;AACd,YAAM,QAAQ,MAAM,MAAM,SAAS,KAAK,KAAK;AAC7C,UAAI,CAAC;AACH,cAAM,IAAI,SAAS,SAAS,KAAK,KAAK,cAAc,cAAc,WAAW;UAC3E;SACD;AAGH,YAAM,WAAW,MAAM,aAAY,GAC7B,iBAAyC,CAAA;AAC/C,iBAAW,WAAW;AACpB,uBAAe,QAAQ,IAAI,KAAK,eAAe,QAAQ,IAAI,KAAK,KAAK;AAGvE,aAAO,WAAW;QAChB,OAAO;QACP,OAAO,EAAE,MAAM,KAAK,OAAO,cAAc,SAAS,QAAQ,eAAc;OACzE;IACH;AAEA,UAAM,aAAa,MAAM,cAAa,GAChC,SAAwD,CAAA;AAC9D,eAAW,aAAa,YAAY;AAClC,YAAM,QAAQ,MAAM,MAAM,SAAS,SAAS;AAC5C,MAAK,SACL,OAAO,KAAK,EAAE,MAAM,WAAW,cAAc,MAAM,aAAY,EAAG,OAAM,CAAE;IAC5E;AAEA,WAAO,WAAW,EAAE,OAAO,cAAc,OAAM,CAAE;EACnD,CAAC;AACH;AAEO,MAAM,gBAAuD;EAClE,MAAM;EACN,aAAa;EACb;EACA,SAAS;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ import { CANONICAL_LAYER_NAMES } from "../../core/layers.js";
3
+ import { CLIError, ErrorCategory } from "../../utils/errors.js";
4
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
5
+ const inputSchema = {
6
+ layer: z.string().optional().describe("Canonical layer name to list (e.g. 'api', 'data-model'). Omit to list across all layers."),
7
+ type: z.string().optional().describe("Restrict results to a single element type."),
8
+ rootPath: rootPathSchema
9
+ };
10
+ async function modelListHandler(args) {
11
+ return runTool(async () => {
12
+ if (args.layer) {
13
+ const layer = await (await loadModel(args.rootPath)).getLayer(args.layer);
14
+ if (!layer)
15
+ throw new CLIError(`Layer ${args.layer} not found`, ErrorCategory.NOT_FOUND, [
16
+ 'Use "model_info" to see all available layers'
17
+ ]);
18
+ let elements = layer.listElements();
19
+ return args.type && (elements = elements.filter((e) => e.type === args.type)), jsonResult({
20
+ layer: args.layer,
21
+ count: elements.length,
22
+ elements: elements.map((e) => e.toJSON())
23
+ });
24
+ }
25
+ const model = await loadModel(args.rootPath), layers = [];
26
+ for (const layerName of CANONICAL_LAYER_NAMES) {
27
+ const layer = await model.getLayer(layerName);
28
+ if (!layer)
29
+ continue;
30
+ let elements = layer.listElements();
31
+ args.type && (elements = elements.filter((e) => e.type === args.type)), elements.length > 0 && layers.push({
32
+ layer: layerName,
33
+ count: elements.length,
34
+ elements: elements.map((e) => e.toJSON())
35
+ });
36
+ }
37
+ return jsonResult({
38
+ layers,
39
+ totalElements: layers.reduce((sum, l) => sum + l.count, 0)
40
+ });
41
+ });
42
+ }
43
+ const modelListTool = {
44
+ name: "model_list",
45
+ description: "List elements in the architecture model, optionally scoped to a layer and/or element type.",
46
+ inputSchema,
47
+ handler: modelListHandler
48
+ };
49
+ export {
50
+ modelListHandler,
51
+ modelListTool
52
+ };
53
+ //# sourceMappingURL=model-list.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-list.ts"],
4
+ "sourcesContent": ["/**\n * model_list \u2014 list elements in the architecture model, optionally scoped to\n * a single layer and/or element type. Mirrors `dr list`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { CANONICAL_LAYER_NAMES } from \"../../core/layers.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n layer: z\n .string()\n .optional()\n .describe(\"Canonical layer name to list (e.g. 'api', 'data-model'). Omit to list across all layers.\"),\n type: z.string().optional().describe(\"Restrict results to a single element type.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelListArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelListHandler(args: ModelListArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (args.layer) {\n const model = await loadModel(args.rootPath);\n const layer = await model.getLayer(args.layer);\n if (!layer) {\n throw new CLIError(`Layer ${args.layer} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_info\" to see all available layers',\n ]);\n }\n\n let elements = layer.listElements();\n if (args.type) {\n elements = elements.filter((e) => e.type === args.type);\n }\n\n return jsonResult({\n layer: args.layer,\n count: elements.length,\n elements: elements.map((e) => e.toJSON()),\n });\n }\n\n const model = await loadModel(args.rootPath);\n const layers: Array<{ layer: string; count: number; elements: unknown[] }> = [];\n\n for (const layerName of CANONICAL_LAYER_NAMES) {\n const layer = await model.getLayer(layerName);\n if (!layer) continue;\n\n let elements = layer.listElements();\n if (args.type) {\n elements = elements.filter((e) => e.type === args.type);\n }\n\n if (elements.length > 0) {\n layers.push({\n layer: layerName,\n count: elements.length,\n elements: elements.map((e) => e.toJSON()),\n });\n }\n }\n\n return jsonResult({\n layers,\n totalElements: layers.reduce((sum, l) => sum + l.count, 0),\n });\n });\n}\n\nexport const modelListTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_list\",\n description:\n \"List elements in the architecture model, optionally scoped to a layer and/or element type.\",\n inputSchema,\n handler: modelListHandler,\n};\n"],
5
+ "mappings": "AAKA,SAAS,SAAS;AAElB,SAAS,6BAA6B;AACtC,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,OAAO,EACJ,OAAM,EACN,SAAQ,EACR,SAAS,0FAA0F;EACtG,MAAM,EAAE,OAAM,EAAG,SAAQ,EAAG,SAAS,4CAA4C;EACjF,UAAU;;AAKZ,eAAsB,iBAAiB,MAAmB;AACxD,SAAO,QAAQ,YAAW;AACxB,QAAI,KAAK,OAAO;AAEd,YAAM,QAAQ,OADA,MAAM,UAAU,KAAK,QAAQ,GACjB,SAAS,KAAK,KAAK;AAC7C,UAAI,CAAC;AACH,cAAM,IAAI,SAAS,SAAS,KAAK,KAAK,cAAc,cAAc,WAAW;UAC3E;SACD;AAGH,UAAI,WAAW,MAAM,aAAY;AACjC,aAAI,KAAK,SACP,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,IAGjD,WAAW;QAChB,OAAO,KAAK;QACZ,OAAO,SAAS;QAChB,UAAU,SAAS,IAAI,CAAC,MAAM,EAAE,OAAM,CAAE;OACzC;IACH;AAEA,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GACrC,SAAuE,CAAA;AAE7E,eAAW,aAAa,uBAAuB;AAC7C,YAAM,QAAQ,MAAM,MAAM,SAAS,SAAS;AAC5C,UAAI,CAAC;AAAO;AAEZ,UAAI,WAAW,MAAM,aAAY;AACjC,MAAI,KAAK,SACP,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,IAGpD,SAAS,SAAS,KACpB,OAAO,KAAK;QACV,OAAO;QACP,OAAO,SAAS;QAChB,UAAU,SAAS,IAAI,CAAC,MAAM,EAAE,OAAM,CAAE;OACzC;IAEL;AAEA,WAAO,WAAW;MAChB;MACA,eAAe,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;KAC1D;EACH,CAAC;AACH;AAEO,MAAM,gBAAuD;EAClE,MAAM;EACN,aACE;EACF;EACA,SAAS;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,34 @@
1
+ import { jsonResult, reloadModel, rootPathSchema, runTool } from "./shared.js";
2
+ const inputSchema = {
3
+ rootPath: rootPathSchema
4
+ };
5
+ async function modelReloadHandler(args) {
6
+ return runTool(async () => {
7
+ const model = await reloadModel(args.rootPath), layers = [];
8
+ for (const layerName of model.getLayerNames()) {
9
+ const layer = await model.getLayer(layerName);
10
+ layer && layers.push({ name: layerName, elementCount: layer.listElements().length });
11
+ }
12
+ return jsonResult({
13
+ status: "reloaded",
14
+ model: {
15
+ name: model.manifest.name,
16
+ version: model.manifest.version,
17
+ modified: model.manifest.modified
18
+ },
19
+ layers,
20
+ totalElements: layers.reduce((sum, layer) => sum + layer.elementCount, 0)
21
+ });
22
+ });
23
+ }
24
+ const modelReloadTool = {
25
+ name: "model_reload",
26
+ description: "Force a full reload of the architecture model from disk and report a summary of its current state.",
27
+ inputSchema,
28
+ handler: modelReloadHandler
29
+ };
30
+ export {
31
+ modelReloadHandler,
32
+ modelReloadTool
33
+ };
34
+ //# sourceMappingURL=model-reload.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-reload.ts"],
4
+ "sourcesContent": ["/**\n * model_reload \u2014 force a full, non-lazy reload of the architecture model from\n * disk and report a summary of what was read.\n *\n * `loadModel()` (shared.ts) loads the model once per rootPath and holds it in\n * memory for reuse across tool calls, the same way the REST/visualization server\n * holds a long-lived `this.model` field (see `setupFileWatcher()` in\n * `cli/src/server/server.ts`). That cache can go stale after edits made outside\n * this MCP session (e.g. the CLI or another process editing files on disk), so\n * this tool exists to force a fresh read and refresh the cache \u2014 the MCP\n * equivalent of that server's file-watcher-triggered reload.\n */\n\nimport type { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { jsonResult, reloadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n rootPath: rootPathSchema,\n};\n\nexport type ModelReloadArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelReloadHandler(args: ModelReloadArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await reloadModel(args.rootPath);\n\n const layers: Array<{ name: string; elementCount: number }> = [];\n for (const layerName of model.getLayerNames()) {\n const layer = await model.getLayer(layerName);\n if (!layer) continue;\n layers.push({ name: layerName, elementCount: layer.listElements().length });\n }\n\n return jsonResult({\n status: \"reloaded\",\n model: {\n name: model.manifest.name,\n version: model.manifest.version,\n modified: model.manifest.modified,\n },\n layers,\n totalElements: layers.reduce((sum, layer) => sum + layer.elementCount, 0),\n });\n });\n}\n\nexport const modelReloadTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_reload\",\n description: \"Force a full reload of the architecture model from disk and report a summary of its current state.\",\n inputSchema,\n handler: modelReloadHandler,\n};\n"],
5
+ "mappings": "AAeA,SAAS,YAAY,aAAa,gBAAgB,eAAuC;AAEzF,MAAM,cAAc;EAClB,UAAU;;AAKZ,eAAsB,mBAAmB,MAAqB;AAC5D,SAAO,QAAQ,YAAW;AACxB,UAAM,QAAQ,MAAM,YAAY,KAAK,QAAQ,GAEvC,SAAwD,CAAA;AAC9D,eAAW,aAAa,MAAM,cAAa,GAAI;AAC7C,YAAM,QAAQ,MAAM,MAAM,SAAS,SAAS;AAC5C,MAAK,SACL,OAAO,KAAK,EAAE,MAAM,WAAW,cAAc,MAAM,aAAY,EAAG,OAAM,CAAE;IAC5E;AAEA,WAAO,WAAW;MAChB,QAAQ;MACR,OAAO;QACL,MAAM,MAAM,SAAS;QACrB,SAAS,MAAM,SAAS;QACxB,UAAU,MAAM,SAAS;;MAE3B;MACA,eAAe,OAAO,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,cAAc,CAAC;KACzE;EACH,CAAC;AACH;AAEO,MAAM,kBAAyD;EACpE,MAAM;EACN,aAAa;EACb;EACA,SAAS;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { getAllLayerIds, isValidLayer } from "../../generated/layer-registry.js";
3
+ import { NODE_TYPES } from "../../generated/node-types.js";
4
+ import { CLIError, ErrorCategory, findSimilar, formatValidOptions } from "../../utils/errors.js";
5
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
6
+ const inputSchema = {
7
+ query: z.string().optional().describe("Text to match against element ID and name (case-insensitive substring). Ignored when sourceFile is set."),
8
+ layer: z.string().optional().describe("Restrict search to a single layer."),
9
+ type: z.string().optional().describe("Restrict search to a single element type."),
10
+ sourceFile: z.string().optional().describe("Find elements whose source_reference points at this file path."),
11
+ rootPath: rootPathSchema
12
+ };
13
+ function normalizePath(filePath) {
14
+ return filePath.replace(/^\.\//, "").replace(/\\/g, "/");
15
+ }
16
+ function matchesSourceFile(element, sourceFilePath) {
17
+ const sourceRef = element.getSourceReference();
18
+ if (!sourceRef)
19
+ return !1;
20
+ const normalizedQuery = normalizePath(sourceFilePath);
21
+ return (sourceRef.locations ?? []).some((loc) => normalizePath(loc.file) === normalizedQuery);
22
+ }
23
+ async function modelSearchHandler(args) {
24
+ return runTool(async () => {
25
+ if (!args.query && !args.sourceFile && !args.layer && !args.type)
26
+ throw new CLIError("At least one of query, sourceFile, layer, or type must be provided", ErrorCategory.USER, ['Use "model_list" to list all elements without filtering']);
27
+ if (args.layer && !isValidLayer(args.layer)) {
28
+ const validLayers = getAllLayerIds(), similar = findSimilar(args.layer, validLayers, 3), suggestions = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];
29
+ throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Unknown layer "${args.layer}"`, ErrorCategory.USER, suggestions);
30
+ }
31
+ if (args.type) {
32
+ const candidateTypes = args.layer ? Array.from(NODE_TYPES.values()).filter((t) => t.layer === args.layer) : Array.from(NODE_TYPES.values());
33
+ if (!candidateTypes.some((t) => t.type === args.type)) {
34
+ const validTypeNames = Array.from(new Set(candidateTypes.map((t) => t.type))).sort(), similar = findSimilar(args.type, validTypeNames, 3), suggestions = [
35
+ args.layer ? `Valid types for ${args.layer}: ${formatValidOptions(validTypeNames)}` : `Valid types: ${formatValidOptions(validTypeNames)}`
36
+ ];
37
+ throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Unknown element type "${args.type}"${args.layer ? ` for layer "${args.layer}"` : ""}`, ErrorCategory.USER, suggestions);
38
+ }
39
+ }
40
+ const model = await loadModel(args.rootPath), isSourceFileSearch = !!args.sourceFile, queryLower = (args.query ?? "").toLowerCase(), results = [];
41
+ for (const layerName of model.getLayerNames()) {
42
+ if (args.layer && layerName !== args.layer)
43
+ continue;
44
+ const layerObj = await model.getLayer(layerName);
45
+ if (layerObj)
46
+ for (const element of layerObj.listElements()) {
47
+ if (args.type && element.type !== args.type)
48
+ continue;
49
+ if (isSourceFileSearch) {
50
+ if (!matchesSourceFile(element, args.sourceFile))
51
+ continue;
52
+ } else {
53
+ const idMatch = (element.path || element.id).toLowerCase().includes(queryLower), nameMatch = element.name.toLowerCase().includes(queryLower);
54
+ if (!idMatch && !nameMatch)
55
+ continue;
56
+ }
57
+ let sourceFile, sourceSymbol;
58
+ const sourceRef = element.getSourceReference();
59
+ sourceRef?.locations && sourceRef.locations.length > 0 && (sourceFile = sourceRef.locations[0].file, sourceSymbol = sourceRef.locations[0].symbol), results.push({
60
+ layer: layerName,
61
+ id: element.path || element.id,
62
+ type: element.type,
63
+ name: element.name,
64
+ description: element.description,
65
+ sourceFile,
66
+ sourceSymbol
67
+ });
68
+ }
69
+ }
70
+ return jsonResult({
71
+ query: args.query ?? "",
72
+ sourceFile: args.sourceFile,
73
+ count: results.length,
74
+ results
75
+ });
76
+ });
77
+ }
78
+ const modelSearchTool = {
79
+ name: "model_search",
80
+ description: "Search for elements across the model by name/ID substring or by source file reference.",
81
+ inputSchema,
82
+ handler: modelSearchHandler
83
+ };
84
+ export {
85
+ modelSearchHandler,
86
+ modelSearchTool
87
+ };
88
+ //# sourceMappingURL=model-search.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-search.ts"],
4
+ "sourcesContent": ["/**\n * model_search \u2014 search for elements across the model by name/ID substring or\n * source file reference. Mirrors `dr search`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Element } from \"../../core/element.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { NODE_TYPES } from \"../../generated/node-types.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n query: z\n .string()\n .optional()\n .describe(\"Text to match against element ID and name (case-insensitive substring). Ignored when sourceFile is set.\"),\n layer: z.string().optional().describe(\"Restrict search to a single layer.\"),\n type: z.string().optional().describe(\"Restrict search to a single element type.\"),\n sourceFile: z.string().optional().describe(\"Find elements whose source_reference points at this file path.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelSearchArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nfunction normalizePath(filePath: string): string {\n return filePath.replace(/^\\.\\//, \"\").replace(/\\\\/g, \"/\");\n}\n\nfunction matchesSourceFile(element: Element, sourceFilePath: string): boolean {\n const sourceRef = element.getSourceReference();\n if (!sourceRef) return false;\n\n const normalizedQuery = normalizePath(sourceFilePath);\n return (sourceRef.locations ?? []).some((loc) => normalizePath(loc.file) === normalizedQuery);\n}\n\nexport async function modelSearchHandler(args: ModelSearchArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (!args.query && !args.sourceFile && !args.layer && !args.type) {\n throw new CLIError(\n \"At least one of query, sourceFile, layer, or type must be provided\",\n ErrorCategory.USER,\n ['Use \"model_list\" to list all elements without filtering']\n );\n }\n\n if (args.layer && !isValidLayer(args.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(args.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (args.type) {\n const candidateTypes = args.layer\n ? Array.from(NODE_TYPES.values()).filter((t) => t.layer === args.layer)\n : Array.from(NODE_TYPES.values());\n const isKnownType = candidateTypes.some((t) => t.type === args.type);\n if (!isKnownType) {\n const validTypeNames = Array.from(new Set(candidateTypes.map((t) => t.type))).sort();\n const similar = findSimilar(args.type, validTypeNames, 3);\n const suggestions: string[] = [\n args.layer\n ? `Valid types for ${args.layer}: ${formatValidOptions(validTypeNames)}`\n : `Valid types: ${formatValidOptions(validTypeNames)}`,\n ];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(\n `Unknown element type \"${args.type}\"${args.layer ? ` for layer \"${args.layer}\"` : \"\"}`,\n ErrorCategory.USER,\n suggestions\n );\n }\n }\n\n const model = await loadModel(args.rootPath);\n const isSourceFileSearch = !!args.sourceFile;\n const queryLower = (args.query ?? \"\").toLowerCase();\n\n const results: Array<{\n layer: string;\n id: string;\n type: string;\n name: string;\n description?: string;\n sourceFile?: string;\n sourceSymbol?: string;\n }> = [];\n\n for (const layerName of model.getLayerNames()) {\n if (args.layer && layerName !== args.layer) continue;\n\n const layerObj = await model.getLayer(layerName);\n if (!layerObj) continue;\n\n for (const element of layerObj.listElements()) {\n if (args.type && element.type !== args.type) continue;\n\n if (isSourceFileSearch) {\n if (!matchesSourceFile(element, args.sourceFile!)) continue;\n } else {\n const displayId = element.path || element.id;\n const idMatch = displayId.toLowerCase().includes(queryLower);\n const nameMatch = element.name.toLowerCase().includes(queryLower);\n if (!idMatch && !nameMatch) continue;\n }\n\n let sourceFile: string | undefined;\n let sourceSymbol: string | undefined;\n const sourceRef = element.getSourceReference();\n if (sourceRef?.locations && sourceRef.locations.length > 0) {\n sourceFile = sourceRef.locations[0].file;\n sourceSymbol = sourceRef.locations[0].symbol;\n }\n\n results.push({\n layer: layerName,\n id: element.path || element.id,\n type: element.type,\n name: element.name,\n description: element.description,\n sourceFile,\n sourceSymbol,\n });\n }\n }\n\n return jsonResult({\n query: args.query ?? \"\",\n sourceFile: args.sourceFile,\n count: results.length,\n results,\n });\n });\n}\n\nexport const modelSearchTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_search\",\n description: \"Search for elements across the model by name/ID substring or by source file reference.\",\n inputSchema,\n handler: modelSearchHandler,\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { findElementLayer } from "../../utils/element-utils.js";
3
+ import { CLIError, ErrorCategory } from "../../utils/errors.js";
4
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
5
+ const inputSchema = {
6
+ id: z.string().describe("Element ID or path (e.g. 'api.operation.create-order')."),
7
+ rootPath: rootPathSchema
8
+ };
9
+ async function modelShowHandler(args) {
10
+ return runTool(async () => {
11
+ const model = await loadModel(args.rootPath), layerName = await findElementLayer(model, args.id);
12
+ if (!layerName)
13
+ throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [
14
+ 'Use "model_search" to find similar elements',
15
+ 'Use "model_list" to list all elements in a layer'
16
+ ]);
17
+ const layer = await model.getLayer(layerName), element = layer?.getElement(args.id);
18
+ if (!layer || !element)
19
+ throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [
20
+ 'Use "model_search" to find similar elements',
21
+ 'Use "model_list" to list all elements in a layer'
22
+ ]);
23
+ const elementId = element.path || element.id, { outgoing, incoming } = model.relationships.getForElement(elementId);
24
+ return jsonResult({
25
+ layer: layerName,
26
+ element: element.toJSON(),
27
+ relationships: { outgoing, incoming }
28
+ });
29
+ });
30
+ }
31
+ const modelShowTool = {
32
+ name: "model_show",
33
+ description: "Show a single element's full details, attributes, and relationships.",
34
+ inputSchema,
35
+ handler: modelShowHandler
36
+ };
37
+ export {
38
+ modelShowHandler,
39
+ modelShowTool
40
+ };
41
+ //# sourceMappingURL=model-show.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/model-show.ts"],
4
+ "sourcesContent": ["/**\n * model_show \u2014 show a single element with its relationships. Mirrors `dr show`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path (e.g. 'api.operation.create-order').\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelShowArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelShowHandler(args: ModelShowArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const layer = await model.getLayer(layerName);\n const element = layer?.getElement(args.id);\n if (!layer || !element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const elementId = element.path || element.id;\n const { outgoing, incoming } = model.relationships.getForElement(elementId);\n\n return jsonResult({\n layer: layerName,\n element: element.toJSON(),\n relationships: { outgoing, incoming },\n });\n });\n}\n\nexport const modelShowTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_show\",\n description: \"Show a single element's full details, attributes, and relationships.\",\n inputSchema,\n handler: modelShowHandler,\n};\n"],
5
+ "mappings": "AAIA,SAAS,SAAS;AAElB,SAAS,wBAAwB;AACjC,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,IAAI,EAAE,OAAM,EAAG,SAAS,yDAAyD;EACjF,UAAU;;AAKZ,eAAsB,iBAAiB,MAAmB;AACxD,SAAO,QAAQ,YAAW;AACxB,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GAErC,YAAY,MAAM,iBAAiB,OAAO,KAAK,EAAE;AACvD,QAAI,CAAC;AACH,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,QAAQ,MAAM,MAAM,SAAS,SAAS,GACtC,UAAU,OAAO,WAAW,KAAK,EAAE;AACzC,QAAI,CAAC,SAAS,CAAC;AACb,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,YAAY,QAAQ,QAAQ,QAAQ,IACpC,EAAE,UAAU,SAAQ,IAAK,MAAM,cAAc,cAAc,SAAS;AAE1E,WAAO,WAAW;MAChB,OAAO;MACP,SAAS,QAAQ,OAAM;MACvB,eAAe,EAAE,UAAU,SAAQ;KACpC;EACH,CAAC;AACH;AAEO,MAAM,gBAAuD;EAClE,MAAM;EACN,aAAa;EACb;EACA,SAAS;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,22 @@
1
+ import { StatsCollector } from "../../core/stats-collector.js";
2
+ import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
3
+ const inputSchema = {
4
+ rootPath: rootPathSchema
5
+ };
6
+ async function modelStatsHandler(args) {
7
+ return runTool(async () => {
8
+ const model = await loadModel(args.rootPath), stats = await new StatsCollector(model).collect();
9
+ return jsonResult(stats);
10
+ });
11
+ }
12
+ const modelStatsTool = {
13
+ name: "model_stats",
14
+ description: "Get aggregate statistics about the architecture model: element counts, relationships, coverage, and orphans.",
15
+ inputSchema,
16
+ handler: modelStatsHandler
17
+ };
18
+ export {
19
+ modelStatsHandler,
20
+ modelStatsTool
21
+ };
22
+ //# sourceMappingURL=model-stats.js.map