living-documentation 7.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/LICENSE +661 -0
- package/README.md +329 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +62 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/src/frontend/admin.html +1073 -0
- package/dist/src/frontend/annotations.js +546 -0
- package/dist/src/frontend/boot.js +90 -0
- package/dist/src/frontend/config.js +19 -0
- package/dist/src/frontend/dark-mode.js +20 -0
- package/dist/src/frontend/diagram/alignment.js +161 -0
- package/dist/src/frontend/diagram/clipboard.js +172 -0
- package/dist/src/frontend/diagram/constants.js +109 -0
- package/dist/src/frontend/diagram/debug.js +43 -0
- package/dist/src/frontend/diagram/edge-panel.js +260 -0
- package/dist/src/frontend/diagram/edge-rendering.js +12 -0
- package/dist/src/frontend/diagram/grid.js +78 -0
- package/dist/src/frontend/diagram/groups.js +102 -0
- package/dist/src/frontend/diagram/history.js +153 -0
- package/dist/src/frontend/diagram/image-name-modal.js +48 -0
- package/dist/src/frontend/diagram/image-upload.js +36 -0
- package/dist/src/frontend/diagram/label-editor.js +115 -0
- package/dist/src/frontend/diagram/link-panel.js +144 -0
- package/dist/src/frontend/diagram/main.js +299 -0
- package/dist/src/frontend/diagram/network.js +1473 -0
- package/dist/src/frontend/diagram/node-panel.js +267 -0
- package/dist/src/frontend/diagram/node-rendering.js +773 -0
- package/dist/src/frontend/diagram/persistence.js +161 -0
- package/dist/src/frontend/diagram/ports.js +386 -0
- package/dist/src/frontend/diagram/selection-overlay.js +336 -0
- package/dist/src/frontend/diagram/state.js +39 -0
- package/dist/src/frontend/diagram/t.js +3 -0
- package/dist/src/frontend/diagram/toast.js +21 -0
- package/dist/src/frontend/diagram/unlock-hold.js +182 -0
- package/dist/src/frontend/diagram/zoom.js +20 -0
- package/dist/src/frontend/diagram-link-modal.js +137 -0
- package/dist/src/frontend/diagram.html +1279 -0
- package/dist/src/frontend/documents.js +373 -0
- package/dist/src/frontend/export.js +338 -0
- package/dist/src/frontend/i18n/en.json +406 -0
- package/dist/src/frontend/i18n/fr.json +406 -0
- package/dist/src/frontend/i18n.js +32 -0
- package/dist/src/frontend/image-paste.js +101 -0
- package/dist/src/frontend/index.html +2314 -0
- package/dist/src/frontend/misc.js +25 -0
- package/dist/src/frontend/new-doc-modal.js +260 -0
- package/dist/src/frontend/new-folder-modal.js +174 -0
- package/dist/src/frontend/search.js +157 -0
- package/dist/src/frontend/sidebar-helpers.js +58 -0
- package/dist/src/frontend/sidebar.js +182 -0
- package/dist/src/frontend/snippet-detect.js +25 -0
- package/dist/src/frontend/snippet-table.js +85 -0
- package/dist/src/frontend/snippet-tree.js +94 -0
- package/dist/src/frontend/snippets.js +534 -0
- package/dist/src/frontend/state.js +28 -0
- package/dist/src/frontend/utils.js +21 -0
- package/dist/src/frontend/vendor/wordcloud2.js +1187 -0
- package/dist/src/frontend/wordcloud.js +693 -0
- package/dist/src/lib/config.d.ts +17 -0
- package/dist/src/lib/config.d.ts.map +1 -0
- package/dist/src/lib/config.js +79 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/parser.d.ts +11 -0
- package/dist/src/lib/parser.d.ts.map +1 -0
- package/dist/src/lib/parser.js +111 -0
- package/dist/src/lib/parser.js.map +1 -0
- package/dist/src/mcp/server.d.ts +3 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +986 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tools/diagrams.d.ts +44 -0
- package/dist/src/mcp/tools/diagrams.d.ts.map +1 -0
- package/dist/src/mcp/tools/diagrams.js +245 -0
- package/dist/src/mcp/tools/diagrams.js.map +1 -0
- package/dist/src/mcp/tools/documents.d.ts +26 -0
- package/dist/src/mcp/tools/documents.d.ts.map +1 -0
- package/dist/src/mcp/tools/documents.js +127 -0
- package/dist/src/mcp/tools/documents.js.map +1 -0
- package/dist/src/mcp/tools/source.d.ts +29 -0
- package/dist/src/mcp/tools/source.d.ts.map +1 -0
- package/dist/src/mcp/tools/source.js +200 -0
- package/dist/src/mcp/tools/source.js.map +1 -0
- package/dist/src/routes/annotations.d.ts +3 -0
- package/dist/src/routes/annotations.d.ts.map +1 -0
- package/dist/src/routes/annotations.js +83 -0
- package/dist/src/routes/annotations.js.map +1 -0
- package/dist/src/routes/browse.d.ts +3 -0
- package/dist/src/routes/browse.d.ts.map +1 -0
- package/dist/src/routes/browse.js +75 -0
- package/dist/src/routes/browse.js.map +1 -0
- package/dist/src/routes/config.d.ts +3 -0
- package/dist/src/routes/config.d.ts.map +1 -0
- package/dist/src/routes/config.js +97 -0
- package/dist/src/routes/config.js.map +1 -0
- package/dist/src/routes/diagrams.d.ts +3 -0
- package/dist/src/routes/diagrams.d.ts.map +1 -0
- package/dist/src/routes/diagrams.js +69 -0
- package/dist/src/routes/diagrams.js.map +1 -0
- package/dist/src/routes/documents.d.ts +8 -0
- package/dist/src/routes/documents.d.ts.map +1 -0
- package/dist/src/routes/documents.js +332 -0
- package/dist/src/routes/documents.js.map +1 -0
- package/dist/src/routes/export.d.ts +3 -0
- package/dist/src/routes/export.d.ts.map +1 -0
- package/dist/src/routes/export.js +277 -0
- package/dist/src/routes/export.js.map +1 -0
- package/dist/src/routes/images.d.ts +3 -0
- package/dist/src/routes/images.d.ts.map +1 -0
- package/dist/src/routes/images.js +49 -0
- package/dist/src/routes/images.js.map +1 -0
- package/dist/src/routes/wordcloud.d.ts +3 -0
- package/dist/src/routes/wordcloud.d.ts.map +1 -0
- package/dist/src/routes/wordcloud.js +95 -0
- package/dist/src/routes/wordcloud.js.map +1 -0
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +76 -0
- package/dist/src/server.js.map +1 -0
- package/dist/starting-doc/.annotations.json +3 -0
- package/dist/starting-doc/.diagrams.json +1884 -0
- package/dist/starting-doc/.living-doc.json +39 -0
- package/dist/starting-doc/1_tutorial/2026_04_11_13_25_[General]_crer_vos_dossiers.md +16 -0
- package/dist/starting-doc/1_tutorial/2026_04_11_18_58_[General]_creer_un_document_dans_un_dossier.md +9 -0
- package/dist/starting-doc/1_tutorial/2026_04_12_09_00_[General]_editer_et_sauvegarder.md +39 -0
- package/dist/starting-doc/1_tutorial/2026_04_12_10_00_[General]_utiliser_les_snippets.md +71 -0
- package/dist/starting-doc/2026_04_08_20_52_[General]_welcome.md +17 -0
- package/dist/starting-doc/2026_04_11_12_55_[General]_premiers_pas.md +271 -0
- package/dist/starting-doc/2_guide/2026_04_08_00_04_[DOCUMENT]_utilisation_des_images_plein_ecran_lien_clickable.md +40 -0
- package/dist/starting-doc/2_guide/2026_04_08_23_38_[Configuration]_demarrage_de_living_documentation.md +32 -0
- package/dist/starting-doc/2_guide/2026_04_09_09_00_[NAVIGATION]_recherche_plein_texte.md +65 -0
- package/dist/starting-doc/2_guide/2026_04_09_10_00_[EXPORT]_exporter_en_pdf.md +43 -0
- package/dist/starting-doc/2_guide/2026_04_09_11_00_[Configuration]_configurer_le_panneau_admin.md +55 -0
- package/dist/starting-doc/2_guide/2026_04_09_12_00_[Configuration]_extra_files.md +68 -0
- package/dist/starting-doc/2_guide/2026_04_09_13_00_[WORDCLOUD]_word_cloud.md +54 -0
- package/dist/starting-doc/2_guide/2026_04_09_14_00_[DIAGRAM]_creer_et_lier_un_diagramme.md +77 -0
- package/dist/starting-doc/3_concept/2026_04_08_20_58_[DOCUMENTING]_ADRS.md +20 -0
- package/dist/starting-doc/3_concept/2026_04_08_22_15_[DOCUMENTING]_living_documentation.md +17 -0
- package/dist/starting-doc/3_concept/2026_04_08_22_46_[METHODOLOGY]_diataxis_architecture_du_contenu.md +16 -0
- package/dist/starting-doc/4_reference/2026_04_08_23_14_[FUNDAMENTALS]_the_living_documentation_tool.md +41 -0
- package/dist/starting-doc/4_reference/2026_04_09_01_00_[REFERENCE]_raccourcis_clavier.md +61 -0
- package/dist/starting-doc/4_reference/2026_04_09_02_00_[REFERENCE]_tokens_pattern_nommage.md +75 -0
- package/dist/starting-doc/4_reference/2026_04_09_03_00_[REFERENCE]_types_de_snippets.md +68 -0
- package/dist/starting-doc/4_reference/2026_04_11_17_31_[FUNDAMENTALS]_architecturer_une_documentation.md +12 -0
- package/dist/starting-doc/4_reference/2026_04_12_14_07_[FUNDAMENTALS]_dossiers_et_catgories.md +89 -0
- package/dist/starting-doc/images/admin_screenshot.png +0 -0
- package/dist/starting-doc/images/ajout-document.png +0 -0
- package/dist/starting-doc/images/ajouter-document-categorie.png +0 -0
- package/dist/starting-doc/images/ajouter_un_document_dans_un_dossier.png +0 -0
- package/dist/starting-doc/images/architecturer_une_documentation_reference.png +0 -0
- package/dist/starting-doc/images/cr_er_un_document.png +0 -0
- package/dist/starting-doc/images/creation-nouveau-dossier.png +0 -0
- package/dist/starting-doc/images/creer-document-context-engineering.png +0 -0
- package/dist/starting-doc/images/creer-dossier-only-tutoriel.png +0 -0
- package/dist/starting-doc/images/creer-dossier-tutoriel.png +0 -0
- package/dist/starting-doc/images/creer-dossiers-done.png +0 -0
- package/dist/starting-doc/images/creer-un-document.png +0 -0
- package/dist/starting-doc/images/creer-vos-dossiers-tutoriel.png +0 -0
- package/dist/starting-doc/images/creer-vos-dossiers.png +0 -0
- package/dist/starting-doc/images/decouverte_adrs.png +0 -0
- package/dist/starting-doc/images/diataxis.png +0 -0
- package/dist/starting-doc/images/diataxis_callout.png +0 -0
- package/dist/starting-doc/images/document-cree.png +0 -0
- package/dist/starting-doc/images/liens_snippets.png +0 -0
- package/dist/starting-doc/images/living_documentation.png +0 -0
- package/dist/starting-doc/images/npm_logo.png +0 -0
- package/dist/starting-doc/images/popup-creer-document.png +0 -0
- package/dist/starting-doc/images/popup-creer-dossier.png +0 -0
- package/dist/starting-doc/images/popup-dossier-cree.png +0 -0
- package/dist/starting-doc/images/quatre-dossiers-crees.png +0 -0
- package/dist/starting-doc/images/screenshot-living-doc.png +0 -0
- package/dist/starting-doc/images/the_living_documentation_tool.png +0 -0
- package/package.json +49 -0
|
@@ -0,0 +1,986 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mcpRouter = mcpRouter;
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const express_1 = require("express");
|
|
8
|
+
const documents_1 = require("./tools/documents");
|
|
9
|
+
const diagrams_1 = require("./tools/diagrams");
|
|
10
|
+
const source_1 = require("./tools/source");
|
|
11
|
+
// ── Server guide ──────────────────────────────────────────────────────────────
|
|
12
|
+
// Shared by the `instructions` field (sent on MCP initialize) and the
|
|
13
|
+
// `get_server_guide` tool (explicit retrieval for clients that don't surface
|
|
14
|
+
// server instructions to the model).
|
|
15
|
+
const SERVER_GUIDE = `# Living Documentation — Server Guide
|
|
16
|
+
|
|
17
|
+
This server maintains a living documentation system composed of:
|
|
18
|
+
- **Documents** (Markdown) — the source of truth.
|
|
19
|
+
- **Diagrams** — visual derivations of documents.
|
|
20
|
+
|
|
21
|
+
## Document ↔ diagram contract
|
|
22
|
+
Documents are authoritative. Diagrams are derived views and must not introduce
|
|
23
|
+
information that is absent from the documents. If a diagram needs a concept
|
|
24
|
+
that isn't documented yet, create or update the document first.
|
|
25
|
+
|
|
26
|
+
## Default diagram scope
|
|
27
|
+
- When documenting the project big picture, generate a **context diagram**.
|
|
28
|
+
- Do NOT generate container diagrams, component diagrams, or UML diagrams
|
|
29
|
+
unless the user explicitly asks for them by name.
|
|
30
|
+
- If the user asks for "a diagram", "the big picture", or "documentation",
|
|
31
|
+
produce a context diagram.
|
|
32
|
+
|
|
33
|
+
## Mandatory workflow before creating or updating any diagram
|
|
34
|
+
1. Call \`list_documents\` to see what exists.
|
|
35
|
+
2. Call \`read_document\` on the documents relevant to the requested diagram.
|
|
36
|
+
3. Call \`list_diagrams\` to check whether the diagram already exists
|
|
37
|
+
(update rather than duplicate by passing its \`id\` back to \`create_diagram\`).
|
|
38
|
+
4. Only then call \`create_diagram\`, using node/edge content grounded in the
|
|
39
|
+
documents you read.
|
|
40
|
+
|
|
41
|
+
Never invent actors, systems, or relationships that are not present in the
|
|
42
|
+
documents.
|
|
43
|
+
|
|
44
|
+
## Conventions by diagram type
|
|
45
|
+
### Context diagram (default)
|
|
46
|
+
- Central system as \`box\` (c-blue).
|
|
47
|
+
- Users / roles as \`actor\` (c-gray).
|
|
48
|
+
- External systems as \`box\` (c-slate).
|
|
49
|
+
- Persistence / datastores as \`database\` (c-teal).
|
|
50
|
+
- Keep to ~10 nodes maximum.
|
|
51
|
+
|
|
52
|
+
### Container diagram (explicit request only)
|
|
53
|
+
- Each deployable unit as \`box\`.
|
|
54
|
+
- Databases as \`database\`.
|
|
55
|
+
- Queues as \`ellipse\`.
|
|
56
|
+
|
|
57
|
+
### UML diagram (explicit request only)
|
|
58
|
+
- Follow the requested UML variant's conventions (class, sequence, state,
|
|
59
|
+
activity, use-case …).
|
|
60
|
+
|
|
61
|
+
### Screen-guide diagram (explicit request only)
|
|
62
|
+
An annotated screenshot built in **three layers**. Source code is the reference
|
|
63
|
+
(not the Markdown docs) — use \`read_source_file\` / \`search_source\`.
|
|
64
|
+
|
|
65
|
+
**1. Background image** — one \`image\` node with the screenshot.
|
|
66
|
+
- \`name: "screenshot"\` (used as edge anchor; not displayed).
|
|
67
|
+
- \`imageSrc\`: URL returned by \`POST /api/images/upload\`.
|
|
68
|
+
- \`width\` / \`height\` = natural screenshot pixels. \`locked: true\`.
|
|
69
|
+
|
|
70
|
+
**2. Zone overlays** — one translucent \`box\` per major layout region
|
|
71
|
+
(left/right sidebar, top bar, main content, footer …).
|
|
72
|
+
- \`bgOpacity: 0.15–0.20\`, \`locked: true\`, empty label.
|
|
73
|
+
- \`width\` / \`height\` / \`x\` / \`y\` cover the zone on the screenshot.
|
|
74
|
+
- One distinct \`color\` per zone (e.g. c-red = left drawer, c-amber = top bar,
|
|
75
|
+
c-cyan = main area). Typical count: **2–5 zones**.
|
|
76
|
+
- Each zone gets a **zone-label post-it** of the **same color**, placed inside
|
|
77
|
+
or at the edge of the zone (1–3 words: "Top Bar", "Collapsible Drawer",
|
|
78
|
+
"Main Page").
|
|
79
|
+
|
|
80
|
+
**3. Feature callouts** — one \`post-it\` per first-level feature, placed
|
|
81
|
+
**outside the screenshot** and linked to the UI element by a free-end arrow.
|
|
82
|
+
- First-level feature = visible without interaction + changes behavior
|
|
83
|
+
significantly when used. Typical count: **4–10**.
|
|
84
|
+
- Label: 2–5 words, title-cased; multi-line allowed via \`\\n\`.
|
|
85
|
+
- Color depends on kind:
|
|
86
|
+
- **Interactive** (button, link, input, toggle) → \`c-amber\` or
|
|
87
|
+
\`c-orange\` (yellow family). **Default.**
|
|
88
|
+
- **Differentiating** (product-distinguishing feature) → a distinct
|
|
89
|
+
non-yellow color (\`c-purple\`, \`c-rose\`, \`c-red\`, \`c-sky\`,
|
|
90
|
+
\`c-teal\`, \`c-green\`). Reserve for the 1–3 hero features.
|
|
91
|
+
|
|
92
|
+
#### Free-end arrows — never anchor on the image node
|
|
93
|
+
Anchoring on the image makes every arrow converge to its centre. Use one of:
|
|
94
|
+
- **\`anchor\` node** (8×8, invisible at rest, visible on hover) placed on the
|
|
95
|
+
target pixel inside the screenshot, with edge
|
|
96
|
+
\`{ from: "<post-it>", to: "<anchor name>" }\`. **Preferred.**
|
|
97
|
+
- **Edge with \`from\` only (no \`to\`)** — renders a floating arrow
|
|
98
|
+
endpoint the user can drag onto the target.
|
|
99
|
+
|
|
100
|
+
Edge labels stay empty on this diagram type — the arrow alone speaks. Missing-
|
|
101
|
+
label warnings are disabled for screen-guide.
|
|
102
|
+
|
|
103
|
+
### Edges
|
|
104
|
+
- Every edge MUST have a \`label\` describing the interaction as a verb phrase
|
|
105
|
+
("authenticates", "publishes events to", "reads from", "sends notifications via").
|
|
106
|
+
- Exception: screen-guide diagrams may have unlabeled edges.
|
|
107
|
+
|
|
108
|
+
## Node label format (C4 convention)
|
|
109
|
+
Use \`\\n\` line breaks:
|
|
110
|
+
\`\`\`
|
|
111
|
+
Name\\n[Type]\\nShort description of role or responsibility
|
|
112
|
+
\`\`\`
|
|
113
|
+
Types: \`[Person]\`, \`[Software System]\`, \`[External System]\`, \`[Database]\`, \`[Device]\`.
|
|
114
|
+
Keep descriptions to 1–2 short lines.
|
|
115
|
+
|
|
116
|
+
## Coordinate system (when positions are provided)
|
|
117
|
+
- Origin \`(0, 0)\` is the canvas center.
|
|
118
|
+
- \`+x\` is right, \`+y\` is down.
|
|
119
|
+
- Use multiples of **40** for grid alignment.
|
|
120
|
+
- \`x\` and \`y\` are **optional**: omit them to let the editor auto-lay out
|
|
121
|
+
nodes. Only provide coordinates when you want a fixed layout (e.g., following
|
|
122
|
+
a C4 convention).
|
|
123
|
+
- **Screen-guide exception**: positions align to screenshot pixels (and
|
|
124
|
+
anchors to target pixels), not to the 40-unit grid.
|
|
125
|
+
|
|
126
|
+
## Source code access (fallback only)
|
|
127
|
+
Three tools expose read-only access to the project source under \`sourceRoot\`
|
|
128
|
+
(configurable in \`.living-doc.json\`; defaults to the parent folder of
|
|
129
|
+
\`docsFolder\`):
|
|
130
|
+
|
|
131
|
+
- \`list_source_files(pattern?, maxResults?)\`
|
|
132
|
+
- \`read_source_file(path)\`
|
|
133
|
+
- \`search_source(query, pattern?, maxResults?, caseSensitive?)\`
|
|
134
|
+
|
|
135
|
+
**Rules**:
|
|
136
|
+
1. Documentation tools come first. Use source tools only when the docs do not
|
|
137
|
+
carry the required detail (typical case: screen-guide diagrams, or
|
|
138
|
+
low-level code documentation with no ADR).
|
|
139
|
+
2. If you find yourself reading more than 3 source files for the same
|
|
140
|
+
diagram, stop and update the documentation first.
|
|
141
|
+
3. Common ignored folders (\`node_modules\`, \`dist\`, \`.git\`, \`build\`,
|
|
142
|
+
\`target\`, …) are skipped automatically.
|
|
143
|
+
|
|
144
|
+
## Guardrails (enforced server-side in create_diagram)
|
|
145
|
+
- \`diagramType\` is required.
|
|
146
|
+
- Non-context types (\`container\`, \`component\`, \`uml\`, \`screen-guide\`) are
|
|
147
|
+
rejected unless \`userRequestedExplicitly: true\` is also passed.
|
|
148
|
+
- \`image\` nodes without \`imageSrc\` are rejected.
|
|
149
|
+
- A response \`warnings\` array flags missing edge labels (except for
|
|
150
|
+
screen-guide) or oversized context diagrams.
|
|
151
|
+
`;
|
|
152
|
+
// ── Tool definitions ──────────────────────────────────────────────────────────
|
|
153
|
+
const SHAPE_LIST = 'box, actor (person), database, ellipse, circle, post-it, text-free, image, anchor (invisible endpoint for free-end arrows — screen-guide only)';
|
|
154
|
+
const COLOR_LIST = 'c-blue, c-green, c-gray, c-teal, c-amber, c-orange, c-rose, c-purple, c-cyan, c-indigo, c-pink, c-lime, c-red, c-sky, c-slate (short aliases like "blue", "teal" also work)';
|
|
155
|
+
const GUIDE_HINT = 'If unsure of the workflow, call `get_server_guide` first.';
|
|
156
|
+
const CREATE_DIAGRAM_DESCRIPTION = [
|
|
157
|
+
'Create or overwrite a diagram from a high-level description.',
|
|
158
|
+
'',
|
|
159
|
+
'## Required workflow (do ALL of these before calling)',
|
|
160
|
+
'1. `list_documents` — see what exists.',
|
|
161
|
+
'2. `read_document` on documents relevant to the diagram.',
|
|
162
|
+
'3. `list_diagrams` — if the diagram already exists, pass its `id` back to update in place (do not duplicate).',
|
|
163
|
+
'Do not invent actors, systems, or relationships absent from the documents.',
|
|
164
|
+
'',
|
|
165
|
+
'## Scope rule',
|
|
166
|
+
'The default diagram for a project is a **context diagram**. Container, component, and UML diagrams are produced ONLY when the user explicitly requests them by name. If the user asks for "a diagram", "the big picture", or "documentation", produce a context diagram.',
|
|
167
|
+
'',
|
|
168
|
+
'## Conventions by diagram type',
|
|
169
|
+
'- Context (default): central system as `box` (c-blue); users as `actor` (c-gray); external systems as `box` (c-slate); datastores as `database` (c-teal). Max ~10 nodes.',
|
|
170
|
+
'- Container (explicit-only): deployables as `box`, databases as `database`, queues as `ellipse`.',
|
|
171
|
+
'- UML (explicit-only): follow the requested UML variant (class, sequence, state, …).',
|
|
172
|
+
'- Every edge MUST have a `label` describing the interaction as a verb phrase ("authenticates", "publishes events to", "reads from").',
|
|
173
|
+
'',
|
|
174
|
+
'## Source-of-truth contract',
|
|
175
|
+
'Documents are authoritative. A diagram must not contain information absent from the documents. If a diagram needs a concept that isn\'t documented, create or update the document first (via `create_document`).',
|
|
176
|
+
'',
|
|
177
|
+
'## Positioning',
|
|
178
|
+
'`x` and `y` are **optional**. Omit them and the editor auto-lays out nodes. Provide coordinates only when a fixed layout is required (e.g., following a C4 convention). When provided: origin `(0,0)` is the canvas center, `+x` = right, `+y` = down; use multiples of 40.',
|
|
179
|
+
'',
|
|
180
|
+
'## Guardrails (enforced)',
|
|
181
|
+
'- `diagramType` is required.',
|
|
182
|
+
'- For `container`, `component`, or `uml`, `userRequestedExplicitly: true` is required — confirms the user asked for that type by name. Otherwise the call is rejected.',
|
|
183
|
+
'- Missing edge labels and oversized context diagrams produce warnings.',
|
|
184
|
+
'',
|
|
185
|
+
'## Worked example (context diagram, derived from an ADR)',
|
|
186
|
+
'```json',
|
|
187
|
+
'{',
|
|
188
|
+
' "diagramType": "context",',
|
|
189
|
+
' "title": "Living Documentation — system context",',
|
|
190
|
+
' "nodes": [',
|
|
191
|
+
' { "name": "Living Documentation\\n[Software System]\\nServes Markdown docs\\nand diagrams", "type": "box", "color": "c-blue" },',
|
|
192
|
+
' { "name": "Developer\\n[Person]\\nBrowses and edits\\nproject docs", "type": "actor", "color": "c-gray" },',
|
|
193
|
+
' { "name": "Local filesystem\\n[Datastore]\\nHosts .md files and\\ndiagrams.json", "type": "database","color": "c-teal" }',
|
|
194
|
+
' ],',
|
|
195
|
+
' "edges": [',
|
|
196
|
+
' { "from": "Developer\\n[Person]\\nBrowses and edits\\nproject docs", "to": "Living Documentation\\n[Software System]\\nServes Markdown docs\\nand diagrams", "label": "reads and edits docs via" },',
|
|
197
|
+
' { "from": "Living Documentation\\n[Software System]\\nServes Markdown docs\\nand diagrams", "to": "Local filesystem\\n[Datastore]\\nHosts .md files and\\ndiagrams.json", "label": "reads from / writes to" }',
|
|
198
|
+
' ]',
|
|
199
|
+
'}',
|
|
200
|
+
'```',
|
|
201
|
+
'',
|
|
202
|
+
`## Available shapes and colors`,
|
|
203
|
+
`Shapes: ${SHAPE_LIST}.`,
|
|
204
|
+
`Colors: ${COLOR_LIST}.`,
|
|
205
|
+
'',
|
|
206
|
+
GUIDE_HINT,
|
|
207
|
+
].join('\n');
|
|
208
|
+
const CREATE_DOCUMENT_DESCRIPTION = [
|
|
209
|
+
'Create a new Markdown document. The filename is generated automatically from the configured pattern (date + category + title slug). Pass `content` as full Markdown; omit to create an empty stub.',
|
|
210
|
+
'',
|
|
211
|
+
'## Source-of-truth contract',
|
|
212
|
+
'Documents are the source of truth. Diagrams are derived views. If a diagram needs a concept that isn\'t documented, create or update the document first (here) before calling `create_diagram`.',
|
|
213
|
+
'',
|
|
214
|
+
'## Worked example',
|
|
215
|
+
'```json',
|
|
216
|
+
'{',
|
|
217
|
+
' "title": "Payment system context",',
|
|
218
|
+
' "category": "Architecture",',
|
|
219
|
+
' "folder": "adrs",',
|
|
220
|
+
' "content": "# Payment system context\\n\\n**status:** Accepted\\n**tags:** context, payment\\n\\nThe system integrates with Stripe for card capture and pre-authorization..."',
|
|
221
|
+
'}',
|
|
222
|
+
'```',
|
|
223
|
+
'',
|
|
224
|
+
GUIDE_HINT,
|
|
225
|
+
].join('\n');
|
|
226
|
+
const TOOLS = [
|
|
227
|
+
{
|
|
228
|
+
name: 'get_server_guide',
|
|
229
|
+
description: 'Return the living-documentation server guide: purpose, mandatory workflow, scope rules (context vs container/UML), diagram conventions, node/edge format, and coordinate system. Call this first whenever you are unsure how to use the server.',
|
|
230
|
+
inputSchema: { type: 'object', properties: {} },
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: 'list_documents',
|
|
234
|
+
description: `List all documents with their id, title, category, and folder. Documents are the source of truth — read them before creating or updating any diagram. ${GUIDE_HINT}`,
|
|
235
|
+
inputSchema: { type: 'object', properties: {} },
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: 'read_document',
|
|
239
|
+
description: `Read the raw Markdown content of a document by its id. Use this to gather facts (actors, systems, flows) before creating a diagram. Ignore documents whose frontmatter contains \`status: SuperSeeded\`. ${GUIDE_HINT}`,
|
|
240
|
+
inputSchema: {
|
|
241
|
+
type: 'object',
|
|
242
|
+
properties: {
|
|
243
|
+
id: { type: 'string', description: 'Document id as returned by list_documents' },
|
|
244
|
+
},
|
|
245
|
+
required: ['id'],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'create_document',
|
|
250
|
+
description: CREATE_DOCUMENT_DESCRIPTION,
|
|
251
|
+
inputSchema: {
|
|
252
|
+
type: 'object',
|
|
253
|
+
properties: {
|
|
254
|
+
title: { type: 'string', description: 'Human-readable document title' },
|
|
255
|
+
category: { type: 'string', description: 'Category extracted from the filename, e.g. "Architecture", "Guide"' },
|
|
256
|
+
folder: { type: 'string', description: 'Optional subfolder relative to the docs root, e.g. "adrs" or "adrs/backend"' },
|
|
257
|
+
content: { type: 'string', description: 'Full Markdown content. Omit to create an empty document.' },
|
|
258
|
+
},
|
|
259
|
+
required: ['title', 'category'],
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'list_diagrams',
|
|
264
|
+
description: `List all saved diagrams with their id and title. Always call this before \`create_diagram\` — if a relevant diagram already exists, pass its id back to \`create_diagram\` to update rather than duplicate. ${GUIDE_HINT}`,
|
|
265
|
+
inputSchema: { type: 'object', properties: {} },
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: 'read_diagram',
|
|
269
|
+
description: `Read the nodes and edges of an existing diagram by its id. Returns the diagram in the same format accepted by \`create_diagram\`, ready to be modified and passed back. ${GUIDE_HINT}`,
|
|
270
|
+
inputSchema: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: {
|
|
273
|
+
id: { type: 'string', description: 'Diagram id as returned by list_diagrams' },
|
|
274
|
+
},
|
|
275
|
+
required: ['id'],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'create_diagram',
|
|
280
|
+
description: CREATE_DIAGRAM_DESCRIPTION,
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
id: { type: 'string', description: 'Optional: existing diagram id to overwrite. If omitted, a new diagram is created.' },
|
|
285
|
+
title: { type: 'string', description: 'Diagram title' },
|
|
286
|
+
diagramType: {
|
|
287
|
+
type: 'string',
|
|
288
|
+
enum: ['context', 'container', 'component', 'uml', 'flow', 'erd', 'screen-guide', 'other'],
|
|
289
|
+
description: 'Type of diagram. "context" is the default. "container", "component", "uml", and "screen-guide" require explicit user request — set `userRequestedExplicitly: true` alongside them.',
|
|
290
|
+
},
|
|
291
|
+
userRequestedExplicitly: {
|
|
292
|
+
type: 'boolean',
|
|
293
|
+
description: 'Set to true only when the user explicitly asked for a container, component, UML, or screen-guide diagram by name. Required for those diagramType values; ignored for "context".',
|
|
294
|
+
},
|
|
295
|
+
nodes: {
|
|
296
|
+
type: 'array',
|
|
297
|
+
description: 'List of nodes. Node labels should follow the C4 convention: "Name\\n[Type]\\nShort description".',
|
|
298
|
+
items: {
|
|
299
|
+
type: 'object',
|
|
300
|
+
properties: {
|
|
301
|
+
name: { type: 'string', description: 'Node label shown in the diagram. Use \\n for line breaks. C4 format: "Name\\n[Type]\\nDescription". Empty string allowed for zone overlays, anchors, and the image background.' },
|
|
302
|
+
type: { type: 'string', description: `Shape type: ${SHAPE_LIST}.` },
|
|
303
|
+
color: { type: 'string', description: `Color key, e.g. c-blue or "blue". Available: ${COLOR_LIST}.` },
|
|
304
|
+
x: { type: 'number', description: 'Optional canvas X (0 = center). Omit to auto-lay out. When provided, use multiples of 40 (screen-guide exception: pixel-aligned).' },
|
|
305
|
+
y: { type: 'number', description: 'Optional canvas Y (0 = center, positive = down). Omit to auto-lay out. When provided, use multiples of 40 (screen-guide exception: pixel-aligned).' },
|
|
306
|
+
width: { type: 'number', description: 'Optional explicit node width in pixels. Required for image backgrounds and zone overlays in screen-guide diagrams. Otherwise estimated from the label.' },
|
|
307
|
+
height: { type: 'number', description: 'Optional explicit node height in pixels. Required for image backgrounds and zone overlays in screen-guide diagrams. Otherwise estimated from the label.' },
|
|
308
|
+
bgOpacity: { type: 'number', description: 'Optional background opacity (0–1). Use 0.15–0.20 for translucent zone-overlay boxes in screen-guide diagrams.' },
|
|
309
|
+
locked: { type: 'boolean', description: 'Optional: lock the node so it cannot be moved or resized by accident. Recommended for screen-guide backgrounds and zone overlays.' },
|
|
310
|
+
linkedDiagramId: { type: 'string', description: 'Optional: id of another diagram to navigate to when clicking this node (C4 drill-down).' },
|
|
311
|
+
imageSrc: { type: 'string', description: 'Required when `type` is "image". URL path returned by POST /api/images/upload (e.g. "/images/foo.png").' },
|
|
312
|
+
},
|
|
313
|
+
required: ['name', 'type'],
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
edges: {
|
|
317
|
+
type: 'array',
|
|
318
|
+
description: 'List of directed edges between nodes. Every edge should have a `label` describing the interaction (verb phrase). Exception: screen-guide edges have empty labels.',
|
|
319
|
+
items: {
|
|
320
|
+
type: 'object',
|
|
321
|
+
properties: {
|
|
322
|
+
from: { type: 'string', description: 'Name of the source node (must match a node `name` exactly).' },
|
|
323
|
+
to: { type: 'string', description: 'Name of the target node (must match a node `name` exactly). Optional for screen-guide diagrams — omit to render a free-end arrow the user can drag.' },
|
|
324
|
+
label: { type: 'string', description: 'Edge label — verb phrase describing the interaction. Strongly recommended; missing labels produce warnings (except for screen-guide).' },
|
|
325
|
+
},
|
|
326
|
+
required: ['from'],
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
required: ['title', 'diagramType', 'nodes', 'edges'],
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: 'list_source_files',
|
|
335
|
+
description: [
|
|
336
|
+
'List files under the project `sourceRoot` (configured in `.living-doc.json`, defaults to the parent folder of the docs directory).',
|
|
337
|
+
'',
|
|
338
|
+
'Use this tool as a **fallback** when the Markdown documentation lacks a specific low-level detail needed for a diagram — for example, when generating a screen-guide diagram or when documenting a piece of code that has no ADR. For architectural facts, read documents first.',
|
|
339
|
+
'',
|
|
340
|
+
'Common ignored folders are skipped automatically (`node_modules`, `dist`, `.git`, `build`, `target`, etc.).',
|
|
341
|
+
].join('\n'),
|
|
342
|
+
inputSchema: {
|
|
343
|
+
type: 'object',
|
|
344
|
+
properties: {
|
|
345
|
+
pattern: { type: 'string', description: 'Optional glob-like pattern matched against the relative path. Supports `*` (within a segment) and `**` (across segments). Example: `src/**/*.ts`.' },
|
|
346
|
+
maxResults: { type: 'number', description: 'Max number of files to return (default 500, hard cap 2000).' },
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: 'read_source_file',
|
|
352
|
+
description: [
|
|
353
|
+
'Read a source file under the project `sourceRoot`. Path must be relative to `sourceRoot`.',
|
|
354
|
+
'',
|
|
355
|
+
'Use this **only after** you have tried the documentation tools (`list_documents` / `read_document`). If you find yourself reading more than 3 source files for the same diagram, stop and update the documentation first — the docs are the source of truth.',
|
|
356
|
+
'',
|
|
357
|
+
'Files larger than 512 KB are rejected; use `search_source` to locate the relevant section.',
|
|
358
|
+
].join('\n'),
|
|
359
|
+
inputSchema: {
|
|
360
|
+
type: 'object',
|
|
361
|
+
properties: {
|
|
362
|
+
path: { type: 'string', description: 'Path relative to `sourceRoot`, e.g. `src/frontend/index.html`.' },
|
|
363
|
+
},
|
|
364
|
+
required: ['path'],
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
name: 'search_source',
|
|
369
|
+
description: [
|
|
370
|
+
'Grep-like text search across files under the project `sourceRoot`.',
|
|
371
|
+
'',
|
|
372
|
+
'Preferred over `read_source_file` when you only need to locate a symbol, identifier, or string. Returns `{ file, line, text }` matches.',
|
|
373
|
+
].join('\n'),
|
|
374
|
+
inputSchema: {
|
|
375
|
+
type: 'object',
|
|
376
|
+
properties: {
|
|
377
|
+
query: { type: 'string', description: 'Substring to match (plain text, not regex).' },
|
|
378
|
+
pattern: { type: 'string', description: 'Optional glob to restrict the search (e.g. `src/**/*.ts`).' },
|
|
379
|
+
caseSensitive: { type: 'boolean', description: 'Default false.' },
|
|
380
|
+
maxResults: { type: 'number', description: 'Max number of matches to return (default 200, hard cap 1000).' },
|
|
381
|
+
},
|
|
382
|
+
required: ['query'],
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
];
|
|
386
|
+
// ── MCP Prompts ────────────────────────────────────────────────────────────────
|
|
387
|
+
// Prompt templates guide the LLM to produce well-structured create_diagram
|
|
388
|
+
// calls. Layout work (positions, types, colors) happens on the caller's side —
|
|
389
|
+
// zero tokens consumed by the server.
|
|
390
|
+
const PROMPTS = [
|
|
391
|
+
{
|
|
392
|
+
name: 'generate-context-diagram',
|
|
393
|
+
description: 'DEFAULT. Generate a C4 System Context diagram — one system in the center, surrounding users and external systems. Safe to auto-invoke when the user asks for "a diagram", "the big picture", or "documentation".',
|
|
394
|
+
arguments: [
|
|
395
|
+
{ name: 'scope', description: 'Optional: name of the system to put at the center. Inferred from the docs if omitted.', required: false },
|
|
396
|
+
],
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
name: 'generate-container-diagram',
|
|
400
|
+
description: 'EXPLICIT-ONLY. Generate a C4 Container diagram (internal containers of a single system). Invoke this only when the user explicitly asks for a "container diagram".',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'generate-uml-diagram',
|
|
404
|
+
description: 'EXPLICIT-ONLY. Generate a UML diagram. Invoke this only when the user explicitly asks for a "UML diagram" by name.',
|
|
405
|
+
arguments: [
|
|
406
|
+
{ name: 'umlType', description: 'UML variant: class, sequence, state, activity, or use-case.', required: true },
|
|
407
|
+
],
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'update-diagram-from-docs',
|
|
411
|
+
description: 'Re-read source documents and update existing diagrams so they reflect the current state of the documentation. Accepts an optional diagramId to target a single diagram.',
|
|
412
|
+
arguments: [
|
|
413
|
+
{ name: 'diagramId', description: 'Optional: id of a single diagram to update. If omitted, all diagrams are inspected.', required: false },
|
|
414
|
+
],
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: 'generate-screen-guide',
|
|
418
|
+
description: 'EXPLICIT-ONLY. Generate an annotated UI guide: a screenshot image as the background with post-it notes describing each UI element. Reads the source code of the screen (HTML/JSX/template). Invoke only when the user explicitly asks for a "screen guide", "UI guide", or "annotated screenshot".',
|
|
419
|
+
arguments: [
|
|
420
|
+
{ name: 'screenFile', description: 'Relative path (under sourceRoot) of the screen source file to document, e.g. `src/frontend/index.html`.', required: true },
|
|
421
|
+
{ name: 'screenshotUrl', description: 'Optional: URL of the uploaded screenshot (e.g. `/images/index-2026.png`). If omitted, the prompt will instruct the user to upload one via the Admin UI first.', required: false },
|
|
422
|
+
],
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: 'flow',
|
|
426
|
+
description: 'Left-to-right linear flow diagram — steps or stages in a process.',
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'erd',
|
|
430
|
+
description: 'Entity-Relationship Diagram — entities as boxes, relationships as labeled edges.',
|
|
431
|
+
},
|
|
432
|
+
];
|
|
433
|
+
// Prepended to every diagram prompt — enforces ADR-first information gathering.
|
|
434
|
+
const PREAMBLE = `
|
|
435
|
+
## Before anything else — mine the existing documentation
|
|
436
|
+
|
|
437
|
+
Living Documentation is a tool where knowledge lives primarily in Markdown documents (ADRs, guides, decisions).
|
|
438
|
+
**Do not ask the user questions you can answer yourself by reading the docs.**
|
|
439
|
+
|
|
440
|
+
1. Call \`list_documents\` to get the full document list.
|
|
441
|
+
2. Read documents that look architecturally significant regardless of their folder name — look for ADR-style frontmatter (lines starting with \`**status:**\`, \`**description:**\`, \`**tags:**\`), README files, and any document whose title or category suggests architecture, integration, or domain knowledge.
|
|
442
|
+
3. **Ignore any document whose frontmatter contains \`status: SuperSeeded\`** — it is deprecated and must not be used as a source of truth.
|
|
443
|
+
4. Read the frontmatter (\`description\` and \`tags\` fields) of each relevant document with \`read_document\` to find answers to the diagram-specific questions below.
|
|
444
|
+
5. Only ask the user for information that cannot be found in any active (non-superseded) document.
|
|
445
|
+
|
|
446
|
+
## Node label format — mandatory
|
|
447
|
+
|
|
448
|
+
Every node label must follow the Simon Brown C4 convention using \\n for line breaks:
|
|
449
|
+
|
|
450
|
+
\`\`\`
|
|
451
|
+
Name\\n[Type]\\nShort description of role or responsibility
|
|
452
|
+
\`\`\`
|
|
453
|
+
|
|
454
|
+
Examples:
|
|
455
|
+
- \`"DriveBox\\n[Software System]\\nManages ad campaigns\\ndisplayed on taxi tablets"\`
|
|
456
|
+
- \`"Advertiser\\n[Person]\\nUploads media and\\npays for campaigns"\`
|
|
457
|
+
- \`"Stripe\\n[External System]\\nCard payment and\\npre-authorization"\`
|
|
458
|
+
|
|
459
|
+
Types to use: \`[Person]\`, \`[Software System]\`, \`[External System]\`, \`[Database]\`, \`[Device]\`
|
|
460
|
+
Keep descriptions short — 1 to 2 lines maximum.
|
|
461
|
+
|
|
462
|
+
## C4 progression — mandatory ordering
|
|
463
|
+
|
|
464
|
+
C4 diagrams must be created in strict order:
|
|
465
|
+
|
|
466
|
+
1. **Context first** — the entry point when scanning a project's docs for the first time.
|
|
467
|
+
It answers: what is the system, who uses it, what external systems does it integrate with?
|
|
468
|
+
2. **Container after** — a drill-down created only when a Context diagram already exists
|
|
469
|
+
**and** the reader explicitly asks to go deeper into a specific system.
|
|
470
|
+
3. **Component after that** — same rule, only after a Container exists.
|
|
471
|
+
|
|
472
|
+
**When reading docs for the first time, always create the Context diagram.**
|
|
473
|
+
Never jump to Container or Component as the first diagram for a system.
|
|
474
|
+
|
|
475
|
+
## Linked diagrams — C4 drill-down
|
|
476
|
+
|
|
477
|
+
Any node can link to an **already-existing** diagram for navigation (e.g. Context → Container → Component).
|
|
478
|
+
|
|
479
|
+
**Workflow:**
|
|
480
|
+
1. Call \`list_diagrams\`.
|
|
481
|
+
2. If a relevant child diagram already exists, add \`linkedDiagramId: "<id>"\` on the matching node.
|
|
482
|
+
3. If no child diagram exists, leave \`linkedDiagramId\` unset.
|
|
483
|
+
|
|
484
|
+
**RULE — never create child diagrams automatically.**
|
|
485
|
+
Container and Component diagrams are only created on explicit user request for a specific scope.
|
|
486
|
+
Do not create them as a side effect of creating a Context diagram.
|
|
487
|
+
|
|
488
|
+
Clicking a linked node in the editor navigates directly to the child diagram.
|
|
489
|
+
`.trim();
|
|
490
|
+
function buildPromptTemplate(name, args) {
|
|
491
|
+
switch (name) {
|
|
492
|
+
case 'generate-context-diagram':
|
|
493
|
+
return `
|
|
494
|
+
${PREAMBLE}
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
You are about to create a **C4 System Context Diagram** following Simon Brown's C4 model.
|
|
499
|
+
|
|
500
|
+
## Step 1 — Answer these three questions first (ask the user only if not found in docs)
|
|
501
|
+
|
|
502
|
+
1. **Scope** — What is the software system we are describing?${args.scope ? ` (The user specified: **${args.scope}**.)` : ' What is its name and primary responsibility?'}
|
|
503
|
+
2. **Users** — Who uses it? For each type of user: what are they doing with the system?
|
|
504
|
+
3. **Integrations** — What external systems does it need to integrate with? What data or interactions flow between them?
|
|
505
|
+
|
|
506
|
+
Do not proceed to the diagram until you have clear answers to all three.
|
|
507
|
+
|
|
508
|
+
## Step 2 — Build the diagram
|
|
509
|
+
|
|
510
|
+
### Layout rules (grid = 40 units, physics is disabled — positions are final)
|
|
511
|
+
- **Main system** → center: x: 0, y: 0. Type: box. Color: c-blue.
|
|
512
|
+
- **Human users (actors)** → left: x: -320, y: 0. Spread vertically by ±160 if several. Type: actor. Color: c-gray.
|
|
513
|
+
- **External systems** → right: x: 320, y: 0. Spread vertically by ±160 if several. Type: box. Color: c-slate.
|
|
514
|
+
- **External databases / datastores** → below: x: 0, y: 240. Type: database. Color: c-teal.
|
|
515
|
+
- All positions must be multiples of 40.
|
|
516
|
+
- Keep the diagram under ~10 nodes total.
|
|
517
|
+
|
|
518
|
+
### Edge rules
|
|
519
|
+
- Direction: actor → system, system → external system, system → datastore.
|
|
520
|
+
- Every edge must have a label describing the interaction in plain language (e.g. "submits orders", "reads customer data", "sends notifications via").
|
|
521
|
+
|
|
522
|
+
### Color palette
|
|
523
|
+
| Element | Color |
|
|
524
|
+
|---|---|
|
|
525
|
+
| Main system | c-blue |
|
|
526
|
+
| Human actor | c-gray |
|
|
527
|
+
| External system | c-slate |
|
|
528
|
+
| Datastore | c-teal |
|
|
529
|
+
|
|
530
|
+
## Step 3 — Call \`create_diagram\` with \`diagramType: "context"\`.
|
|
531
|
+
`.trim();
|
|
532
|
+
case 'generate-container-diagram':
|
|
533
|
+
return `
|
|
534
|
+
${PREAMBLE}
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
You are about to create a **C4 Container Diagram** following Simon Brown's C4 model.
|
|
539
|
+
|
|
540
|
+
## ⚠️ Explicit-request check
|
|
541
|
+
Only proceed if the user explicitly asked for a *container* diagram. If the request was generic ("a diagram", "the big picture"), stop and use \`generate-context-diagram\` instead.
|
|
542
|
+
|
|
543
|
+
## ⚠️ Pre-flight check — mandatory before anything else
|
|
544
|
+
|
|
545
|
+
1. Call \`list_diagrams\`.
|
|
546
|
+
2. If **no C4 Context diagram exists** for the target system → **stop here**.
|
|
547
|
+
- Inform the user that a Context diagram must be created first.
|
|
548
|
+
- Create the Context diagram using the \`generate-context-diagram\` prompt rules.
|
|
549
|
+
- Do not create the Container diagram in this session.
|
|
550
|
+
3. Only proceed to the Container diagram if a Context diagram already exists.
|
|
551
|
+
|
|
552
|
+
## Step 1 — Answer these questions first (ask the user only if not found in docs)
|
|
553
|
+
|
|
554
|
+
1. **System** — Which system are we zooming into?
|
|
555
|
+
2. **Containers** — What are its internal containers (web app, mobile app, API, background worker, database, cache…)?
|
|
556
|
+
3. **Users** — Which users interact directly with which containers?
|
|
557
|
+
4. **Integrations** — Which external systems do the containers communicate with?
|
|
558
|
+
|
|
559
|
+
## Step 2 — Build the diagram
|
|
560
|
+
|
|
561
|
+
### Layout rules (grid = 40 units)
|
|
562
|
+
Place containers in a logical left-to-right or top-to-bottom flow:
|
|
563
|
+
- **Frontend / Browser / Mobile**: x: -320, y: 0. Type: box. Color: c-sky.
|
|
564
|
+
- **API / Backend**: x: 0, y: 0. Type: box. Color: c-blue.
|
|
565
|
+
- **Database**: x: 320, y: 80. Type: database. Color: c-teal.
|
|
566
|
+
- **Cache / Queue**: x: 320, y: -80. Type: ellipse. Color: c-amber.
|
|
567
|
+
- **External actor** (user): x: -560, y: 0. Type: actor. Color: c-gray.
|
|
568
|
+
- **External system**: x: 0, y: 240. Type: box. Color: c-slate.
|
|
569
|
+
- Spread additional containers vertically by multiples of 160.
|
|
570
|
+
- All positions must be multiples of 40.
|
|
571
|
+
|
|
572
|
+
### Edge rules
|
|
573
|
+
- Label every edge with the protocol or action: "HTTPS", "SQL", "REST", "publishes", "subscribes"…
|
|
574
|
+
|
|
575
|
+
## Step 3 — Call \`create_diagram\` with \`diagramType: "container"\` and \`userRequestedExplicitly: true\`.
|
|
576
|
+
`.trim();
|
|
577
|
+
case 'generate-uml-diagram': {
|
|
578
|
+
const umlType = (args.umlType || '').trim().toLowerCase() || 'class';
|
|
579
|
+
return `
|
|
580
|
+
${PREAMBLE}
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
You are about to create a **UML ${umlType} diagram**.
|
|
585
|
+
|
|
586
|
+
## ⚠️ Explicit-request check
|
|
587
|
+
Only proceed if the user explicitly asked for a *UML* diagram by name. Otherwise use \`generate-context-diagram\` instead.
|
|
588
|
+
|
|
589
|
+
## Step 1 — Gather the facts from docs
|
|
590
|
+
|
|
591
|
+
Read the documents relevant to the UML ${umlType} diagram. For each element you plan to put on the diagram, make sure it exists in the documentation. Do not invent classes, states, or actors absent from the docs.
|
|
592
|
+
|
|
593
|
+
## Step 2 — Apply the UML ${umlType} conventions
|
|
594
|
+
|
|
595
|
+
${umlTypeGuidance(umlType)}
|
|
596
|
+
|
|
597
|
+
### Common rules (all UML variants)
|
|
598
|
+
- Each edge must have a label describing the relationship or transition.
|
|
599
|
+
- Keep labels short; use C4-style multi-line labels for class/component descriptions when helpful.
|
|
600
|
+
- Use multiples of 40 for positions. Origin (0,0) = canvas center.
|
|
601
|
+
|
|
602
|
+
## Step 3 — Call \`create_diagram\` with \`diagramType: "uml"\` and \`userRequestedExplicitly: true\`.
|
|
603
|
+
`.trim();
|
|
604
|
+
}
|
|
605
|
+
case 'update-diagram-from-docs':
|
|
606
|
+
return `
|
|
607
|
+
${PREAMBLE}
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
611
|
+
You are about to **update ${args.diagramId ? `diagram \`${args.diagramId}\`` : 'all existing diagrams'}** to reflect the current state of the documentation.
|
|
612
|
+
|
|
613
|
+
## Step 1 — Inventory existing diagrams
|
|
614
|
+
|
|
615
|
+
${args.diagramId
|
|
616
|
+
? `1. Call \`read_diagram\` with id \`${args.diagramId}\` to load its current nodes and edges.`
|
|
617
|
+
: `1. Call \`list_diagrams\` to get all diagrams with their id and title.
|
|
618
|
+
2. For each diagram, call \`read_diagram\` to load its current nodes and edges.`}
|
|
619
|
+
|
|
620
|
+
## Step 2 — Gather current architecture knowledge
|
|
621
|
+
|
|
622
|
+
1. Call \`list_documents\` to get all documents.
|
|
623
|
+
2. Read the documents that are architecturally significant (ADRs, README, guides with integration or architecture tags).
|
|
624
|
+
3. Ignore any document whose frontmatter contains \`status: SuperSeeded\`.
|
|
625
|
+
|
|
626
|
+
## Step 3 — Compare and update
|
|
627
|
+
|
|
628
|
+
For each diagram in scope:
|
|
629
|
+
|
|
630
|
+
1. **Identify the diagram type** from its title and content (Context, Container, Flow, ERD, UML…).
|
|
631
|
+
2. **Compare** its nodes and edges against the current documentation:
|
|
632
|
+
- New containers, systems, or actors mentioned in the docs but missing?
|
|
633
|
+
- Nodes that no longer exist or have been renamed?
|
|
634
|
+
- Edge labels still accurate?
|
|
635
|
+
3. **If up to date** → skip it, report "no changes needed".
|
|
636
|
+
4. **If changes are needed** → call \`create_diagram\` with:
|
|
637
|
+
- The **same \`id\`** as the existing diagram (overwrites it in place).
|
|
638
|
+
- The same \`diagramType\`. For non-context types, include \`userRequestedExplicitly: true\` since the user is explicitly updating that diagram.
|
|
639
|
+
- The same title unless a rename is warranted.
|
|
640
|
+
- Updated nodes and edges, preserving \`x\`/\`y\` positions of unchanged nodes.
|
|
641
|
+
|
|
642
|
+
## Step 4 — Report
|
|
643
|
+
|
|
644
|
+
Summarize which diagrams were updated (and what changed) and which were skipped (already up to date).
|
|
645
|
+
`.trim();
|
|
646
|
+
case 'flow':
|
|
647
|
+
return `
|
|
648
|
+
${PREAMBLE}
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
You are about to create a **linear flow diagram**.
|
|
653
|
+
|
|
654
|
+
## Step 1 — Answer these questions first (ask the user only if not found in docs)
|
|
655
|
+
|
|
656
|
+
1. **Process** — What process or workflow are we representing?
|
|
657
|
+
2. **Steps** — What are the steps or stages in order?
|
|
658
|
+
3. **Actors** — Are there human actors or external systems involved at any step?
|
|
659
|
+
4. **Branches** — Are there decision points or alternative paths?
|
|
660
|
+
|
|
661
|
+
## Step 2 — Build the diagram
|
|
662
|
+
|
|
663
|
+
### Layout rules (grid = 40 units)
|
|
664
|
+
- Steps are laid out **left to right**, each separated by 240 units on X.
|
|
665
|
+
- All nodes at y: 0 unless a branch is needed (branch at y: ±160).
|
|
666
|
+
- First step: x: -480. Then x: -240, x: 0, x: 240, x: 480… (adjust origin to center the flow).
|
|
667
|
+
- Use type: box for process steps (color: c-blue), type: actor for human actors (color: c-gray), type: database for stores (color: c-teal).
|
|
668
|
+
- Decision diamonds are not a native shape — use ellipse (color: c-amber) to indicate a decision point.
|
|
669
|
+
- All positions must be multiples of 40.
|
|
670
|
+
|
|
671
|
+
### Edge rules
|
|
672
|
+
- Edges are directional left-to-right.
|
|
673
|
+
- Label branches: "yes / no", "success / error", etc.
|
|
674
|
+
|
|
675
|
+
## Step 3 — Call \`create_diagram\` with \`diagramType: "flow"\`.
|
|
676
|
+
`.trim();
|
|
677
|
+
case 'erd':
|
|
678
|
+
return `
|
|
679
|
+
${PREAMBLE}
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
You are about to create an **Entity-Relationship Diagram**.
|
|
684
|
+
|
|
685
|
+
## Step 1 — Answer these questions first (ask the user only if not found in docs)
|
|
686
|
+
|
|
687
|
+
1. **Domain** — What domain or bounded context does this ERD cover?
|
|
688
|
+
2. **Entities** — What are the main entities (tables, aggregates)?
|
|
689
|
+
3. **Relationships** — What are the relationships between them and their cardinalities (1:1, 1:N, N:M)?
|
|
690
|
+
4. **Key attributes** — Are there important attributes worth labeling on the edges?
|
|
691
|
+
|
|
692
|
+
## Step 2 — Build the diagram
|
|
693
|
+
|
|
694
|
+
### Layout rules (grid = 40 units)
|
|
695
|
+
- Each entity is a box. Place them so related entities are close together.
|
|
696
|
+
- Suggested starting positions for up to 6 entities:
|
|
697
|
+
- top-left: x: -320, y: -200
|
|
698
|
+
- top-center: x: 0, y: -200
|
|
699
|
+
- top-right: x: 320, y: -200
|
|
700
|
+
- bottom-left: x: -320, y: 200
|
|
701
|
+
- bottom-center: x: 0, y: 200
|
|
702
|
+
- bottom-right: x: 320, y: 200
|
|
703
|
+
- All positions must be multiples of 40.
|
|
704
|
+
- Color: c-blue for main entities, c-green for junction/pivot tables, c-slate for lookup/reference tables.
|
|
705
|
+
|
|
706
|
+
### Edge rules
|
|
707
|
+
- Label every edge with the cardinality and nature of the relationship:
|
|
708
|
+
"1:N", "N:M", "has many", "belongs to", "references", etc.
|
|
709
|
+
- Edges are undirected by convention in ERDs — leave \`label\` descriptive.
|
|
710
|
+
|
|
711
|
+
## Step 3 — Call \`create_diagram\` with \`diagramType: "erd"\`.
|
|
712
|
+
`.trim();
|
|
713
|
+
case 'generate-screen-guide': {
|
|
714
|
+
const screenFile = (args.screenFile || '').trim();
|
|
715
|
+
const screenshotUrl = (args.screenshotUrl || '').trim();
|
|
716
|
+
return `
|
|
717
|
+
## Screen-guide diagram — source code IS the reference
|
|
718
|
+
|
|
719
|
+
A screen guide is an annotated screenshot built in **three layers**:
|
|
720
|
+
1. the screenshot image as background,
|
|
721
|
+
2. translucent \`box\` overlays covering each major layout region (zones),
|
|
722
|
+
3. \`post-it\` callouts for each first-level feature, linked to the UI by
|
|
723
|
+
free-end arrows.
|
|
724
|
+
|
|
725
|
+
**The source code is the authoritative reference**, not the Markdown docs.
|
|
726
|
+
No ADR describes every button.
|
|
727
|
+
|
|
728
|
+
## ⚠️ Explicit-request check
|
|
729
|
+
Only proceed if the user explicitly asked for a *screen guide*, *UI guide*, or *annotated screenshot*.
|
|
730
|
+
|
|
731
|
+
## Step 1 — Resolve the screen source
|
|
732
|
+
|
|
733
|
+
${screenFile
|
|
734
|
+
? `The user specified \`${screenFile}\`. Call \`read_source_file\` with \`path: "${screenFile}"\`.`
|
|
735
|
+
: `Ask the user which screen to document (e.g. \`src/frontend/index.html\`). Then call \`read_source_file\` on it.`}
|
|
736
|
+
|
|
737
|
+
If the screen pulls in components or partials, use \`search_source\` + \`read_source_file\` to follow them. Cap at ~5 files total — enough to identify zones and first-level features, not to trace every dependency.
|
|
738
|
+
|
|
739
|
+
## Step 2 — Identify layout zones (YOU decide, do not ask)
|
|
740
|
+
|
|
741
|
+
Scan the screen structure for **major visual regions** that partition the layout. Typical zones:
|
|
742
|
+
- Left / right sidebar or drawer
|
|
743
|
+
- Top bar / header
|
|
744
|
+
- Main content area
|
|
745
|
+
- Footer
|
|
746
|
+
- Right panel
|
|
747
|
+
|
|
748
|
+
Pick **2–5 zones**. For each zone, capture:
|
|
749
|
+
- \`name\` — 1–3 words ("Top Bar", "Collapsible Drawer", "Main Page").
|
|
750
|
+
- \`color\` — one distinct color per zone. Suggested rotation: \`c-red, c-amber, c-cyan, c-sky, c-lime, c-teal\`. Never reuse a color between two zones.
|
|
751
|
+
|
|
752
|
+
You will need the zone's bounding box on the screenshot (left/top/width/height in pixels) — you'll compute that once the user provides the screenshot.
|
|
753
|
+
|
|
754
|
+
## Step 3 — Identify first-level features (YOU decide, do not ask)
|
|
755
|
+
|
|
756
|
+
A **first-level feature** is:
|
|
757
|
+
- **Visible on screen** without any interaction (a button, toggle, input, primary navigation element, filter).
|
|
758
|
+
- **Changes user-facing behavior significantly** when used (navigates, filters, toggles mode, opens a panel, searches).
|
|
759
|
+
|
|
760
|
+
NOT a first-level feature:
|
|
761
|
+
- Decorative elements (logos, dividers, icons without action).
|
|
762
|
+
- Controls nested inside a panel/modal that only appears after clicking something.
|
|
763
|
+
- Pure labels / static text.
|
|
764
|
+
- Duplicate controls (if the same action has two buttons, count it once).
|
|
765
|
+
|
|
766
|
+
Typical count: **4–10** features. Do not pad with minor buttons; do not omit obvious ones.
|
|
767
|
+
|
|
768
|
+
For each feature, capture:
|
|
769
|
+
- \`name\` — 2–5 words, title-cased ("Collapsible Drawer", "Dark / Light Mode", "Text Search in all documents"). Multi-line via \`\\n\` allowed when needed.
|
|
770
|
+
- \`kind\`:
|
|
771
|
+
- \`interactive\` — standard button, link, input, toggle. **Default.**
|
|
772
|
+
- \`differentiating\` — a feature that distinguishes the product from alternatives ("Professional Diagram Editor", "Word Cloud Generator"). Reserve for the 1–3 truly distinguishing features.
|
|
773
|
+
- \`target\` — which UI element / zone it points to (used to place the anchor and the post-it).
|
|
774
|
+
|
|
775
|
+
**Color assignment for feature callouts:**
|
|
776
|
+
- \`interactive\` → \`c-amber\` or \`c-orange\` (yellow family). Default.
|
|
777
|
+
- \`differentiating\` → a distinct non-yellow color (\`c-purple\`, \`c-rose\`, \`c-red\`, \`c-sky\`, \`c-teal\`, \`c-green\`). Never yellow.
|
|
778
|
+
|
|
779
|
+
## Step 4 — Request the screenshot and WAIT
|
|
780
|
+
|
|
781
|
+
Tell the user:
|
|
782
|
+
|
|
783
|
+
> I identified N zones and M first-level features in \`<file>\`:
|
|
784
|
+
> - Zones: [comma-separated names]
|
|
785
|
+
> - Features: [comma-separated names, annotated with "(diff)" for the differentiating ones]
|
|
786
|
+
> I now need a screenshot of this screen. Two options:
|
|
787
|
+
> (a) Save the PNG into \`./documentation/images/<name>.png\` inside your docs folder.
|
|
788
|
+
> (b) Paste or drop the image into any existing diagram in the editor — it uploads automatically and returns a URL like \`/images/xxx.png\`.
|
|
789
|
+
> Please reply with (1) the URL, and (2) the natural pixel width × height of the image.
|
|
790
|
+
|
|
791
|
+
**Then stop.** Do not call \`create_diagram\` yet.
|
|
792
|
+
|
|
793
|
+
${screenshotUrl
|
|
794
|
+
? `(The user already provided \`${screenshotUrl}\` — you still need the pixel dimensions to place zones correctly.)`
|
|
795
|
+
: ''}
|
|
796
|
+
|
|
797
|
+
## Step 5 — Build the diagram
|
|
798
|
+
|
|
799
|
+
Coordinate system: screen-guide positions align to **screenshot pixels** (canvas centre is origin), NOT to the 40-unit grid. Use the pixel dimensions the user provided.
|
|
800
|
+
|
|
801
|
+
### Nodes
|
|
802
|
+
|
|
803
|
+
**A. Background image** (one node, \`locked\`):
|
|
804
|
+
\`\`\`json
|
|
805
|
+
{ "type": "image", "name": "screenshot", "imageSrc": "<URL>",
|
|
806
|
+
"width": <imgW>, "height": <imgH>, "x": 0, "y": 0, "locked": true }
|
|
807
|
+
\`\`\`
|
|
808
|
+
|
|
809
|
+
**B. Zone overlays** (one per zone, \`locked\`, translucent):
|
|
810
|
+
\`\`\`json
|
|
811
|
+
{ "type": "box", "name": "", "color": "<zone color>",
|
|
812
|
+
"bgOpacity": 0.18, "locked": true,
|
|
813
|
+
"width": <zoneW>, "height": <zoneH>,
|
|
814
|
+
"x": <zoneCenterX>, "y": <zoneCenterY> }
|
|
815
|
+
\`\`\`
|
|
816
|
+
|
|
817
|
+
**C. Zone labels** (one post-it per zone, **same color as the zone**):
|
|
818
|
+
\`\`\`json
|
|
819
|
+
{ "type": "post-it", "name": "<zone name>", "color": "<zone color>",
|
|
820
|
+
"x": <inside zone>, "y": <inside zone>, "locked": true }
|
|
821
|
+
\`\`\`
|
|
822
|
+
|
|
823
|
+
**D. Feature callouts** (one post-it per feature, placed **outside** the screenshot):
|
|
824
|
+
\`\`\`json
|
|
825
|
+
{ "type": "post-it", "name": "<feature name>",
|
|
826
|
+
"color": "<c-amber for interactive, distinct non-yellow for differentiating>",
|
|
827
|
+
"x": <outside screenshot>, "y": <outside screenshot> }
|
|
828
|
+
\`\`\`
|
|
829
|
+
Spread them in horizontal bands above/below the image and/or vertical columns left/right of it. Keep callouts close to their target so the arrow reads naturally.
|
|
830
|
+
|
|
831
|
+
**E. Anchors** (one per feature callout, placed on the target pixel — 8×8, invisible at rest):
|
|
832
|
+
\`\`\`json
|
|
833
|
+
{ "type": "anchor", "name": "a1", "color": "c-gray",
|
|
834
|
+
"x": <target pixel x>, "y": <target pixel y> }
|
|
835
|
+
\`\`\`
|
|
836
|
+
Use short unique names (\`a1\`, \`a2\`, …) — anchors are invisible so the label does not matter.
|
|
837
|
+
|
|
838
|
+
### Edges
|
|
839
|
+
|
|
840
|
+
For each feature callout, emit one directed edge from the post-it to its anchor, with an **empty** label:
|
|
841
|
+
\`\`\`json
|
|
842
|
+
{ "from": "<post-it name>", "to": "a1", "label": "" }
|
|
843
|
+
\`\`\`
|
|
844
|
+
|
|
845
|
+
If you do not know exact target coordinates, you may omit the anchor and the \`to\` field — the edge renders a free-end arrow the user can drag:
|
|
846
|
+
\`\`\`json
|
|
847
|
+
{ "from": "<post-it name>", "label": "" }
|
|
848
|
+
\`\`\`
|
|
849
|
+
|
|
850
|
+
**Prefer anchors.** The free-end fallback is a shortcut when pixel targets are unknown.
|
|
851
|
+
|
|
852
|
+
**Never** point edges at the image node itself — every arrow would converge on the image centre.
|
|
853
|
+
|
|
854
|
+
## Step 6 — Call \`create_diagram\`
|
|
855
|
+
|
|
856
|
+
\`\`\`json
|
|
857
|
+
{
|
|
858
|
+
"diagramType": "screen-guide",
|
|
859
|
+
"userRequestedExplicitly": true,
|
|
860
|
+
"title": "Screen guide — <screen name>",
|
|
861
|
+
"nodes": [ /* image + zone boxes + zone labels + feature callouts + anchors */ ],
|
|
862
|
+
"edges": [ /* one edge per feature callout → its anchor */ ]
|
|
863
|
+
}
|
|
864
|
+
\`\`\`
|
|
865
|
+
`.trim();
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
function umlTypeGuidance(umlType) {
|
|
870
|
+
switch (umlType) {
|
|
871
|
+
case 'class':
|
|
872
|
+
return `### UML class diagram
|
|
873
|
+
- Each class is a \`box\` (c-blue for domain classes, c-green for value objects, c-slate for interfaces).
|
|
874
|
+
- Node label: \`ClassName\\n[Class]\\n+ attr: Type\\n+ method(): Type\`.
|
|
875
|
+
- Edges: label relationships as "extends", "implements", "has 1", "has *", "uses".`;
|
|
876
|
+
case 'sequence':
|
|
877
|
+
return `### UML sequence diagram
|
|
878
|
+
- Each participant is a \`box\` (c-blue for systems, c-gray for actors).
|
|
879
|
+
- Arrange participants left-to-right at the same y (spacing 200).
|
|
880
|
+
- Edges are messages; the label is the method/event name and uses arrows top-down by ordering the edges in the array chronologically.`;
|
|
881
|
+
case 'state':
|
|
882
|
+
return `### UML state diagram
|
|
883
|
+
- Each state is an \`ellipse\` (c-amber).
|
|
884
|
+
- Start and end states are \`circle\` (c-slate for end, c-green for start).
|
|
885
|
+
- Edges are transitions; label with the event/trigger.`;
|
|
886
|
+
case 'activity':
|
|
887
|
+
return `### UML activity diagram
|
|
888
|
+
- Activities are \`box\` (c-blue).
|
|
889
|
+
- Decision nodes are \`ellipse\` (c-amber).
|
|
890
|
+
- Start/end are \`circle\` (c-green/c-slate).
|
|
891
|
+
- Edges labeled with the guard or action.`;
|
|
892
|
+
case 'use-case':
|
|
893
|
+
case 'usecase':
|
|
894
|
+
return `### UML use-case diagram
|
|
895
|
+
- Actors are \`actor\` (c-gray) on the left (x: -320).
|
|
896
|
+
- Use cases are \`ellipse\` (c-blue) in the center.
|
|
897
|
+
- The system boundary is implied by grouping — no explicit box needed.
|
|
898
|
+
- Edges between actor and use case labeled with the action ("initiates", "participates in").`;
|
|
899
|
+
default:
|
|
900
|
+
return `### UML ${umlType} diagram\nFollow the standard UML conventions for \`${umlType}\` diagrams. Use \`box\`, \`ellipse\`, \`actor\`, \`circle\`, or \`database\` shapes as appropriate; label every edge.`;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
function createMcpServer(docsPath) {
|
|
904
|
+
const server = new index_js_1.Server({ name: 'living-documentation', version: '1.0.0' }, {
|
|
905
|
+
capabilities: { tools: {}, prompts: {} },
|
|
906
|
+
instructions: SERVER_GUIDE,
|
|
907
|
+
});
|
|
908
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
909
|
+
server.setRequestHandler(types_js_1.ListPromptsRequestSchema, async () => ({ prompts: PROMPTS }));
|
|
910
|
+
server.setRequestHandler(types_js_1.GetPromptRequestSchema, async (request) => {
|
|
911
|
+
const name = request.params.name;
|
|
912
|
+
const prompt = PROMPTS.find(p => p.name === name);
|
|
913
|
+
if (!prompt)
|
|
914
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
915
|
+
const args = (request.params.arguments ?? {});
|
|
916
|
+
const text = buildPromptTemplate(name, args);
|
|
917
|
+
return {
|
|
918
|
+
description: prompt.description,
|
|
919
|
+
messages: [{ role: 'user', content: { type: 'text', text } }],
|
|
920
|
+
};
|
|
921
|
+
});
|
|
922
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
923
|
+
const { name, arguments: args = {} } = request.params;
|
|
924
|
+
try {
|
|
925
|
+
switch (name) {
|
|
926
|
+
case 'get_server_guide':
|
|
927
|
+
return { content: [{ type: 'text', text: SERVER_GUIDE }] };
|
|
928
|
+
case 'list_documents':
|
|
929
|
+
return (0, documents_1.toolListDocuments)(docsPath);
|
|
930
|
+
case 'read_document':
|
|
931
|
+
return (0, documents_1.toolReadDocument)(docsPath, args);
|
|
932
|
+
case 'create_document':
|
|
933
|
+
return (0, documents_1.toolCreateDocument)(docsPath, args);
|
|
934
|
+
case 'list_diagrams':
|
|
935
|
+
return (0, diagrams_1.toolListDiagrams)(docsPath);
|
|
936
|
+
case 'read_diagram':
|
|
937
|
+
return (0, diagrams_1.toolReadDiagram)(docsPath, args);
|
|
938
|
+
case 'create_diagram':
|
|
939
|
+
return (0, diagrams_1.toolCreateDiagram)(docsPath, args);
|
|
940
|
+
case 'list_source_files':
|
|
941
|
+
return (0, source_1.toolListSourceFiles)(docsPath, args);
|
|
942
|
+
case 'read_source_file':
|
|
943
|
+
return (0, source_1.toolReadSourceFile)(docsPath, args);
|
|
944
|
+
case 'search_source':
|
|
945
|
+
return (0, source_1.toolSearchSource)(docsPath, args);
|
|
946
|
+
default:
|
|
947
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
catch (err) {
|
|
951
|
+
return {
|
|
952
|
+
content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
953
|
+
isError: true,
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
return server;
|
|
958
|
+
}
|
|
959
|
+
function mcpRouter(docsPath) {
|
|
960
|
+
const router = (0, express_1.Router)();
|
|
961
|
+
// Main MCP endpoint — stateless: one Server + Transport per request
|
|
962
|
+
router.post('/', async (req, res) => {
|
|
963
|
+
const server = createMcpServer(docsPath);
|
|
964
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
965
|
+
try {
|
|
966
|
+
await server.connect(transport);
|
|
967
|
+
await transport.handleRequest(req, res, req.body);
|
|
968
|
+
}
|
|
969
|
+
finally {
|
|
970
|
+
await server.close();
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
// GET — surface a helpful message (Claude Desktop / browser landing)
|
|
974
|
+
router.get('/', (_req, res) => {
|
|
975
|
+
res.json({
|
|
976
|
+
mcp: 'living-documentation',
|
|
977
|
+
version: '1.0.0',
|
|
978
|
+
transport: 'streamable-http',
|
|
979
|
+
endpoint: 'POST /mcp',
|
|
980
|
+
tools: TOOLS.map(t => t.name),
|
|
981
|
+
prompts: PROMPTS.map(p => ({ name: p.name, description: p.description })),
|
|
982
|
+
});
|
|
983
|
+
});
|
|
984
|
+
return router;
|
|
985
|
+
}
|
|
986
|
+
//# sourceMappingURL=server.js.map
|