Skip to main content
Glama

langgraph-spec-toolkit

CI License: MIT Python 3.11+ Status: v0.2 alpha

An MCP server + Claude skill for building LangGraph projects by editing a structured YAML spec — not by regenerating Python from scratch on every turn.

edit spec.yaml (via MCP tools)  →  validate_graph  →  render_python  →  graph.py

Graph topology — nodes, edges, state schema, checkpointer — is data, not prose. An LLM agent should be able to add a node or rewire an edge with one small, targeted tool call, not re-emit 150 lines of Python and hope nothing upstream broke. spec.yaml is the source of truth; graph.py is a deterministic, regenerable build artifact you never hand-edit.

Quick look

Demo: init_project, apply_changes, validate_graph, and render_python run end to end, producing a deterministic graph.py

Four tool calls, zero hand-written Python for the graph wiring itself. (Regenerate with vhs .github/assets/demo.tape — see that file for a vhs 0.12.0 bug you may need to work around.)

$ uv run python .github/assets/demo.py
1) init_project - scaffold spec.yaml, nodes.py

2) apply_changes - nodes + edges wired in one round trip

3) validate_graph - catch problems before any code is emitted

   ok=True  issues=0

4) render_python - deterministic codegen, no LLM involved

   wrote demo_graph/graph.py

$ cat demo_graph/graph.py
"""Auto-generated by langgraph-spec-toolkit — DO NOT EDIT BY HAND.

Regenerate with the `render_python` MCP tool after changing spec.yaml.
Source spec: demo_graph
"""

from langgraph.graph import StateGraph, START, END
from typing import TypedDict
from . import nodes


class GraphState(TypedDict):
    pass


def build_graph():
    workflow = StateGraph(GraphState)

    workflow.add_node('greet', nodes.greet)
    workflow.add_node('respond', nodes.respond)

    workflow.add_edge(START, 'greet')
    workflow.add_edge('greet', 'respond')
    workflow.add_edge('respond', END)

    return workflow.compile()

Related MCP server: Oplink

Table of contents

Why

  • Real-world cost. Measured on a real Claude Code session's /cost output (not a synthetic estimate), in a fresh session with no prior history: building a small 2-node graph from scratch cost $0.1267 hand-writing graph.py directly, vs. $0.1291 through this toolkit's MCP tools (using apply_changes to wire nodes/edges in one call) — roughly at parity for this small, from-scratch case, which is close to the toolkit's least favorable scenario since there's no existing complexity yet for hand-written regeneration to be expensive.

  • Error rate. Free-form Python regeneration risks silently dropping an edge, mistyping a state key, or producing an unreachable node. A structured spec can be validated before any code is emitted.

  • Diffability. spec.yaml changes are small, reviewable diffs. A regenerated file's diff is often the whole file.

Installation

Requires Python 3.11+ and uv (which provides uvx).

Via uvx (recommended — no clone, no local install; uvx fetches langgraph-spec-toolkit from PyPI and runs it on demand):

{
  "mcpServers": {
    "langgraph-spec-toolkit": {
      "command": "uvx",
      "args": ["langgraph-spec-toolkit"]
    }
  }
}

From source (if you're developing on the toolkit itself):

git clone <this-repo>
cd langgraph-spec-toolkit
uv sync
{
  "mcpServers": {
    "langgraph-spec-toolkit": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/langgraph-spec-toolkit", "python", "-m", "mcp_server.server"]
    }
  }
}

Runtime dependencies are intentionally minimal: mcp, jinja2, pyyaml. render_python's output imports langgraph (and langchain-core, if your state uses message types) — those are dependencies of the project you're generating, not of this toolkit.

Usage

Either config above starts the MCP server (it speaks MCP over stdio) the moment your client connects — there's no separate "run the server" step to do by hand. If you want to smoke-test it directly:

uv run python -m mcp_server.server   # from a source checkout
uvx langgraph-spec-toolkit           # from PyPI

