Skip to content

Commit 58282f9

Browse files
authored
fix(calm-suite): correct read_calm_guide relationship example and expand MCP docs (finos#2687)
1 parent 8c29e18 commit 58282f9

2 files changed

Lines changed: 87 additions & 8 deletions

File tree

calm-suite/calm-studio/packages/mcp-server/src/tools/guide.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,13 @@ const CALM_GUIDE = `
8080
"relationships": [
8181
{
8282
"unique-id": "browser-to-api",
83-
"relationship-type": "connects",
84-
"source": "user-browser",
85-
"destination": "api-server",
83+
"relationship-type": { "connects": { "source": { "node": "user-browser" }, "destination": { "node": "api-server" } } },
8684
"protocol": "HTTPS",
8785
"description": "User requests via HTTPS"
8886
},
8987
{
9088
"unique-id": "api-to-db",
91-
"relationship-type": "connects",
92-
"source": "api-server",
93-
"destination": "postgres-db",
89+
"relationship-type": { "connects": { "source": { "node": "api-server" }, "destination": { "node": "postgres-db" } } },
9490
"protocol": "TCP",
9591
"description": "API persists data to PostgreSQL"
9692
}
@@ -107,7 +103,7 @@ const CALM_GUIDE = `
107103
5. **Use render_diagram** to visualize — returns SVG with color-coded node types.
108104
6. **Use describe_architecture** to get a text summary of all nodes and relationships.
109105
7. Every node needs a globally unique \`unique-id\` (kebab-case recommended).
110-
8. Relationships reference nodes by their \`unique-id\` in \`source\` and \`destination\`.
106+
8. \`relationship-type\` is an **object** keyed by variant (\`connects\`, \`interacts\`, \`composed-of\`, \`deployed-in\`, \`options\`) — never a plain string. Each variant has its own nested structure (e.g. \`connects\` wraps \`source\`/\`destination\` as \`{ node, interfaces? }\` objects).
111107
`.trim();
112108

113109
// ---------------------------------------------------------------------------

docs/docs/working-with-calm/calm-studio.md

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,87 @@ Import a CALM JSON file to start from an existing architecture (e.g., one genera
124124

125125
## MCP Server Integration
126126

127-
CALM Studio ships a standalone MCP server (`@calmstudio/mcp-server`) that lets AI tools like Claude Code and GitHub Copilot create and modify CALM architectures programmatically. The server exposes tools covering node CRUD, relationship management, rendering, and validation.
127+
CALM Studio ships a standalone MCP server (`@calmstudio/mcp`) that lets AI tools like Claude Code and GitHub Copilot create and modify CALM architectures programmatically. The server exposes 20 tools covering node CRUD, relationship management, rendering, and validation.
128+
129+
### Recommended workflow
130+
131+
Always call `read_calm_guide` before creating nodes or relationships. It returns the full node-type vocabulary and relationship forms that the other tools enforce.
132+
133+
```
134+
1. read_calm_guide() ← node types, relationship forms, usage tips
135+
2. read_calm_guide(topic="arb-conversion") ← AI architecture mapping table (optional)
136+
3. create_architecture(file, nodes, relationships)
137+
4. validate_architecture(file) ← fix errors before continuing
138+
5. finalize_architecture(file) ← validates + attaches AIGF if AI nodes present
139+
6. export_calm(file, destination)
140+
```
141+
142+
### Relationship form — nested object, not a string
143+
144+
`relationship-type` is an **object** keyed by variant. This is enforced by the CALM 1.2 schema and by `validate_architecture`. The flat string form (`"relationship-type": "connects"`) is invalid and will be rejected.
145+
146+
**connects** — point-to-point communication:
147+
148+
```json
149+
{
150+
"unique-id": "api-to-db",
151+
"relationship-type": {
152+
"connects": {
153+
"source": { "node": "api-service" },
154+
"destination": { "node": "postgres-db" }
155+
}
156+
},
157+
"protocol": "JDBC"
158+
}
159+
```
160+
161+
**composed-of** — structural containment:
162+
163+
```json
164+
{
165+
"unique-id": "platform-composed-of-services",
166+
"relationship-type": {
167+
"composed-of": {
168+
"container": "platform",
169+
"nodes": ["auth-service", "api-service"]
170+
}
171+
}
172+
}
173+
```
174+
175+
**interacts** — actor to system:
176+
177+
```json
178+
{
179+
"unique-id": "user-interacts-app",
180+
"relationship-type": {
181+
"interacts": {
182+
"actor": "end-user",
183+
"nodes": ["web-frontend"]
184+
}
185+
}
186+
}
187+
```
188+
189+
**deployed-in** — deployment containment:
190+
191+
```json
192+
{
193+
"unique-id": "service-in-cluster",
194+
"relationship-type": {
195+
"deployed-in": {
196+
"container": "k8s-cluster",
197+
"nodes": ["api-service"]
198+
}
199+
}
200+
}
201+
```
202+
203+
### Common mistakes
204+
205+
| Mistake | Fix |
206+
|---|---|
207+
| `"relationship-type": "connects"` (string) | Use nested object: `{ "connects": { "source": ..., "destination": ... } }` |
208+
| `"source": "node-id"` as a sibling key | Move inside variant: `"connects": { "source": { "node": "node-id" } }` |
209+
| Adding relationships before nodes | `add_relationship` validates refs — add nodes first |
210+
| `export_calm` before `finalize_architecture` | Always finalize first; it runs final validation |

0 commit comments

Comments
 (0)