diagrams-mcp-server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| DIAGRAMS_DIR | No | Where diagram files live, relative to PROJECT_ROOT unless absolute. Default is 'diagrams'. | |
| PROJECT_ROOT | No | Root of the codebase this server is attached to (used by diagrams_check_consistency). Defaults to current working directory. | |
| PLANTUML_SERVER_URL | No | Override the public PlantUML rendering fallback (e.g. to point at a self-hosted instance). Default is 'https://www.plantuml.com/plantuml'. | |
| ALLOW_REMOTE_PLANTUML | No | Set to exactly 'true' to allow the remote PlantUML server fallback when no local 'plantuml' CLI is installed. Any other value keeps remote rendering disabled. | |
| DISABLE_REMOTE_PLANTUML | No | Set to exactly 'true' to never use the remote PlantUML server, even when ALLOW_REMOTE_PLANTUML=true is set. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| diagrams_listA | List all PlantUML and Mermaid diagram files stored under the project's diagrams directory. This tool scans the configured diagrams root recursively and returns every file with a recognized diagram extension (.puml, .plantuml, .mmd, .mermaid). It does NOT create, modify, or render diagrams — read-only. Args:
Returns: JSON with schema: { "diagrams_root": string, // absolute path being scanned "count": number, // number of diagrams in this page "total": number, // number of diagrams matching type_filter, before paging "offset": number, // effective offset of this page "limit": number, // effective limit of this page (requested limit, or remaining count when omitted) "has_more": boolean, // true when diagrams after this page remain "diagrams": [ { "relative_path": string, // path to use with diagrams_get / diagrams_update "type": "plantuml" | "mermaid", "title": string | null, // best-effort extracted title "size_bytes": number, "modified_at": string // ISO 8601 timestamp } ] } Pagination is explicit: omitting offset/limit returns every match with has_more=false. Nothing is ever silently dropped — has_more tells the caller when to request the next page with offset=<offset+count>. Examples:
Error Handling:
|
| diagrams_getA | Retrieve the raw source text of a single PlantUML or Mermaid diagram, in full or as an explicit character window. Args:
Returns: JSON with schema: { "relative_path": string, "type": "plantuml" | "mermaid", "content": string, // full source, or the requested [offset, offset+max_chars) window "is_partial": boolean, // true when content is a window rather than the full source "offset": number, // effective character offset of this window "total_chars": number, // full source length in characters "returned_chars": number,// length of the returned content "has_more": boolean // true when source after this window remains } The text block always equals structuredContent.content. Content is never silently truncated: omitting offset/max_chars returns everything, and requesting a window is always reported via is_partial/has_more. Examples:
Error Handling:
|
| diagrams_createA | Create a new PlantUML or Mermaid diagram file under the diagrams root. The diagram type is inferred from the file extension in relative_path:
This tool refuses to overwrite an existing file — use diagrams_update for that. Intermediate directories in relative_path are created automatically. Performs a basic, dependency-free syntax check before writing (not full validation): PlantUML must include @startuml/@enduml boundaries; Mermaid must start with a known diagram declaration. Clearly invalid or empty sources are rejected without creating a file. Args:
Returns: JSON with schema: { "relative_path": string, "created": true } Examples:
Error Handling:
|
| diagrams_updateA | Replace the full content of an existing PlantUML or Mermaid diagram file. This performs a full-content replace, not a partial edit — pass the complete new diagram source. To create a new diagram, use diagrams_create (or set create_if_missing=true here). Performs a basic, dependency-free syntax check before writing (not full validation): PlantUML must include @startuml/@enduml boundaries; Mermaid must start with a known diagram declaration. Clearly invalid or empty sources are rejected without overwriting the existing file. Args:
Returns: JSON with schema: { "relative_path": string, "updated": true } Examples:
Error Handling:
|
| diagrams_deleteA | Delete a single PlantUML or Mermaid diagram file from the diagrams root. This is destructive and cannot be undone — the file is removed from disk. To replace content instead, use diagrams_update. To remove then recreate with different content, delete first, then use diagrams_create. Args:
Returns: JSON with schema: { "relative_path": string, "deleted": true } Examples:
Error Handling:
|
| diagrams_renderA | Render a PlantUML or Mermaid diagram to an image (SVG or PNG) and return it as base64-encoded image content. Rendering requirements:
Args:
Returns: An image content block (base64-encoded), plus a JSON summary: { "relative_path": string, "format": "svg" | "png", "rendered": true } Examples:
Error Handling:
|
| diagrams_exportA | Package a stored PlantUML or Mermaid diagram and its rendered SVG into one self-contained HTML file you can share or open outside the repo. The SVG is encoded as a data image, so renderer markup is not parsed into the HTML DOM. SVG image processing disables scripts and external resource loading. A restrictive content security policy allows only data images and inline wrapper styles. SVG text is not selectable in the exported image. Diagram source is escaped in a native collapsible block when include_source is set, and the artifact works offline without new dependencies. Rendering uses the same path and the same rules as diagrams_render: Mermaid requires the local 'mmdc' CLI with no fallback, and PlantUML prefers a local 'plantuml' CLI, falling back to the configured remote server only when ALLOW_REMOTE_PLANTUML=true and DISABLE_REMOTE_PLANTUML is not 'true'. Remote PlantUML rendering sends diagram source to that server over HTTPS. The tool never writes a file: the HTML comes back as text and you decide where it lands. A bundle larger than 5000000 bytes is refused outright rather than cut down, because a half-rendered artifact is worse than none. Args:
Returns: The HTML as a text content block, plus a JSON summary: { "relative_path": string, // POSIX form, the only path in the bundle "diagram_type": "plantuml" | "mermaid", "format": "html", "bytes": number, // UTF-8 byte length of the returned HTML "svg_chars": number, // image source characters after XML preamble stripping, before base64 encoding "source_included": boolean, // whether the source block was embedded "truncated": false, // always false; over-cap is an error, never a cut file "rendered_with": "local-plantuml" | "remote-plantuml" | "mmdc" } Examples:
Error Handling:
|
| diagrams_save_exportA | Save a stored PlantUML or Mermaid diagram as one self-contained HTML file inside the diagrams root. The SVG is encoded as a data image, so renderer markup is not parsed into the HTML DOM. SVG image processing disables scripts and external resource loading. A restrictive content security policy allows only data images and inline wrapper styles. SVG text is not selectable in the exported image. Diagram source is escaped in a native collapsible block when include_source is set, and the artifact works offline without new dependencies. Rendering uses the same path and the same rules as diagrams_render: Mermaid requires the local 'mmdc' CLI with no fallback, and PlantUML prefers a local 'plantuml' CLI, falling back to the configured remote server only when ALLOW_REMOTE_PLANTUML=true and DISABLE_REMOTE_PLANTUML is not 'true'. Remote PlantUML rendering sends diagram source to that server over HTTPS. The finished bundle is measured before the output directories or file are created. A bundle larger than 5000000 bytes is refused. The target must end in .html (case-insensitive) and must not exist: existing files are refused atomically, never overwritten. Saved HTML files are excluded from diagram listing and CRUD tools. To replace an export, choose a different output_path or remove the existing target yourself. Args:
Returns: A short acknowledgement as a text content block (not the HTML itself), plus a JSON summary: { "relative_path": string, // POSIX form of the source diagram "output_path": string, // POSIX form of the saved HTML file "diagram_type": "plantuml" | "mermaid", "format": "html", "bytes": number, // UTF-8 byte length of the saved HTML "svg_chars": number, // image source characters after XML preamble stripping, before base64 encoding "source_included": boolean, // whether the source block was embedded "truncated": false, // always false; over-cap is an error, never a cut file "rendered_with": "local-plantuml" | "remote-plantuml" | "mmdc" } Examples:
Error Handling:
|
| diagrams_check_consistencyA | Compare class/interface/component names mentioned in a PlantUML or Mermaid diagram against identifiers that actually exist in the codebase, to catch documentation drift. This is a heuristic, text-based check (not a full semantic/AST analysis): it extracts entity names from class/interface/enum/component declarations in the diagram, then searches source files under the project root for a matching identifier as a whole word. It flags names that appear in the diagram but were not found anywhere in the scanned code — a signal the diagram may be outdated, or the code was renamed/removed/not yet built. This tool does NOT modify the diagram or the code. It only reports findings; the caller (agent or human) decides what to do about them. Args:
Returns: JSON with schema: { "diagram_path": string, "entities_found": number, // total entity names extracted from the diagram "entities_matched": number, // how many were found somewhere in the code "entities_unmatched": number, // how many were NOT found (potential drift) "files_scanned": number, // how many source files were searched "searched_directory": string, // absolute path of the code root that was scanned "truncated": boolean, // true when the 5,000-file scan cap was reached; unmatched results may be incomplete "scan_limit": number, // maximum source files collected during the scan "scan_warning": string | null, // human-readable warning when truncated, otherwise null "entities": string[], // extracted entity names, in extraction order "matched_entities": string[], // extracted entities found in the code "unmatched_entities": string[],// extracted entities NOT found (potential drift) "analyzers": { // scanned file extensions per analyzer tier "reliable": string[], // per-language declaration patterns (JS/TS, Python, PHP, Java) "experimental": string[], // generic heuristic path (C#, Go, Ruby, Kotlin, Rust) "generic": string[] // other scanned extensions, heuristic path only }, "confidence": "heuristic", // results are evidence, never a definitive verdict "heuristic_warning": string, // human-readable limits of the heuristic "evidence": [ // per-entity evidence, same order as "entities" { "name": string, "matched": boolean, "analyzers": ("reliable" | "experimental" | "generic")[], "matched_files": string[], // POSIX paths relative to searched_directory (capped) "matched_file_count": number } ], "issues": [ { "name": string, // the unmatched entity name "issue": string, // human-readable explanation "severity": "warning" | "info" } ] } Examples:
Error Handling:
|
| diagrams_generateA | Draft a PlantUML or Mermaid class diagram from a slice of the codebase, returning source text to review and then save with diagrams_create. This is the generative flip side of diagrams_check_consistency: the same code-reading machinery that detects drift can seed the diagram in the first place. It reads class/interface/enum/type/function declarations under the requested scope and emits one box per declared name, plus extends/implements edges when the TypeScript AST can evidence them. It never writes: nothing lands in the diagrams directory without an explicit diagrams_create call. It is a heuristic (name extraction, not full type modeling) and says so in every result: member lists, generics, package nesting, and cross-file inheritance through re-exports are out of scope, and a scope without TypeScript-family files yields entities with no relations. Args:
Returns: JSON with schema: { "scope": string, // POSIX path as resolved, "." for the project root "format": "puml" | "mermaid", "source": string, // the generated diagram; identical to the text block "entities": string[], // declared names in emission order, capped "entities_included": number, // length of "entities" "entities_available": number, // distinct names found, may exceed the cap "entities_capped": boolean, // true when names were dropped by the cap "entity_limit": number, // the applied cap (max_entities, at most 60) "relations": [ // evidenced edges only; empty when evidence is unavailable { "from": string, "to": string, "kind": "extends" | "implements" } ], "relations_included": number, "relations_available": number, "relations_capped": boolean, // true when edges were dropped by the cap or by an entity the cap removed "relation_limit": number, // 60 "files_scanned": number, "truncated": boolean, // true when the 5,000-file scan cap was reached "scan_limit": number, // 5,000 "scan_warning": string | null, // human-readable warning when truncated, otherwise null "dialect_note": string | null, // non-null when relations are unavailable or the scope has no code files "confidence": "heuristic", "heuristic_warning": string, // what name extraction can and cannot tell you "written": false // always false; save with diagrams_create } Every cap reports itself in-band, so a truncated or capped result is never silent. Examples:
Error Handling:
|
| diagrams_generate_sequenceA | Draft a PlantUML or Mermaid sequence diagram from the message-call patterns in a slice of the codebase, returning source text to review and then save with diagrams_create. Static call-site order is not runtime order. This tool reads call sites in the order a reader meets them and says so in every result: a call inside a callback, promise, or listener is counted in deferred_count and excluded from the messages, because its real position in the conversation is unknowable from source. It is the generative flip side of the consistency checker's ordered call graph: the same caller-to-callee evidence, turned into a starter diagram instead of a verdict. It never writes: nothing lands in the diagrams directory without an explicit diagrams_create call. Each sender is the file containing the call site even when another file declares the same caller name. Callee mapping uses case-insensitive declared-identifier equality and the first declaring participant in file order. A callee that no file in the scope declares is reported in unresolved_callees, never attached to an invented participant. Which class owns a method is a type question, and out of scope. Args:
Returns: JSON with schema: { "scope": string, // POSIX path as resolved, "." for the project root "format": "puml" | "mermaid", "source": string, // the generated sequence; identical to the text block (message labels carry '()' when include_call_parentheses is true) "participants": string[], // participant names as emitted, in first-conversation order, capped "participants_included": number, // length of "participants" "participants_available": number,// distinct participants in candidate messages, may exceed the cap "participants_capped": boolean, // true when participants were dropped by the cap "participant_limit": number, // the applied cap (max_participants, at most 20) "messages": [ // ordered call sites, one per sequenced call (message stays bare when include_call_parentheses is true) { "from": string, "to": string, "message": string, "line": number, "via_callback": false } ], "messages_included": number, "messages_available": number, // candidate messages, may exceed the cap "messages_capped": boolean, // true when messages were dropped by either cap "message_limit": number, // the applied cap (max_messages, at most 50) "deferred_count": number, // call sites inside callbacks/promises: counted, never sequenced "unresolved_callees": string[], // callees no participant in the scope declares "files_scanned": number, "truncated": boolean, // true when the 5,000-file scan cap was reached "scan_limit": number, // 5,000 "scan_warning": string | null, // human-readable warning when truncated, otherwise null "confidence": "heuristic", "heuristic_warning": string, // what static call order can and cannot tell you "written": false // always false; save with diagrams_create } Every cap reports itself in-band, so a truncated or capped result is never silent. Examples:
Error Handling:
|
| diagrams_diffA | Compare two diagram sources — two stored files, or a stored file against inline text — and report the added, removed, and renamed entity names in structured form. This is the review-time companion to diagrams_check_consistency: that tool asks whether a diagram still matches the code, this one asks what changed between two versions of the diagram itself. Give it the previous version as a_relative_path or a_content and the new version as the b side, and it lists what a reviewer needs to confirm. It is pure comparison over sources the store already knows how to read: no writes, no network, no filesystem changes. Each side supplies exactly one of a path or inline content, so unstaged edits can be diffed without a round trip. Rename detection pairs a removed name with an added one only when they are identical once lowercased and stripped of separators, and every rename carries confidence: "heuristic" — similarity is not semantic identity. Args:
Returns: JSON with schema: { "a": { "source": string, "type": "plantuml" | "mermaid" }, // path, or "" "b": { "source": string, "type": "plantuml" | "mermaid" }, "added": [{ "name": string }], // declared on b only "removed": [{ "name": string }], // declared on a only "renamed": [ // paired by the shared name normalizer { "from": string, "to": string, "confidence": "heuristic" } ], "unchanged": string[], // declared on both, in a's order "unchanged_count": number, "participants_added": string[], // sequence diagrams only; [] otherwise "participants_removed": string[], "calls_added": string[], "calls_removed": string[], "is_same": boolean, // entity names unchanged, and call order unchanged when comparison is enabled "call_order": { "a": string[], "b": string[], "changed": boolean }, // present only when compare_call_order=true "confidence": "heuristic", "heuristic_warning": string } A paired rename leaves the added/removed lists, so no change is reported twice. The two sides may use different dialects; each is read with its own syntax. Examples:
Error Handling:
|
| diagrams_templateA | Emit a built-in starter skeleton (class, sequence, or C4-context) or a custom project template in PlantUML or Mermaid, returning validated source text to fill in and then save with diagrams_create. Built-in skeletons are pure and require no filesystem or code scan. Custom templates read one named JSON file under PROJECT_ROOT/.diagrams-templates; identical inputs and file contents yield identical source. No template evaluates code or fetches remote resources. It never writes: nothing lands in the diagrams directory without an explicit diagrams_create call, and the emitted source clears the exact syntax gate that tool enforces, so the output can be saved as-is. The three built-in kinds are 'class', 'sequence', and 'c4_context'. Use 'custom' with custom_template to load .json. The selected 'puml' or 'mermaid' object must contain 'source' and 'entity' strings. Source placeholders are {{title}} and {{entities}}; entity patterns support {{name}}. Reads are limited to 65536 bytes and expansion to 1000000 JavaScript string characters. Files must be regular files inside the template directory; symlinks, unknown fields, and unsupported placeholders are rejected. Args:
Returns: JSON with schema: { "template": "class" | "sequence" | "c4_context" | "custom", "custom_template": string, // present only for custom templates "format": "puml" | "mermaid", "title": string | null, // the normalized one-line title, or null when none was given "source": string, // the skeleton; identical to the text block "entities": string[], // the names as accepted, in input order "entities_included": number, // length of "entities" "deterministic": true, // same inputs and template contents yield the same source "written": false // always false; save with diagrams_create } Examples:
Error Handling:
|
| diagrams_list_templatesA | Discover the diagram templates diagrams_template can instantiate, without reading any template contents. Lists the built-in skeleton kinds (each supports 'puml' and 'mermaid') plus the custom-template candidate names found as *.json entries directly under PROJECT_ROOT/.diagrams-templates. A candidate name is an identifier to pass as custom_template to diagrams_template with template='custom'; the definition, the selected dialect, and the emitted source are validated there, not here. Discovery reads directory entries only — file contents are never read, so a malformed JSON file can still appear as a candidate — and it never writes or creates a missing template directory. The scan is bounded: at most 1000 directory entries are examined (MAX_TEMPLATE_SCAN_ENTRIES), counting non-template entries too, plus one lookahead to detect the cap. There is no pagination, no full directory total, and no global subset ordering promised when capped: custom_count describes only the returned candidates, and the returned names are sorted only within the capped subset, which depends on filesystem iteration order. Args: (none): Call with {} — discovery takes no arguments. Returns: JSON with schema: { "built_in": [ // one entry per built-in kind, in documented order { "template": "class" | "sequence" | "c4_context", "formats": ["puml", "mermaid"] } ], "custom": [ // candidate names, sorted within the scanned subset { "template": "custom", "custom_template": string, "relative_path": string } ], "custom_count": number, // length of "custom": returned candidates only, not a full total when capped "entries_scanned": number, // directory entries examined, including non-template entries "scan_limit": number, // 1000 "truncated": boolean, // true when the entry cap was reached "scan_warning": string | null,// human-readable warning when truncated, otherwise null "written": false // always false; discovery never writes } Each custom relative_path identifies the project-relative file '.diagrams-templates/.json'. Pass the custom_template identifier, not this path, to diagrams_template. Examples:
Error Handling:
|
| diagrams_scaffoldA | Draft empty exported TypeScript classes from the entity-name candidates in a stored PlantUML or Mermaid diagram, returning source text to review and then save yourself. This reads heuristic entity-name candidates through the existing extractor unchanged, so candidates may include aliases, namespaces, components, participants, and call names such as charge. By default (all opt-in flags false) it does NOT recover class kinds, members, field types, relations, or runtime behavior. Every result says so with confidence "heuristic" plus a heuristic_warning; review the draft before saving it as TypeScript yourself. With include_members=true, simple top-level multiline class NAME { blocks can add member stubs. Names must be bare ASCII identifiers; quoted, aliased, generic, nested, or decorated classes are outside this subset. The first substantive line must be @startuml (PlantUML) or classDiagram (Mermaid). Supported members: optional +, -, #, or ~ visibility; fields name: Type, Type name, or bare name; methods name(args) with an optional single-token return label, or PlantUML Type name(args). Without include_types, fields become unknown; methods accept ..._args: unknown[], return unknown, and throw the literal "Not implemented". Argument names, types, modifiers, and bodies are not recovered. Member names use the same ASCII identifier grammar and length cap as class names; constructor and prototype are excluded. Duplicate names keep their first occurrence across field/method collisions and repeated class blocks. Unsupported syntax is skipped, including constructors, initializers, implementation bodies, and external Class : member notation. Whole-line comments, PlantUML block comments, and note bodies are ignored. Each emitted class receives at most 30 members; members_capped reports an additional recognized unique name beyond that limit. This is a heuristic subset, not a full parser. With include_types=true (which implies include_members=true), accepted field labels resolve to a strict case-sensitive subset only: string, number, boolean, bigint, or exactly an emitted class name, optionally with one [] suffix, optionally paired with exactly one null arm in either order (for example, string | null or null | User[]); nullable labels canonicalize to Atom | null. Whitespace around arms and the separator is allowed, but not inside an atom. Bare null, undefined as a type atom, any, unknown, void, extra or duplicate arms, parentheses, other generics, objects, functions, qualified names, and nested arrays are unsupported. Classes past max_entities, skipped candidates, and nonexistent classes fall back to unknown. Accepted fields emit as name!: Type (definite assignment for strict TypeScript); every other emitted field keeps the member-mode name: unknown;. Methods stay literal throwing stubs with no recovered params or returns. Class references are heuristic labels only, with no supplied runtime value or relations claimed. typed_fields counts accepted emitted fields and unresolved_fields counts emitted fields falling back to unknown (never methods or skipped/over-cap members). Array and ReadonlyArray accept exactly one supported primitive or emitted-class base and emit T[] or readonly T[] respectively. Either wrapper may have one null arm. No whitespace is allowed inside wrappers and nested wrappers or array arguments or array suffixes on wrappers remain unsupported. Wrapper and nullable labels require name: Type field notation. Trimmed labels are retained up to 82 characters including whitespace around the separator. Type identifiers remain limited to 60 characters. An overlong label falls back to unknown even if removing extra whitespace would make it fit. With include_relations=true, typed members are enabled even if include_types/include_members are false. Body field labels use the same nullable grammar as include_types. Top-level Owner --> Target : role links become role!: Target;. Optional target multiplicity before Target (quoted , 0.., or 1..*) becomes role!: Target[];. Both endpoints must be selected emitted classes and independently declared plain top-level class NAME, class NAME { multiline blocks, or class NAME {} empty blocks. No endpoint classes are invented. Alias/quoted/generic/nested/implicit declarations and other arrows, multiplicities or free-text/unlabeled links are outside this subset. Role names use the member identifier rules. Body fields/methods win collisions regardless of edge position, then the first accepted role wins. Relation fields follow body members. Comments, note bodies and nested blocks are ignored. At most 300 relationship fields are appended, within the existing class member cap. Recognized arrow lines not added (missing endpoints, invalid role, conflicts, duplicates or limits) increment relations_skipped. Unsupported grammar does not count. A novel candidate refused by either cap sets relations_capped; a class cap also sets members_capped. These are heuristic proposed fields, not recovered ownership, inheritance, runtime values or enforced cardinality. Relation mode additionally returns include_relations:true, relations_included, relations_skipped, relations_capped, relation_limit. Type/member counts include appended fields. False or omitted include_relations preserves the three existing source and response modes. It never writes, renders, fetches, or executes: one traversal-protected store read, pure filtering and emission, no new dependencies. Nothing lands outside the response until you save it with an explicit write. Still read-only with include_members=true or include_types=true. Args:
Returns: JSON with schema: { "relative_path": string, // POSIX form "language": "typescript", "source": string, // the scaffold; identical to the text block ("" when no emittable names) "entities": string[], // emitted class names in candidate order, capped "entities_included": number, // length of "entities" "entities_available": number, // valid candidates before the cap "entities_capped": boolean, // true when valid names were dropped by the cap "entity_limit": number, // the applied cap (max_entities, at most 60) "skipped_entities": string[], // invalid or reserved candidates, independent of the cap "skipped_count": number, // length of "skipped_entities" "confidence": "heuristic", "heuristic_warning": string, // candidate-only limitations by default; member-mode limitations when include_members=true; typed-mode limitations when include_types=true "written": false, // always false; save the source yourself // include_members=true only: // "include_members": true, // "members_included": number, // total emitted field+method stubs across emitted classes // "members_capped": boolean, // true when a 31st unique supported member was found // "member_limit": 30 // fixed per-class member cap // include_types=true only (implies the member keys above): // "include_types": true, // "typed_fields": number, // emitted fields with an accepted type label (name!: Type) // "unresolved_fields": number // emitted fields falling back to name: unknown } Names are emitted only when they match /^[A-Za-z_][A-Za-z0-9_]*$/ at most 60 characters and avoid reserved and TypeScript-forbidden class names. Other candidates are listed in skipped_entities without further renaming. An empty candidate set returns empty source. Examples:
Error Handling:
|
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 15 tools
Most tools target clearly distinct operations, and descriptions include explicit 'Don't use when' guidance that steers between near-pairs. The main soft spots are the export/save_export pair (return HTML vs write HTML) and the generation family (generate, generate_sequence, template, scaffold), which overlap conceptually but are differentiated by target artifact and source.
Every tool uses a consistent snake_case verb_noun pattern under a uniform 'diagrams_' prefix (create, get, update, delete, list, render, export, diff, generate, etc.). Naming is fully predictable with no mixed conventions.
15 tools sit at the top of the well-scoped range, but each covers a distinct capability (CRUD, render, export, diff, consistency, code-to-diagram generation, scaffolding, templates). No tool feels redundant or ceremonial for a rich diagram-management domain.
Full lifecycle coverage is present: list/get/create/update/delete for storage, plus render, export/save, diff, consistency checking, generation from code, and template discovery. The surface supports both authoring and review workflows with no obvious dead ends.