Then drive it through the tools below — or point Claude at skill/SKILL.md and let it drive itself. A typical session:

init_project(project_dir="my_graph", name="my_graph")
apply_changes(project_dir="my_graph", operations=[
    {"op": "add_node", "id": "start"},
    {"op": "add_node", "id": "respond"},
    {"op": "add_edge", "from_": "start", "to": "respond"},
    {"op": "add_edge", "from_": "respond", "to": "END"},
])
validate_graph(project_dir="my_graph")   # -> ok: true
render_python(project_dir="my_graph")    # -> writes my_graph/graph.py

...then write start/respond in my_graph/nodes.py and you have a runnable graph.

The spec format

spec.yaml:

name: simple_chatbot
entry_point: greet
state:
  - name: messages
    type: list[BaseMessage]
    reducer: add_messages
    default: []
nodes:
  - id: greet
    type: python
    config:
      function: greet          # callable in nodes.py; defaults to the node id
  - id: chatbot
    type: python
    config:
      function: chatbot
  - id: tools
    type: python
    config:
      function: call_tools
edges:
  - from: greet
    to: chatbot
  - from: chatbot
    condition: route_after_chatbot   # router fn in nodes.py
    paths:
      continue: tools
      end: END
  - from: tools
    to: chatbot
checkpointer:
  type: none                    # none | memory | sqlite | postgres

Node and router bodies are not generatedrender_python only owns topology, state, and wiring. You write the callables in the project's nodes.py, named to match config.function / condition. This keeps codegen deterministic: the same spec always renders to the same Python, and business logic never gets silently rewritten on a regen.

type on a state field is a raw Python type expression. A handful of common symbols — BaseMessage, AnyMessage, HumanMessage, AIMessage, SystemMessage, ToolMessage, ChatMessage, plus Any / Optional / Sequence / Union / Literal from typing — are recognized by name and auto-imported in the rendered file. reducer similarly recognizes add_messages and add / operator.add as built-ins; anything else is assumed to be a function you define in reducers.py.

MCP tools

Tool

Purpose

init_project(project_dir, name, state_fields?)

Scaffold spec.yaml, nodes.py, __init__.py.

add_node(project_dir, id, type?, config?, entry_point?)

Add/update a node. The first node added becomes entry_point automatically.

add_edge(project_dir, from_, to?, condition?, paths?)

Add a simple (to) or conditional (condition + paths) edge.

remove_node(project_dir, id)

Remove a node; cascades to delete edges touching it.

remove_edge(project_dir, from_, to?)

Remove edge(s) from a source, optionally to one target.

set_state_schema(project_dir, fields)

Replace the state schema wholesale.

apply_changes(project_dir, operations)

Apply several add_node/add_edge/remove_node/remove_edge/set_state_schema edits in one call — atomic (nothing written if any operation is invalid).

get_spec(project_dir)

Read-only fetch of the full current spec.

validate_graph(project_dir)

Run static checks; returns ok + a list of issues.

render_python(project_dir, output_path?)

Emit graph.py (default: <project_dir>/graph.py). Blocks on validation errors.

Note: edges use the parameter name from_, not from — the latter is a reserved word in Python. It still round-trips through the from: key in spec.yaml.

Note: the mutating tools (add_node, add_edge, remove_node, remove_edge, set_state_schema, apply_changes) return a compact summary (node/edge/state counts, entry point, checkpointer type) rather than the full spec — echoing the whole graph back on every small edit would grow with graph size and quietly erode the token savings this toolkit exists for. Call get_spec when you actually need the full picture.

Prefer apply_changes over separate calls whenever wiring more than one node/edge at once (e.g. a whole tool-calling loop) — it's the same edit, one round trip instead of several. See Why for the measured real-world cost. Each operation is a dict with an "op" key plus that operation's normal arguments, e.g. {"op": "add_node", "id": "tools", "config": {...}} — see the tool's own description for the full list. entry_point is set automatically (the first node added, or entry_point: true on a later add_node op) — don't add an edge from "START" yourself, even though rendered graph.py contains one; that edge is derived from entry_point, not wired as a spec edge.

