archdraw-mcp-server 1.0.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.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +757 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/__tests__/constants.test.d.ts +2 -0
- package/dist/lib/__tests__/constants.test.d.ts.map +1 -0
- package/dist/lib/__tests__/constants.test.js +47 -0
- package/dist/lib/__tests__/constants.test.js.map +1 -0
- package/dist/lib/__tests__/diagram-state.test.d.ts +2 -0
- package/dist/lib/__tests__/diagram-state.test.d.ts.map +1 -0
- package/dist/lib/__tests__/diagram-state.test.js +75 -0
- package/dist/lib/__tests__/diagram-state.test.js.map +1 -0
- package/dist/lib/__tests__/elk-runner.test.d.ts +2 -0
- package/dist/lib/__tests__/elk-runner.test.d.ts.map +1 -0
- package/dist/lib/__tests__/elk-runner.test.js +87 -0
- package/dist/lib/__tests__/elk-runner.test.js.map +1 -0
- package/dist/lib/checkpoints.d.ts +48 -0
- package/dist/lib/checkpoints.d.ts.map +1 -0
- package/dist/lib/checkpoints.js +58 -0
- package/dist/lib/checkpoints.js.map +1 -0
- package/dist/lib/constants.d.ts +29 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +62 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/diagram-state.d.ts +18 -0
- package/dist/lib/diagram-state.d.ts.map +1 -0
- package/dist/lib/diagram-state.js +55 -0
- package/dist/lib/diagram-state.js.map +1 -0
- package/dist/lib/elk-runner.d.ts +29 -0
- package/dist/lib/elk-runner.d.ts.map +1 -0
- package/dist/lib/elk-runner.js +532 -0
- package/dist/lib/elk-runner.js.map +1 -0
- package/dist/lib/http.d.ts +3 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +13 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/node-catalog.d.ts +10 -0
- package/dist/lib/node-catalog.d.ts.map +1 -0
- package/dist/lib/node-catalog.js +122 -0
- package/dist/lib/node-catalog.js.map +1 -0
- package/dist/lib/parse-prompt.d.ts +26 -0
- package/dist/lib/parse-prompt.d.ts.map +1 -0
- package/dist/lib/parse-prompt.js +289 -0
- package/dist/lib/parse-prompt.js.map +1 -0
- package/dist/lib/prompt-builder.d.ts +14 -0
- package/dist/lib/prompt-builder.d.ts.map +1 -0
- package/dist/lib/prompt-builder.js +133 -0
- package/dist/lib/prompt-builder.js.map +1 -0
- package/dist/lib/schema.d.ts +1231 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +258 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +287 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/__tests__/export-diagram.test.d.ts +2 -0
- package/dist/tools/__tests__/export-diagram.test.d.ts.map +1 -0
- package/dist/tools/__tests__/export-diagram.test.js +40 -0
- package/dist/tools/__tests__/export-diagram.test.js.map +1 -0
- package/dist/tools/__tests__/update-diagram.test.d.ts +2 -0
- package/dist/tools/__tests__/update-diagram.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-diagram.test.js +90 -0
- package/dist/tools/__tests__/update-diagram.test.js.map +1 -0
- package/dist/tools/apply-template.d.ts +28 -0
- package/dist/tools/apply-template.d.ts.map +1 -0
- package/dist/tools/apply-template.js +388 -0
- package/dist/tools/apply-template.js.map +1 -0
- package/dist/tools/export-diagram.d.ts +36 -0
- package/dist/tools/export-diagram.d.ts.map +1 -0
- package/dist/tools/export-diagram.js +65 -0
- package/dist/tools/export-diagram.js.map +1 -0
- package/dist/tools/fix-layout.d.ts +19 -0
- package/dist/tools/fix-layout.d.ts.map +1 -0
- package/dist/tools/fix-layout.js +100 -0
- package/dist/tools/fix-layout.js.map +1 -0
- package/dist/tools/generate-diagram.d.ts +31 -0
- package/dist/tools/generate-diagram.d.ts.map +1 -0
- package/dist/tools/generate-diagram.js +385 -0
- package/dist/tools/generate-diagram.js.map +1 -0
- package/dist/tools/list-nodes.d.ts +18 -0
- package/dist/tools/list-nodes.d.ts.map +1 -0
- package/dist/tools/list-nodes.js +48 -0
- package/dist/tools/list-nodes.js.map +1 -0
- package/dist/tools/load-checkpoint.d.ts +18 -0
- package/dist/tools/load-checkpoint.d.ts.map +1 -0
- package/dist/tools/load-checkpoint.js +24 -0
- package/dist/tools/load-checkpoint.js.map +1 -0
- package/dist/tools/read-me.d.ts +2 -0
- package/dist/tools/read-me.d.ts.map +1 -0
- package/dist/tools/read-me.js +326 -0
- package/dist/tools/read-me.js.map +1 -0
- package/dist/tools/save-checkpoint.d.ts +11 -0
- package/dist/tools/save-checkpoint.d.ts.map +1 -0
- package/dist/tools/save-checkpoint.js +17 -0
- package/dist/tools/save-checkpoint.js.map +1 -0
- package/dist/tools/update-diagram.d.ts +20 -0
- package/dist/tools/update-diagram.d.ts.map +1 -0
- package/dist/tools/update-diagram.js +189 -0
- package/dist/tools/update-diagram.js.map +1 -0
- package/dist/tools/validate-diagram.d.ts +14 -0
- package/dist/tools/validate-diagram.d.ts.map +1 -0
- package/dist/tools/validate-diagram.js +181 -0
- package/dist/tools/validate-diagram.js.map +1 -0
- package/dist/types/index.d.ts +218 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +50 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { generateDiagram } from './tools/generate-diagram.js';
|
|
6
|
+
import { fixLayout } from './tools/fix-layout.js';
|
|
7
|
+
import { listNodeTypes } from './tools/list-nodes.js';
|
|
8
|
+
import { applyTemplate, getAvailableTemplates } from './tools/apply-template.js';
|
|
9
|
+
import { getReadMe } from './tools/read-me.js';
|
|
10
|
+
import { getDiagramState } from './lib/diagram-state.js';
|
|
11
|
+
import { validateDiagram } from './tools/validate-diagram.js';
|
|
12
|
+
import { updateDiagram } from './tools/update-diagram.js';
|
|
13
|
+
import { saveCheckpoint } from './tools/save-checkpoint.js';
|
|
14
|
+
import { loadCheckpoint } from './tools/load-checkpoint.js';
|
|
15
|
+
import { exportDiagram } from './tools/export-diagram.js';
|
|
16
|
+
import { GenerateDiagramInputSchema, FixLayoutInputSchema, ListNodeTypesInputSchema, ApplyTemplateInputSchema, UpdateDiagramInputSchema, SaveCheckpointInputSchema, LoadCheckpointInputSchema, ExportDiagramInputSchema, } from './lib/schema.js';
|
|
17
|
+
const TOOLS = [
|
|
18
|
+
{
|
|
19
|
+
name: 'generate_diagram',
|
|
20
|
+
description: `Generate a rich architecture diagram with groups, labeled edges, and visual hierarchy.
|
|
21
|
+
|
|
22
|
+
**IMPORTANT**: When this tool returns a 'diagramUrl', tell the user to open that URL in their browser.
|
|
23
|
+
|
|
24
|
+
**INPUT MODES — choose ONE**:
|
|
25
|
+
|
|
26
|
+
**Mode 1 (RECOMMENDED): Mermaid code** — pass a \`graph LR\` / \`graph TD\` diagram in \`mermaid\`.
|
|
27
|
+
This runs the same parser + layout engine the web editor uses, so output is guaranteed to match the product.
|
|
28
|
+
Example:
|
|
29
|
+
graph LR
|
|
30
|
+
subgraph client["Client Tier"]
|
|
31
|
+
Web[Web App]
|
|
32
|
+
Mobile[Mobile App]
|
|
33
|
+
end
|
|
34
|
+
subgraph edge["API Gateway Tier"]
|
|
35
|
+
GW[API Gateway]
|
|
36
|
+
end
|
|
37
|
+
subgraph data["Data Tier"]
|
|
38
|
+
DB[("PostgreSQL")]
|
|
39
|
+
end
|
|
40
|
+
Web --> GW
|
|
41
|
+
Mobile --> GW
|
|
42
|
+
GW --> DB
|
|
43
|
+
Use \`direction\` to pick LR (default) or TD. Any graph \`graph TD\` implies top-down.
|
|
44
|
+
The web parser runs Mermaid → React Flow → Dagre layout, so positions come out clean automatically.
|
|
45
|
+
Optional directives like \`%% archdraw-shape: {"id":"<id>","shape":"shield"}\` are supported for non-native shapes.
|
|
46
|
+
|
|
47
|
+
**Mode 2 (legacy): Structured JSON** — pass \`nodes\` and \`edges\` arrays (schemas below). Less preferred;
|
|
48
|
+
the JSON path uses the internal ELK layout and cannot round-trip through the product pipeline.
|
|
49
|
+
|
|
50
|
+
**ALWAYS ALSO PASS** (when you have them):
|
|
51
|
+
- \`userPrompt\`: the user's request verbatim — node subtitles must reflect any tech stack they named.
|
|
52
|
+
- \`techStack\`: explicit list of technologies (["Next.js", "PostgreSQL 15", "Redis"]).
|
|
53
|
+
- \`customFeatures\`: features the user explicitly asked for.
|
|
54
|
+
|
|
55
|
+
**🚨 CRITICAL SYSTEMATIC RULES — VIOLATIONS WILL BE FLAGGED:**
|
|
56
|
+
|
|
57
|
+
**RULE A — AUTH SERVICE TOPOLOGY**: The Auth Service receives arrows ONLY from login and token refresh endpoints. NO other arrows from the gateway into Auth Service are permitted. All other routes: gateway validates JWT internally and routes DIRECTLY to the target service. BEFORE FINALIZING: audit every edge targeting Auth Service — if label is not login/register/token-refresh, delete it.
|
|
58
|
+
|
|
59
|
+
**RULE B — OBJECT STORAGE IS MANDATORY FOR MEDIA DOMAINS**: For video streaming, image sharing, audio streaming, or any diagram with a CDN or Transcoding Worker — Object Storage (S3/GCS) MUST be present. Required pipeline: Upload → Object Storage (raw) → Transcoding Worker → Object Storage (output) → CDN → Client. Drawing CDN without an origin storage is architecturally invalid.
|
|
60
|
+
|
|
61
|
+
**RULE C — ANALYTICS EVENT STREAM IS CORE INFRASTRUCTURE**: For video/audio streaming, social media, e-commerce, or gaming domains — an Analytics Event Stream (Kafka/Kinesis) feeding a Recommendation Engine is mandatory. Pattern: Client → (play/click event) → Event Stream → Analytics Processor → Recommendation Engine. This is not optional logging — it is the product's primary feedback loop.
|
|
62
|
+
|
|
63
|
+
**RULE D — SECURITY SERVICES MUST NOT BYPASS THE GATEWAY**: DRM, Auth, and License Servers must NEVER connect directly to client-tier nodes. Always route through API Gateway (client → gateway → DRM). A direct client→DRM connection means unauthenticated users can request licenses.
|
|
64
|
+
|
|
65
|
+
**RULE E — EDGE DIRECTION: LEFT->RIGHT ONLY, NO STAR TOPOLOGY** THIS IS THE #1 GENERATION ERROR:
|
|
66
|
+
Edges MUST flow from lower-numbered tier to higher-numbered tier:
|
|
67
|
+
client(0) -> edge(1) -> compute(2) -> async(3) -> data(4) -> external(5)
|
|
68
|
+
|
|
69
|
+
Client tier nodes (Web App, Mobile App) are REQUEST INITIATORS -- they are edge SOURCES, NOT targets.
|
|
70
|
+
- CORRECT: Web App -> API Gateway -> Order Service -> PostgreSQL
|
|
71
|
+
- WRONG: Order Service -> Web App (backward edge, FORBIDDEN)
|
|
72
|
+
- WRONG: PostgreSQL -> Web App (data to client, FORBIDDEN)
|
|
73
|
+
- WRONG: 10 services all -> Web App (star topology, REJECTED)
|
|
74
|
+
|
|
75
|
+
Web Client is NOT a hub. Do NOT draw edges from backend/data/service nodes back to the client.
|
|
76
|
+
If backend needs to push: add a WebSocket Gateway (tier:edge) or Notification Service (tier:compute) as intermediary.
|
|
77
|
+
|
|
78
|
+
DIAGRAMS WITH STAR TOPOLOGY WILL BE AUTOMATICALLY REJECTED. Fix by:
|
|
79
|
+
1. Reverse any edges that point TO a client-tier node FROM a backend node
|
|
80
|
+
2. Remove all edges where target=web_client that do not originate from another client-tier node
|
|
81
|
+
|
|
82
|
+
**MANDATORY REQUIREMENTS** — diagrams missing these will be flagged:
|
|
83
|
+
1. At least ONE group (a Mermaid \`subgraph\`, or \`isGroup:true\` in JSON mode) to cluster related services
|
|
84
|
+
2. Every node MUST have a subtitle describing its specific role
|
|
85
|
+
3. All async/stream/event edges MUST have a label (the event/message name)
|
|
86
|
+
4. Every node MUST have a tier assigned
|
|
87
|
+
5. Domain-specific required nodes must be present (see read_me for checklist)
|
|
88
|
+
|
|
89
|
+
**WORKFLOW**:
|
|
90
|
+
1. Call read_me FIRST for the full reference guide and domain checklist
|
|
91
|
+
2. Identify the domain and verify all required domain nodes are planned
|
|
92
|
+
3. Optionally call list_node_types to find icon names
|
|
93
|
+
4. Design the Mermaid graph: groups (subgraphs) first, then children inside them
|
|
94
|
+
5. Design edges: use correct communicationType, audit Auth Service edges, verify no security bypass
|
|
95
|
+
6. **EDGE AUDIT (mandatory)**: Before calling this tool, scan every edge you planned:
|
|
96
|
+
- Does any edge have a client-tier node as the TARGET? DELETE IT (unless both source and target are client tier)
|
|
97
|
+
- Does any single node receive >45% of all edges? That node is a hub -- redistribute connections
|
|
98
|
+
- Do all edges flow LEFT->RIGHT (lower tier -> higher tier)? If not, fix direction.
|
|
99
|
+
7. Call this tool
|
|
100
|
+
|
|
101
|
+
**NODE FIELDS (JSON mode)**:
|
|
102
|
+
- id (required): snake_case unique ID
|
|
103
|
+
- label (required): 1-3 word display name
|
|
104
|
+
- tier (required): client | edge | compute | async | data | external | observe
|
|
105
|
+
- subtitle (required): specific description of what this service does
|
|
106
|
+
- isGroup: true = swimlane container wrapping child nodes
|
|
107
|
+
- parentId: ID of parent group (places this node inside that group)
|
|
108
|
+
- groupColor: hex background tint for group containers
|
|
109
|
+
- icon: lucide icon name (box, server, database, zap, shield, globe, etc.)
|
|
110
|
+
- accentColor: override highlight color (15 palette options)
|
|
111
|
+
- status: healthy | warning | error | unknown
|
|
112
|
+
- width/height: pixel size (groups: 400-800px wide, 200-400px tall)
|
|
113
|
+
|
|
114
|
+
**EDGE FIELDS (JSON mode)**:
|
|
115
|
+
- source, target (required): node IDs
|
|
116
|
+
- communicationType: sync | async | stream | event | dep
|
|
117
|
+
- label: required for async/stream/event — name the message or event
|
|
118
|
+
- pathType: Smoothstep | bezier | step | straight
|
|
119
|
+
|
|
120
|
+
**TIER COLORS**:
|
|
121
|
+
- client: #64748b (slate) — browsers, mobile apps
|
|
122
|
+
- edge: #6366f1 (indigo) — API gateways, load balancers, CDN
|
|
123
|
+
- compute: #0d9488 (teal) — microservices, workers, APIs
|
|
124
|
+
- async: #d97706 (amber) — queues, event buses, Kafka
|
|
125
|
+
- data: #3b82f6 (blue) — databases, caches, object storage
|
|
126
|
+
- external: #8b5cf6 (violet) — third-party APIs, payment gateways
|
|
127
|
+
- observe: #6b7280 (gray) — monitoring, logging, tracing`,
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: {
|
|
131
|
+
mermaid: {
|
|
132
|
+
type: 'string',
|
|
133
|
+
description: 'RECOMMENDED: Mermaid code for the diagram (graph LR or graph TD with subgraphs). Uses the web pipeline parser + Dagre layout.',
|
|
134
|
+
},
|
|
135
|
+
nodes: {
|
|
136
|
+
type: 'array',
|
|
137
|
+
description: 'Legacy JSON mode (only if not using mermaid). Array of nodes. RULES: (1) every node needs id+label+tier+subtitle, (2) include at least one isGroup:true node, (3) use parentId to nest nodes inside groups, (4) use accentColor to visually differentiate nodes in the same tier.',
|
|
138
|
+
items: {
|
|
139
|
+
type: 'object',
|
|
140
|
+
properties: {
|
|
141
|
+
id: { type: 'string', description: 'Unique snake_case identifier (e.g. "api_gateway", "postgres_db")' },
|
|
142
|
+
label: { type: 'string', description: 'Short display name (1-3 words)' },
|
|
143
|
+
tier: { type: 'string', description: 'Tier: client | edge | compute | async | data | external | observe' },
|
|
144
|
+
layer: { type: 'string', description: 'Alias for tier' },
|
|
145
|
+
subtitle: { type: 'string', description: 'REQUIRED: Specific description (e.g. "PostgreSQL 15, stores orders and users")' },
|
|
146
|
+
isGroup: { type: 'boolean', description: 'true = swimlane container. Use to cluster related services.' },
|
|
147
|
+
parentId: { type: 'string', description: 'ID of parent group — places this node inside that group' },
|
|
148
|
+
groupColor: { type: 'string', description: 'Background hex for group containers (e.g. "#0f172a")' },
|
|
149
|
+
icon: { type: 'string', description: 'Lucide icon name (server, database, zap, globe, shield, cpu, activity, box, cloud, layers, user, lock, wifi)' },
|
|
150
|
+
tierColor: { type: 'string', description: 'Override tier color hex' },
|
|
151
|
+
accentColor: { type: 'string', description: 'Highlight color: #3b82f6 #0ea5e9 #06b6d4 #14b8a6 #22c55e #f59e0b #f97316 #ef4444 #ec4899 #6b7280 #f43f5e #a855f7 #84cc16 #fb923c' },
|
|
152
|
+
status: { type: 'string', enum: ['healthy', 'warning', 'error', 'unknown'], description: 'Status dot shown on node' },
|
|
153
|
+
width: { type: 'number', description: 'Width px. Groups: 400-800. Nodes: 160-260.' },
|
|
154
|
+
height: { type: 'number', description: 'Height px. Groups: 200-400. Nodes: 60-90.' },
|
|
155
|
+
shape: { type: 'string', enum: ['rectangle', 'diamond', 'ellipse', 'hexagon'], description: 'Node shape' },
|
|
156
|
+
},
|
|
157
|
+
required: ['label'],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
edges: {
|
|
161
|
+
type: 'array',
|
|
162
|
+
description: 'Legacy JSON mode (only if not using mermaid). Array of edges. REQUIRED. Add labels to all async/event/stream edges. Do not connect data tier directly to client tier.',
|
|
163
|
+
items: {
|
|
164
|
+
type: 'object',
|
|
165
|
+
properties: {
|
|
166
|
+
id: { type: 'string', description: 'Unique edge identifier' },
|
|
167
|
+
source: { type: 'string', description: 'Source node ID' },
|
|
168
|
+
target: { type: 'string', description: 'Target node ID' },
|
|
169
|
+
communicationType: {
|
|
170
|
+
type: 'string',
|
|
171
|
+
enum: ['sync', 'async', 'stream', 'event', 'dep'],
|
|
172
|
+
default: 'sync',
|
|
173
|
+
description: 'sync=REST/gRPC, async=queue/kafka, stream=WebSocket/SSE, event=pub-sub, dep=dependency',
|
|
174
|
+
},
|
|
175
|
+
pathType: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
enum: ['smooth', 'Smoothstep', 'bezier', 'step', 'straight'],
|
|
178
|
+
default: 'Smoothstep',
|
|
179
|
+
description: 'Edge path style',
|
|
180
|
+
},
|
|
181
|
+
label: { type: 'string', description: 'Edge label. REQUIRED for async/stream/event. Describe the message or event name.' },
|
|
182
|
+
},
|
|
183
|
+
required: ['source', 'target'],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
direction: {
|
|
187
|
+
type: 'string',
|
|
188
|
+
enum: ['RIGHT', 'DOWN', 'LEFT', 'UP'],
|
|
189
|
+
default: 'RIGHT',
|
|
190
|
+
description: 'Layout direction: RIGHT (LR, default), DOWN (TB for pipelines)',
|
|
191
|
+
},
|
|
192
|
+
label: { type: 'string', description: 'Diagram title' },
|
|
193
|
+
diagramDescription: { type: 'string', description: 'One-sentence description of what this architecture does' },
|
|
194
|
+
userPrompt: { type: 'string', description: 'The user\'s original request verbatim. Subtitle content must reflect any tech stack/services the user named.' },
|
|
195
|
+
techStack: { type: 'array', items: { type: 'string' }, description: 'Explicit technologies/services extracted from the prompt (e.g. ["Next.js", "PostgreSQL 15"]).' },
|
|
196
|
+
customFeatures: { type: 'array', items: { type: 'string' }, description: 'Custom features/components the user explicitly requested.' },
|
|
197
|
+
},
|
|
198
|
+
required: [],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'fix_layout',
|
|
203
|
+
description: `Apply ELK auto-layout algorithm to existing nodes and edges.
|
|
204
|
+
|
|
205
|
+
**USE WHEN**: User provides nodes/edges that need automatic positioning
|
|
206
|
+
**INPUT**: Nodes with their tier assignments, plus edges between them
|
|
207
|
+
**OUTPUT**: Returns nodes with x,y positions computed by ELK layered algorithm
|
|
208
|
+
|
|
209
|
+
This tool does NOT generate or modify nodes/edges - it only computes optimal positions.
|
|
210
|
+
|
|
211
|
+
**INPUT**:
|
|
212
|
+
- nodes: Array of nodes (id, label, layer/tier required)
|
|
213
|
+
- edges: Array of connections between nodes
|
|
214
|
+
- direction: Layout direction (RIGHT is default, means left-to-right)`,
|
|
215
|
+
inputSchema: {
|
|
216
|
+
type: 'object',
|
|
217
|
+
properties: {
|
|
218
|
+
nodes: {
|
|
219
|
+
type: 'array',
|
|
220
|
+
description: 'Array of nodes with layer assignments',
|
|
221
|
+
items: {
|
|
222
|
+
type: 'object',
|
|
223
|
+
properties: {
|
|
224
|
+
id: { type: 'string', description: 'Unique node identifier' },
|
|
225
|
+
label: { type: 'string', description: 'Node label/name' },
|
|
226
|
+
layer: { type: 'string', description: 'Tier layer: client, edge, compute, async, data, observe, external' },
|
|
227
|
+
width: { type: 'number', default: 180, description: 'Node width' },
|
|
228
|
+
height: { type: 'number', default: 70, description: 'Node height' },
|
|
229
|
+
},
|
|
230
|
+
required: ['id', 'label', 'layer'],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
edges: {
|
|
234
|
+
type: 'array',
|
|
235
|
+
description: 'Array of edges connecting the nodes',
|
|
236
|
+
items: {
|
|
237
|
+
type: 'object',
|
|
238
|
+
properties: {
|
|
239
|
+
id: { type: 'string', description: 'Unique edge identifier' },
|
|
240
|
+
source: { type: 'string', description: 'Source node ID' },
|
|
241
|
+
target: { type: 'string', description: 'Target node ID' },
|
|
242
|
+
communicationType: {
|
|
243
|
+
type: 'string',
|
|
244
|
+
enum: ['sync', 'async', 'stream', 'event', 'dep'],
|
|
245
|
+
default: 'sync',
|
|
246
|
+
description: 'Communication type between nodes',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
required: ['source', 'target'],
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
direction: {
|
|
253
|
+
type: 'string',
|
|
254
|
+
enum: ['RIGHT', 'DOWN', 'LEFT', 'UP'],
|
|
255
|
+
default: 'RIGHT',
|
|
256
|
+
description: 'Layout direction',
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
required: ['nodes'],
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'list_node_types',
|
|
264
|
+
description: `List all available pre-made component types from the ArchDraw component library.
|
|
265
|
+
|
|
266
|
+
**USE WHEN**: You want to see what components are available before generating a diagram
|
|
267
|
+
**OUTPUT**: Categorized list of 150+ component types with their icons and descriptions
|
|
268
|
+
|
|
269
|
+
**FILTERING**:
|
|
270
|
+
- category: Filter by category name (e.g., "AI / ML", "Data Storage", "Compute", "Messaging & Events")
|
|
271
|
+
- search: Search by label, description, or category
|
|
272
|
+
- limit: Max results (default 50, max 200)
|
|
273
|
+
|
|
274
|
+
**CATEGORIES INCLUDE**:
|
|
275
|
+
- Client & Entry (CDN, Load Balancer, API Gateway)
|
|
276
|
+
- Compute (API Server, Auth Service, Workers, Containers)
|
|
277
|
+
- AI / ML (LLM Models, Vector DB, Embedding Service, RAG)
|
|
278
|
+
- Data Storage (PostgreSQL, MongoDB, Redis, S3)
|
|
279
|
+
- Messaging & Events (Kafka, RabbitMQ, SQS)
|
|
280
|
+
- Observability (Prometheus, Grafana, ELK Stack)
|
|
281
|
+
- External Services (Stripe, Twilio, SendGrid)`,
|
|
282
|
+
inputSchema: {
|
|
283
|
+
type: 'object',
|
|
284
|
+
properties: {
|
|
285
|
+
category: {
|
|
286
|
+
type: 'string',
|
|
287
|
+
description: 'Filter by category name (e.g., "AI / ML", "Data Storage", "Compute")',
|
|
288
|
+
},
|
|
289
|
+
search: {
|
|
290
|
+
type: 'string',
|
|
291
|
+
description: 'Search by label, description, or category',
|
|
292
|
+
},
|
|
293
|
+
limit: {
|
|
294
|
+
type: 'number',
|
|
295
|
+
default: 50,
|
|
296
|
+
minimum: 1,
|
|
297
|
+
maximum: 200,
|
|
298
|
+
description: 'Maximum number of results',
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'apply_template',
|
|
305
|
+
description: `Apply a pre-built architecture template with pre-defined nodes and edges.
|
|
306
|
+
|
|
307
|
+
**IMPORTANT**: When this tool returns a 'diagramUrl', you MUST tell the user to open that URL in their browser to view the diagram. The URL format is: http://localhost:3000/editor?session=<sessionId>
|
|
308
|
+
|
|
309
|
+
**USE WHEN**: User wants a common architecture pattern (e-commerce, chat app, rideshare, etc.)
|
|
310
|
+
**OUTPUT**: Full diagram with positioned nodes and edges from the template. Check the 'message' and 'diagramUrl' fields and tell the user to open the diagramUrl.
|
|
311
|
+
|
|
312
|
+
**AVAILABLE TEMPLATES**:
|
|
313
|
+
- archflow: ArchDraw's own architecture (modern SaaS)
|
|
314
|
+
- chatgpt: LLM chat app with RAG, vector DB, streaming
|
|
315
|
+
- instagram: Social platform with Kafka, media storage, search
|
|
316
|
+
- rideshare: Uber-like with real-time tracking and dynamic pricing
|
|
317
|
+
- ecommerce: Full e-commerce with cart, payments, order management
|
|
318
|
+
|
|
319
|
+
**CUSTOMIZATIONS**:
|
|
320
|
+
- renameNodes: Map of node ID to new label
|
|
321
|
+
- addNodes: Additional nodes to include`,
|
|
322
|
+
inputSchema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
properties: {
|
|
325
|
+
templateId: {
|
|
326
|
+
type: 'string',
|
|
327
|
+
description: 'Template identifier: archflow, chatgpt, instagram, rideshare, ecommerce',
|
|
328
|
+
},
|
|
329
|
+
customizations: {
|
|
330
|
+
type: 'object',
|
|
331
|
+
description: 'Optional customizations to apply',
|
|
332
|
+
properties: {
|
|
333
|
+
renameNodes: {
|
|
334
|
+
type: 'object',
|
|
335
|
+
description: 'Map of node ID to new label',
|
|
336
|
+
additionalProperties: { type: 'string' },
|
|
337
|
+
},
|
|
338
|
+
addNodes: {
|
|
339
|
+
type: 'array',
|
|
340
|
+
description: 'Additional nodes to add',
|
|
341
|
+
items: {
|
|
342
|
+
type: 'object',
|
|
343
|
+
properties: {
|
|
344
|
+
id: { type: 'string' },
|
|
345
|
+
label: { type: 'string' },
|
|
346
|
+
category: { type: 'string' },
|
|
347
|
+
color: { type: 'string' },
|
|
348
|
+
icon: { type: 'string' },
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
required: ['templateId'],
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
name: 'list_templates',
|
|
360
|
+
description: 'List all available architecture templates with their descriptions',
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: 'object',
|
|
363
|
+
properties: {},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: 'read_me',
|
|
368
|
+
description: `Returns a compact LLM-optimized reference guide for ArchDraw — tiers, node types,
|
|
369
|
+
edge communication types, layout rules, and best practices. Call this FIRST before generating
|
|
370
|
+
any diagram to produce accurate, professional output.`,
|
|
371
|
+
inputSchema: {
|
|
372
|
+
type: 'object',
|
|
373
|
+
properties: {},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
name: 'get_diagram_state',
|
|
378
|
+
description: `Returns the current diagram's nodes and edges as structured JSON.
|
|
379
|
+
Call this before update_diagram to read what's on the canvas.
|
|
380
|
+
Optionally pass a sessionId to load that diagram first (e.g. a link the user opened).`,
|
|
381
|
+
inputSchema: {
|
|
382
|
+
type: 'object',
|
|
383
|
+
properties: {
|
|
384
|
+
sessionId: { type: 'string', description: 'Optional session ID to load before returning state (e.g. from a diagramUrl the user shared).' },
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
name: 'update_diagram',
|
|
390
|
+
description: `Surgically modifies an existing diagram. Add nodes, remove nodes,
|
|
391
|
+
add edges, remove edges, or update node properties — without regenerating the whole diagram.`,
|
|
392
|
+
inputSchema: {
|
|
393
|
+
type: 'object',
|
|
394
|
+
properties: {
|
|
395
|
+
addNodes: {
|
|
396
|
+
type: 'array',
|
|
397
|
+
description: 'Nodes to add',
|
|
398
|
+
items: {
|
|
399
|
+
type: 'object',
|
|
400
|
+
properties: {
|
|
401
|
+
id: { type: 'string', description: 'Unique node identifier' },
|
|
402
|
+
label: { type: 'string', description: 'Display name' },
|
|
403
|
+
tier: { type: 'string', description: 'Tier: client, edge, compute, async, data, observe, external' },
|
|
404
|
+
subtitle: { type: 'string', description: 'Optional short description' },
|
|
405
|
+
icon: { type: 'string', description: 'Optional icon name' },
|
|
406
|
+
},
|
|
407
|
+
required: ['id', 'label', 'tier'],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
removeNodeIds: {
|
|
411
|
+
type: 'array',
|
|
412
|
+
description: 'Node IDs to remove',
|
|
413
|
+
items: { type: 'string' },
|
|
414
|
+
},
|
|
415
|
+
addEdges: {
|
|
416
|
+
type: 'array',
|
|
417
|
+
description: 'Edges to add',
|
|
418
|
+
items: {
|
|
419
|
+
type: 'object',
|
|
420
|
+
properties: {
|
|
421
|
+
source: { type: 'string', description: 'Source node ID' },
|
|
422
|
+
target: { type: 'string', description: 'Target node ID' },
|
|
423
|
+
communicationType: { type: 'string', enum: ['sync', 'async', 'stream', 'event', 'dep'] },
|
|
424
|
+
label: { type: 'string', description: 'Optional edge label' },
|
|
425
|
+
},
|
|
426
|
+
required: ['source', 'target'],
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
removeEdgeIds: {
|
|
430
|
+
type: 'array',
|
|
431
|
+
description: 'Edge IDs to remove',
|
|
432
|
+
items: { type: 'string' },
|
|
433
|
+
},
|
|
434
|
+
updateNodes: {
|
|
435
|
+
type: 'array',
|
|
436
|
+
description: 'Nodes to update',
|
|
437
|
+
items: {
|
|
438
|
+
type: 'object',
|
|
439
|
+
properties: {
|
|
440
|
+
id: { type: 'string', description: 'Node ID to update' },
|
|
441
|
+
label: { type: 'string', description: 'New label' },
|
|
442
|
+
subtitle: { type: 'string', description: 'New subtitle' },
|
|
443
|
+
tier: { type: 'string', description: 'New tier' },
|
|
444
|
+
},
|
|
445
|
+
required: ['id'],
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
name: 'validate_diagram',
|
|
453
|
+
description: `Analyses the current diagram and returns a list of structural issues
|
|
454
|
+
and improvement suggestions. Use after generating to catch problems before rendering.`,
|
|
455
|
+
inputSchema: {
|
|
456
|
+
type: 'object',
|
|
457
|
+
properties: {},
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
name: 'save_checkpoint',
|
|
462
|
+
description: `Saves the current diagram state with a named label so it can be restored later.
|
|
463
|
+
Useful for multi-turn workflows: save before a major change, restore if needed.`,
|
|
464
|
+
inputSchema: {
|
|
465
|
+
type: 'object',
|
|
466
|
+
properties: {
|
|
467
|
+
name: { type: 'string', description: 'Checkpoint name (e.g. "before-refactor")' },
|
|
468
|
+
description: { type: 'string', description: 'Optional description' },
|
|
469
|
+
},
|
|
470
|
+
required: ['name'],
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
name: 'load_checkpoint',
|
|
475
|
+
description: `Restores a previously saved diagram state by name.`,
|
|
476
|
+
inputSchema: {
|
|
477
|
+
type: 'object',
|
|
478
|
+
properties: {
|
|
479
|
+
name: { type: 'string', description: 'Checkpoint name to restore' },
|
|
480
|
+
listAvailable: { type: 'boolean', description: 'If true, list all checkpoints without restoring' },
|
|
481
|
+
},
|
|
482
|
+
required: ['name'],
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: 'export_diagram',
|
|
487
|
+
description: `Export the current diagram in various formats.
|
|
488
|
+
|
|
489
|
+
**USE WHEN**: User wants to save or download the diagram
|
|
490
|
+
**OUTPUT**: Returns the diagram data or instructions for image export
|
|
491
|
+
|
|
492
|
+
**FORMATS**:
|
|
493
|
+
- json: Returns raw nodes and edges as JSON (recommended for saving)
|
|
494
|
+
- png: Returns instructions to export as PNG from the editor
|
|
495
|
+
- svg: Returns instructions to export as SVG from the editor
|
|
496
|
+
|
|
497
|
+
**REQUIREMENT**: You must have a diagram loaded (generate or apply a template first).`,
|
|
498
|
+
inputSchema: {
|
|
499
|
+
type: 'object',
|
|
500
|
+
properties: {
|
|
501
|
+
sessionId: { type: 'string', description: 'Session ID from a previous diagram operation. Omit to use the most recent session.' },
|
|
502
|
+
format: { type: 'string', enum: ['json', 'png', 'svg'], default: 'json', description: 'Export format' },
|
|
503
|
+
},
|
|
504
|
+
required: [],
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
];
|
|
508
|
+
class ArchDrawMCPServer {
|
|
509
|
+
server;
|
|
510
|
+
constructor() {
|
|
511
|
+
this.server = new Server({
|
|
512
|
+
name: 'archdraw-mcp-server',
|
|
513
|
+
version: '1.0.0',
|
|
514
|
+
}, {
|
|
515
|
+
capabilities: {
|
|
516
|
+
tools: {},
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
this.setupHandlers();
|
|
520
|
+
}
|
|
521
|
+
setupHandlers() {
|
|
522
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
523
|
+
return { tools: TOOLS };
|
|
524
|
+
});
|
|
525
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
526
|
+
const { name, arguments: args } = request.params;
|
|
527
|
+
try {
|
|
528
|
+
switch (name) {
|
|
529
|
+
case 'generate_diagram': {
|
|
530
|
+
const input = GenerateDiagramInputSchema.parse(args);
|
|
531
|
+
const result = await generateDiagram(input);
|
|
532
|
+
if (result.success) {
|
|
533
|
+
const { setDiagramState } = await import('./lib/diagram-state.js');
|
|
534
|
+
setDiagramState({ nodes: result.nodes, edges: result.edges, sessionId: result.sessionId });
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
content: [
|
|
538
|
+
{
|
|
539
|
+
type: 'text',
|
|
540
|
+
text: JSON.stringify({
|
|
541
|
+
success: result.success,
|
|
542
|
+
message: result.message,
|
|
543
|
+
diagramUrl: result.diagramUrl,
|
|
544
|
+
shareUrl: result.shareUrl,
|
|
545
|
+
sessionId: result.sessionId,
|
|
546
|
+
metadata: result.metadata,
|
|
547
|
+
errors: result.errors,
|
|
548
|
+
note: "Raw nodes and edges omitted for brevity."
|
|
549
|
+
}, null, 2),
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
case 'fix_layout': {
|
|
555
|
+
const input = FixLayoutInputSchema.parse(args);
|
|
556
|
+
const result = await fixLayout(input);
|
|
557
|
+
return {
|
|
558
|
+
content: [
|
|
559
|
+
{
|
|
560
|
+
type: 'text',
|
|
561
|
+
text: JSON.stringify(result, null, 2),
|
|
562
|
+
},
|
|
563
|
+
],
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
case 'list_node_types': {
|
|
567
|
+
const input = ListNodeTypesInputSchema.parse(args ?? {});
|
|
568
|
+
const result = await listNodeTypes(input);
|
|
569
|
+
return {
|
|
570
|
+
content: [
|
|
571
|
+
{
|
|
572
|
+
type: 'text',
|
|
573
|
+
text: JSON.stringify(result, null, 2),
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
case 'apply_template': {
|
|
579
|
+
const input = ApplyTemplateInputSchema.parse(args);
|
|
580
|
+
const result = await applyTemplate(input);
|
|
581
|
+
if (result.success) {
|
|
582
|
+
const { setDiagramState } = await import('./lib/diagram-state.js');
|
|
583
|
+
setDiagramState({ nodes: result.nodes, edges: result.edges, sessionId: result.sessionId });
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
content: [
|
|
587
|
+
{
|
|
588
|
+
type: 'text',
|
|
589
|
+
text: JSON.stringify({
|
|
590
|
+
success: result.success,
|
|
591
|
+
message: result.message,
|
|
592
|
+
diagramUrl: result.diagramUrl,
|
|
593
|
+
shareUrl: result.shareUrl,
|
|
594
|
+
sessionId: result.sessionId,
|
|
595
|
+
errors: result.errors,
|
|
596
|
+
note: "Raw nodes and edges omitted for brevity."
|
|
597
|
+
}, null, 2),
|
|
598
|
+
},
|
|
599
|
+
],
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
case 'list_templates': {
|
|
603
|
+
const templates = getAvailableTemplates();
|
|
604
|
+
return {
|
|
605
|
+
content: [
|
|
606
|
+
{
|
|
607
|
+
type: 'text',
|
|
608
|
+
text: JSON.stringify({ templates }, null, 2),
|
|
609
|
+
},
|
|
610
|
+
],
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
case 'read_me': {
|
|
614
|
+
const readmeContent = getReadMe();
|
|
615
|
+
return {
|
|
616
|
+
content: [
|
|
617
|
+
{
|
|
618
|
+
type: 'text',
|
|
619
|
+
text: readmeContent,
|
|
620
|
+
},
|
|
621
|
+
],
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
case 'get_diagram_state': {
|
|
625
|
+
const { sessionId } = (args ?? {});
|
|
626
|
+
if (typeof sessionId === 'string' && sessionId.trim().length > 0) {
|
|
627
|
+
const { syncDiagramStateFromSession } = await import('./lib/diagram-state.js');
|
|
628
|
+
const synced = await syncDiagramStateFromSession(sessionId.trim());
|
|
629
|
+
if (!synced) {
|
|
630
|
+
return {
|
|
631
|
+
content: [
|
|
632
|
+
{
|
|
633
|
+
type: 'text',
|
|
634
|
+
text: JSON.stringify({ error: `Could not load session '${sessionId}'. It may not exist or the frontend is unreachable.` }, null, 2),
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
isError: true,
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const state = getDiagramState();
|
|
642
|
+
return {
|
|
643
|
+
content: [
|
|
644
|
+
{
|
|
645
|
+
type: 'text',
|
|
646
|
+
text: JSON.stringify(state.nodes.length === 0 && state.edges.length === 0
|
|
647
|
+
? { nodes: [], edges: [], message: 'No diagram loaded yet.' }
|
|
648
|
+
: state, null, 2),
|
|
649
|
+
},
|
|
650
|
+
],
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
case 'update_diagram': {
|
|
654
|
+
const input = UpdateDiagramInputSchema.parse(args);
|
|
655
|
+
const result = await updateDiagram(input);
|
|
656
|
+
if (result.success) {
|
|
657
|
+
const { setDiagramState } = await import('./lib/diagram-state.js');
|
|
658
|
+
setDiagramState({ nodes: result.nodes, edges: result.edges, sessionId: result.sessionId });
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
content: [
|
|
662
|
+
{
|
|
663
|
+
type: 'text',
|
|
664
|
+
text: JSON.stringify({
|
|
665
|
+
success: result.success,
|
|
666
|
+
message: result.message,
|
|
667
|
+
error: result.error,
|
|
668
|
+
changes: result.changes,
|
|
669
|
+
diagramUrl: result.diagramUrl,
|
|
670
|
+
sessionId: result.sessionId,
|
|
671
|
+
note: "Raw nodes and edges omitted for brevity."
|
|
672
|
+
}, null, 2),
|
|
673
|
+
},
|
|
674
|
+
],
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
case 'validate_diagram': {
|
|
678
|
+
const result = await validateDiagram();
|
|
679
|
+
return {
|
|
680
|
+
content: [
|
|
681
|
+
{
|
|
682
|
+
type: 'text',
|
|
683
|
+
text: JSON.stringify(result, null, 2),
|
|
684
|
+
},
|
|
685
|
+
],
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
case 'save_checkpoint': {
|
|
689
|
+
const input = SaveCheckpointInputSchema.parse(args);
|
|
690
|
+
const result = await saveCheckpoint(input);
|
|
691
|
+
return {
|
|
692
|
+
content: [
|
|
693
|
+
{
|
|
694
|
+
type: 'text',
|
|
695
|
+
text: JSON.stringify(result, null, 2),
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
case 'load_checkpoint': {
|
|
701
|
+
const input = LoadCheckpointInputSchema.parse(args);
|
|
702
|
+
const result = await loadCheckpoint(input);
|
|
703
|
+
return {
|
|
704
|
+
content: [
|
|
705
|
+
{
|
|
706
|
+
type: 'text',
|
|
707
|
+
text: JSON.stringify(result, null, 2),
|
|
708
|
+
},
|
|
709
|
+
],
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
case 'export_diagram': {
|
|
713
|
+
const input = ExportDiagramInputSchema.parse(args);
|
|
714
|
+
const result = await exportDiagram(input);
|
|
715
|
+
return {
|
|
716
|
+
content: [
|
|
717
|
+
{
|
|
718
|
+
type: 'text',
|
|
719
|
+
text: JSON.stringify(result, null, 2),
|
|
720
|
+
},
|
|
721
|
+
],
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
default:
|
|
725
|
+
return {
|
|
726
|
+
content: [
|
|
727
|
+
{
|
|
728
|
+
type: 'text',
|
|
729
|
+
text: `Unknown tool: ${name}`,
|
|
730
|
+
},
|
|
731
|
+
],
|
|
732
|
+
isError: true,
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
return {
|
|
738
|
+
content: [
|
|
739
|
+
{
|
|
740
|
+
type: 'text',
|
|
741
|
+
text: error instanceof Error ? error.message : String(error),
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
isError: true,
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
async run() {
|
|
750
|
+
const transport = new StdioServerTransport();
|
|
751
|
+
await this.server.connect(transport);
|
|
752
|
+
console.error('ArchDraw MCP server running on stdio');
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const server = new ArchDrawMCPServer();
|
|
756
|
+
server.run().catch(console.error);
|
|
757
|
+
//# sourceMappingURL=index.js.map
|