Validation

validate_graph checks for:

  • Unreachable nodes — no path from entry_point.

  • Missing path to END — a node that can never terminate the graph.

  • Dangling conditions — a conditional edge with no paths, or a paths target that isn't a real node id (or END).

  • State/id typos — duplicate node ids, duplicate state field names, an entry_point that doesn't match any node id, an unknown checkpointer type.

  • Unsafe identifiersconfig.function, a conditional edge's condition, a state field's name, and a non-builtin reducer are all spliced into the generated Python unquoted (e.g. nodes.<function>), so each must be a valid Python identifier; a state field's type must at least parse as a Python expression. This is a correctness and safety check — it's the boundary that keeps a bad spec value from becoming arbitrary code in graph.py.

render_python refuses to emit code while validation errors are present; warnings (like an unreachable node) don't block rendering.

Example

examples/simple_chatbot has a spec with a message-reducer state field, a linear edge, and a conditional tool-call loop, plus the generated graph.py — diff the two to see exactly what codegen does. It's been exercised end-to-end against a real langgraph + langchain-core install to confirm the generated wiring executes, not just that it parses.

Development

uv sync
uv run python -m mcp_server.server   # smoke-test the server starts
uv run pytest                        # run the test suite
uv run ruff check .                  # lint

The test suite (tests/) covers spec.py (dataclasses, YAML round-trips), validator/ (every check, including the identifier/injection-safety ones), renderer/ (codegen against the committed example, plus each reducer/ checkpointer variant), every MCP tool's run() function, and MCP tool registration itself. New tools or spec fields should come with tests in the matching file.

CI (.github/workflows/ci.yml) runs lint and the test suite (on Python 3.11 and 3.12) on every push and pull request against main.

Releasing

Publishing to PyPI (.github/workflows/publish.yml) uses Trusted Publishing — no API token is stored in this repo. One-time setup (maintainers only):

  1. On pypi.org, add a trusted publisher for this project: owner mkrishna-gs, repo langgraph-spec-toolkit, workflow publish.yml, environment pypi. (If the project doesn't exist on PyPI yet, PyPI supports adding a trusted publisher for a not-yet-published project name — it claims the name on first publish.)

  2. In this repo's GitHub settings, create an environment named pypi (optionally with required reviewers, for an extra manual gate before every publish).

After that, cutting a release is the whole process:

  1. Bump version in pyproject.toml.

  2. Tag and push, then publish a GitHub Release from that tag (or use gh release create).

  3. publish.yml builds the sdist/wheel and publishes them automatically.

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md for the project layout, dev setup, and the checklist to run through before opening a PR.

License

MIT

Available Tools

10 tools
add_edgeA

Add an edge between nodes.

Simple edge: set to (a node id, or "END"). Conditional edge: set condition (the name of a router function in nodes.py) and paths (a mapping of the router's return value to a target node id or "END").

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
from_Yes
pathsNo
conditionNo
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden. It mentions conditions and paths but does not disclose what happens when invalid inputs are given, whether edges can overwrite existing ones, or any validation behavior. It also doesn't mention the return value or side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: an introductory sentence followed by bullet-like lines for each edge type. Every sentence adds value, and the most important information (how to specify each type) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, but the description doesn't mention what the tool returns, which might be important for agents. It also lacks behavioral details like validation or error handling. Given the complexity of conditional edges, the description covers the main usage but misses edge cases and side effects.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description must compensate for all parameters. It does explain 'to', 'condition', and 'paths' in context (e.g., 'to' is a node id or END), but it does not explain 'project_dir' and 'from_' at all. The description adds value for some parameters but leaves others undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool adds an edge between nodes and distinguishes between simple and conditional edges, which is a specific verb and resource. However, it does not explicitly contrast with siblings like remove_edge, but the purpose is clear enough.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance on when to use simple vs conditional edges, explaining the required parameters for each case. It does not explicitly mention alternatives, but the context is sufficient for an agent to decide which parameters to set.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_nodeB

Add or update a node. config['function'] names the callable in nodes.py (defaults to the node id if omitted).

The first node added to a project becomes the entry point automatically; pass entry_point=True to (re)designate a later node instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
typeNopython
configNo
entry_pointNo
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden. It discloses two important behaviors: config['function'] defaults to node id, and the first node auto-becomes entry point. However, it does not disclose whether 'update' overwrites existing config, whether it validates the callable exists, or any side effects on edges.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loads the primary action, then explains the two non-obvious behaviors. Every sentence earns its place, though the entry-point rule could be more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema and 5 parameters, but no annotations. The description covers the most subtle behaviors (config function resolution and entry point designation) but omits update semantics, error conditions, and relationship to project initialization. Adequate for basic use, incomplete for edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains config['function'] and entry_point semantics, but leaves id, type, and project_dir meanings to the schema. The description adds value for two of five parameters, which is partial compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb+resource ('Add or update a node') and explains the key config['function'] behavior, which distinguishes it from graph-structure tools like add_edge/remove_node. It doesn't explicitly contrast with siblings, but the resource and behavior are specific enough to be identifiable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context: it is for adding/updating nodes, and the entry-point rule tells when to use entry_point=True. However, it does not explicitly state when to prefer alternatives like remove_node or validate_graph, nor does it mention prerequisites like project initialization.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_changesA

Apply several spec edits in one call instead of one add_node/add_edge/... call each.

Prefer this over separate calls whenever wiring more than one node/edge at once (e.g. adding a whole tool-calling loop) — it's the same edit, one round trip instead of several.

operations is a list, applied in order against one loaded spec and saved once at the end. Nothing is written if any operation is invalid (bad op name, missing required field, dangling reference) — the whole batch is atomic. Each entry is a dict with an "op" key plus that operation's normal arguments:

{"op": "add_node", "id": "tools", "config": {"function": "call_tools"}} {"op": "add_edge", "from_": "chatbot", "condition": "route", "paths": {"continue": "tools", "end": "END"}} {"op": "add_edge", "from_": "tools", "to": "chatbot"} {"op": "remove_node", "id": "..."} {"op": "remove_edge", "from_": "...", "to": "..."} {"op": "set_state_schema", "fields": [...]}

entry_point is set automatically (the first node added, or pass entry_point=true on a later add_node op) — don't add an edge from "START" yourself, even though rendered graph.py contains one; that edge is derived from entry_point, not wired as a spec edge.

Returns a compact summary (counts), like the other mutating tools — call get_spec if you need the full picture afterward.

ParametersJSON Schema
NameRequiredDescriptionDefault
operationsYes
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, this description carries the full behavioral burden. It discloses atomicity ('Nothing is written if any operation is invalid'), ordering ('applied in order'), persistence ('saved once at the end'), automatic entry_point derivation, and the compact summary return. This is a thorough behavioral contract for a mutating batch tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately long but every sentence carries instructional weight: usage guidance, atomicity, operation format, entry_point caveat, and return behavior. The front-loaded purpose and clean example block make it easy to scan, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multi-operation batching with atomic semantics) and an existing output schema, the description covers all necessary operational details: operation set, ordering, atomicity, entry_point handling, and post-call guidance. An agent can invoke it correctly and predict its side effects without needing additional information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates richly for the `operations` parameter with a full format spec and concrete examples for add_node, add_edge, remove_node, remove_edge, and set_state_schema. However, `project_dir` is never explained beyond its name in the schema, leaving a small gap in an otherwise strong parameter narrative.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Apply several spec edits in one call' and explicitly contrasts with individual add_node/add_edge calls, naming the sibling tools it replaces. This makes the batch-mutation purpose unmistakable and differentiates it from the single-edit siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear when-to-use rule ('whenever wiring more than one node/edge at once') and mentions the alternative of separate calls. It also explains when not to fabricate a START edge, and routes to get_spec for full results, leaving no ambiguity about selection or follow-up.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_specA

Read-only fetch of the full current spec.

Mutating tools (add_node, add_edge, remove_node, remove_edge, set_state_schema) return a compact summary (counts), not the full spec, to keep per-edit response cost flat as the graph grows. Call this when you actually need the whole picture.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly declares the operation is read-only, explains that the return is the full spec rather than a summary, and gives the design rationale about per-edit response cost. It does not discuss error conditions or permissions, but the core behavioral traits are well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and then adds a tightly relevant paragraph explaining the contrast with mutating tools. Every sentence earns its place, and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read-only tool with an output schema available, the description covers the main behavioral context: what it retrieves, when to call it, and how it differs from siblings. The missing parameter documentation is a minor gap given the self-explanatory project_dir name, but the tool is otherwise fully understandable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not mention project_dir at all. The parameter name and title ('Project Dir') give some minimal hint, but the description fails to compensate for the absence of schema documentation, such as what the path should point to or any required format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: "Read-only fetch of the full current spec." It also distinguishes itself from sibling mutating tools by noting they return compact summaries, making it clear this tool provides the complete graph state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool: "Call this when you actually need the whole picture." It also explains that mutating tools (add_node, add_edge, remove_node, remove_edge, set_state_schema) return only counts, which tells the agent when those alternatives are more appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

init_projectA

Create a new spec-driven LangGraph project: spec.yaml, nodes.py stub, init.py.

project_dir: directory to create/use (created if missing; error if a spec.yaml already exists there). name: project/graph name, stored in spec.yaml. state_fields: optional initial state fields, each {name, type, reducer?, default?}.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
project_dirYes
state_fieldsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It explains that project_dir is created if missing, errors if spec.yaml already exists, and details how name and state_fields are used. It does not mention whether other files are overwritten or permissions required, but the error condition on spec.yaml suggests safe creation. This is reasonably transparent for a scaffold tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose, followed by parameter explanations. Each sentence carries necessary information—creation artifacts, error condition, and parameter details. It is slightly verbose in the parameter block but remains efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an initialization tool with an output schema (not shown), the description covers all necessary aspects: purpose, parameters, error behavior, and file outputs. It does not mention what the return value looks like, but since an output schema exists, that is acceptable. It could be more explicit about side effects (e.g., creating directories) but overall it is complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, so the description must fully compensate. It does: each parameter (project_dir, name, state_fields) is explained with its role, constraints, and expected structure (e.g., state_fields items have name, type, reducer?, default?). This adds meaning far beyond the bare schema titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates a new spec-driven LangGraph project and enumerates the artifacts it generates (spec.yaml, nodes.py stub, __init__.py). This distinguishes it from sibling tools that modify or inspect an existing project, so an agent can immediately recognize it as the setup/initialization tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for new projects by noting that an error occurs if spec.yaml already exists, which effectively warns against reuse. However, it does not explicitly state when to prefer this tool over siblings (e.g., 'use for initial scaffolding') or mention any alternatives. The error condition provides partial guidance but the exclusion logic is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_edgeA

Remove edge(s) from a source node. Omit to to remove all edges from that source.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
from_Yes
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It reveals a key behavioral nuance: omitting `to` removes all edges from the source, which is not obvious from the schema alone. However, it does not mention error handling, side effects, or what happens if the edge or node does not exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences with zero filler. The primary action is front-loaded, and the optional behavior is stated immediately after, making it easy for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation tool, the description covers the core behavior and the optional parameter's effect. The output schema exists, so return values are not needed. The only gap is the unaddressed `project_dir` parameter and edge-case behavior, but these are minor for this tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explicitly explains the `to` parameter (optional, and omission removes all edges), and `from_` is clearly implied as the source node. However, `project_dir` is not explained, leaving its purpose unclear despite being required.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Remove edge(s) from a source node.' It specifies the verb (remove), the resource (edge), and the context (source node), distinguishing it from sibling tools like remove_node and add_edge without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a usage hint for the `to` parameter ('Omit `to` to remove all edges'), but it does not explicitly state when to use this tool versus alternatives like remove_node or add_edge. The usage is implied by the name and description rather than directly addressed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_nodeA

Remove a node, cascading to delete any edges that touch it.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral disclosure burden. It meaningfully discloses that the operation is destructive to edges as well as the node, which is the most important side-effect. It does not discuss failure behavior or irreversibility, but the core cascading behavior is clearly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence, front-loaded with the primary action and immediately followed by the critical side-effect. Every word earns its place; there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with an output schema, the core semantics are covered. However, the description leaves project_dir's role and the node-identification semantics implicit, and it does not state what happens if the node does not exist. This is acceptable but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description adds no meaning to either parameter. 'id' and 'project_dir' are only explained by their names, so an agent must infer that 'id' identifies the node and 'project_dir' locates the containing project. The description should have compensated for the missing parameter docs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Remove a node') and the key side-effect (cascading deletion of edges). It is clearly distinguishable from sibling tools like remove_edge, since it targets a node and explicitly handles edge cleanup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than explicit: the 'cascading' phrase suggests this is the right tool when both a node and its touching edges should be removed, versus remove_edge for edges alone. No explicit when-to-use or when-not-to-use guidance is provided, but the context is inferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_pythonA

Render the current spec into idiomatic LangGraph Python (graph.py by default).

Deterministic Jinja2 templating — no LLM involved, same spec always produces the same code. Blocks if the spec has validation errors (warnings still allow rendering).

ParametersJSON Schema
NameRequiredDescriptionDefault
output_pathNo
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does add meaningful behavioral context: deterministic Jinja2 templating, no LLM involvement, and error-blocking versus warning-tolerant rendering. It does not explicitly describe file overwriting or other side effects, but the default output path and rendering behavior are clearly disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three short, meaningful sentences with the core purpose front-loaded. The second sentence about determinism and validation behavior earns its place and adds no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value documentation is not required. However, for a tool with no annotations that appears to write files, the description does not state how project_dir and output_path interact or whether an existing graph.py is overwritten. It covers validation behavior well but lacks full file-handling context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for undocumented parameters. It only clarifies the output_path default via 'graph.py by default' and leaves project_dir and custom output_path behavior largely unexplained. This is partial compensation at best.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action and resource: rendering the current spec into idiomatic LangGraph Python, defaulting to graph.py. This distinguishes it from sibling tools like get_spec and validate_graph, which inspect or validate rather than generate code.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool should be used after the spec is valid, since it blocks on validation errors, but it never explicitly says when to use it or when to prefer a sibling tool. No alternatives or exclusions are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_state_schemaA

Replace the graph's state schema wholesale.

Each field: {name, type, reducer?, default?}. type is a raw Python type expression (e.g. "str", "list[str]"); reducer names a reducer function (e.g. "add_messages", or a custom name defined in reducers.py).

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full disclosure burden. It does convey the destructive nature ('replace wholesale') and documents the field contract ({name, type, reducer?, default?}) plus the type/reducer syntax. However, it omits error behavior (e.g., invalid Python type expressions), validation of the schema, and side effects on nodes referencing old fields. The documented field structure adds genuine value, but coverage is incomplete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with the core purpose front-loaded in the first sentence and supporting field details in the following two. No filler or redundant phrasing; each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value documentation is not required. The description covers the input contract for 'fields' but lacks error-condition disclosure and side-effect context (what happens to existing nodes or references after a wholesale schema swap). For a schema-replacement mutation, this is a meaningful gap, though the tool has only two parameters and moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does substantially for 'fields' by defining each sub-field's shape and the exact syntax of 'type' and 'reducer' with examples. However, 'project_dir' receives zero explanation—no hint that it is the project path or how it is used. The main parameter is richly documented, but one of the two required parameters is ignored.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope: 'Replace the graph's state schema wholesale.' This clearly distinguishes it from sibling tools like add_node/add_edge (which mutate graph structure) and init_project (project setup). The 'wholesale' qualifier precisely conveys full replacement, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states what the tool does but gives no guidance on when to choose it over alternatives, and never names a sibling or an exclusion condition. There is no mention of when incremental updates would be preferable or when this wholesale replacement is appropriate. Usage context is entirely implied by the purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_graphA

Check the spec for unreachable nodes, missing paths to END, dangling conditions/edges, and duplicate/typo'd ids. Returns ok=False if any errors (as opposed to warnings) are found.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_dirYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must carry the burden of behavioral disclosure. It explains that the tool returns ok=False if errors are found, and distinguishes errors from warnings, which is useful. However, it doesn't specify what 'errors' vs 'warnings' mean in this context, nor does it explain whether the tool performs any side effects (likely none, but it's not stated). Since it's a validation tool, it's presumably read-only, but that's implicit, not explicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, with the first sentence defining the purpose and the second detailing the return behavior. It's concise, front-loaded with the action and scope, and every phrase adds value. No redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a validation function with a single simple parameter and an output schema (which likely describes the return structure). Given its complexity, the description covers the core functionality (what is validated, what the result means). It doesn't provide examples or elaborate on warning vs error categories, but for a validation tool, this is reasonably complete. The output schema exists, so return details are structured elsewhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage for the only parameter 'project_dir', so the description must compensate. The description does not explain 'project_dir' beyond its name, but the name is self-explanatory (the directory containing the spec). Given the parameter's simplicity, the missing explicit description is a minor gap. Still, the description doesn't add any additional meaning beyond the schema, but the schema itself is minimal, so the baseline is 4 due to low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('validate') and resource ('the spec'), and lists the specific error types it checks for (unreachable nodes, missing paths to END, dangling conditions/edges, duplicate/typo'd ids). This distinguishes it from sibling tools like get_spec or init_project, though it doesn't explicitly name a sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use it (when you need to validate the spec for errors), but it doesn't explicitly state when to use it versus alternatives or when not to use it. It also doesn't mention typical triggers like 'after making changes' or 'before rendering'. The context is clear enough but lacks explicit routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.2.0
    • Addedapply_changes
  2. 9 tool updatesv0.1.0
    • First observedadd_edge
    • First observedadd_node
    • First observedget_spec
    • First observedinit_project
    • First observedremove_edge
    • First observedremove_node
    • First observedrender_python
    • First observedset_state_schema
    • First observedvalidate_graph

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct operation: adding/removing nodes and edges, setting schema, fetching the spec, validating, rendering, initializing, and batch-applying changes. Even apply_changes is clearly scoped as a batch wrapper with explicit op names, so no tool is easily confused with another.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: add_node, remove_edge, set_state_schema, get_spec, validate_graph, render_python, init_project, apply_changes. There are no style deviations or vague verbs.

Tool Count5/5

Ten tools is well-scoped for a LangGraph spec toolkit. Each tool covers a necessary piece of the workflow without redundancy, and the count supports both simple edits and batching without feeling bloated.

Completeness5/5

The toolkit covers the full graph-building lifecycle: project creation, node and edge CRUD, state schema management, validation, rendering to Python, and full-spec inspection. The batch apply_changes tool also fills the practical gap of multi-edit workflows.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables orchestration of MCP tool calls through declarative YAML-defined directed graphs with data transformation, conditional routing, and observable execution flows.
    57 npm
    22
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables creating no-code agent workflows by combining multiple MCP servers into unified YAML-defined tools. Supports parameterized prompts and scripted steps, exposing a single MCP endpoint that orchestrates external servers like Chrome DevTools and shadcn.
    10
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    A local, auditable multi-model workflow engine that lets you define YAML graphs for orchestrating LLM agents across vendors, with MCP tools for validation, dry-runs, execution, and human approval, all fully observable in a local web interface.
    8
    3
    Apache 2.0