arch-mcp
Parses and indexes C++ source files into the architecture graph for dependency, impact, and affected-test analysis.
Indexes Dockerfiles and the container images they build as graph nodes, supporting dependency and deployment impact analysis.
Reads repository Git metadata and compares graph snapshots between Git refs for diffing changes.
Detects Gradle projects via settings.gradle and build.gradle manifests when determining workspace roots.
Parses GraphQL API contracts into API operation nodes and reference edges for architecture analysis.
Parses and indexes JavaScript source files and import relationships into the architecture graph.
Parses and indexes Kotlin source files into the architecture graph for dependency and impact analysis.
Parses Kubernetes configs and workloads, modeling deployment relationships to container images.
Indexes Markdown documents as documentation nodes and reference targets in the repository graph.
Parses and indexes PHP source files into the architecture graph for dependency and impact analysis.
Parses PostgreSQL DDL and SQL statements, modeling tables, views, reads, and writes in the graph.
Parses and indexes Python source files into the architecture graph for dependency and impact analysis.
Parses and indexes Ruby source files into the architecture graph for dependency and impact analysis.
Parses and indexes Rust source files into the architecture graph for dependency and impact analysis.
Parses Swagger/OpenAPI API contracts into API operation nodes for architecture and impact analysis.
Parses Terraform resources behind a flag, adding infrastructure service nodes to the graph.
Parses and indexes TypeScript source files and import relationships into the architecture graph.
Indexes CI YAML configuration files as configuration nodes for infrastructure and dependency analysis.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@arch-mcpwhat does changing src/index.ts break?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
arch-mcp
Maps your repo's architecture — files, imports, SQL, APIs — and shows what a change breaks.

arch-mcp is an MCP server over stdio. It indexes a workspace into a graph of files, modules, symbols, database tables, API contracts, container and CI files, then answers questions about that graph: what depends on this file, which tests a change touches, what two snapshots differ by.
Features
Find what a change breaks. impact returns the transitive dependents of the files you changed, affected_tests narrows that to test files (src/index.ts:90-119).
One graph across stacks. 22 adapters read JavaScript/TypeScript, Python, nine more languages through wasm grammars, SQL, API contracts, manifests, Dockerfile, Kubernetes, CI YAML, Markdown and SCIP indexes (src/core/adapters/registry.ts:67-89).
Answers state their own coverage. Every response carries index.coverage and index.kinds, so you can tell a missing edge from a missing adapter (src/core/envelope.ts:59, src/core/envelope.ts:162-173).
Your repository stays untouched. The server only reads: the cache lives in %LOCALAPPDATA%\arch-mcp\cache\<sha1(repo)> and nothing is written back (src/cache.ts:8-11).
Responses respect a byte budget. max_bytes defaults to 65536 with a hard cap of 1048576; a truncated answer always carries truncated: true and a hint (src/config.ts:35-40).
Related MCP server: UCN
What it sees
Every node is addressed as kind:path#symbol in repo-relative POSIX form (src/core/adapters/types.ts:2).
Nodes (11)
Kind | What it is |
| A source file or manifest on disk |
| An importable module, one per source file in the tree-sitter pipeline |
| A dependency: a manifest entry, a container image, or a CI action |
| A function, class or type declaration found by tree-sitter or SCIP |
| A SQL table |
| A SQL view |
| One API operation from an OpenAPI, Swagger, proto, GraphQL or AsyncAPI contract |
| A configuration object: a CI file, a Kubernetes config referenced by |
| A Markdown document |
| A deployable unit: an API service, a Kubernetes workload, a Terraform resource |
| A Dockerfile or the image it builds |
Source: src/core/adapters/types.ts:5-16.
Edges (10)
Edge | In plain words | Emitted today |
| File A uses file B | yes ( |
| Function A calls function B | yes ( |
| SQL: a table or view is read; with sqlglot on, the edge also carries columns | yes ( |
| SQL: a table or view is written, with columns under sqlglot | yes ( |
| An API operation, an infrastructure file, a document, or a package dependency points at an object | yes ( |
| A Kubernetes workload deploys an image | yes ( |
| Class or interface inheritance | no |
| Interface implementation | no |
| Configuration of another object | no |
| A test covers a target | no |
The last four edges are declared in the type system, but no adapter emits them yet. The index.kinds block reports them honestly as not_emitted with an empty emitter list (src/core/adapters/registry.ts:116-117, src/core/adapters/registry.ts:121, src/core/adapters/registry.ts:123).
Coverage you can trust
The server never claims a complete picture it cannot back up.
Each response carries
index.coveragewithfiles_seen,parsedandunsupported, plusindex.kindswith the status of every edge kind (src/core/envelope.ts:59,src/core/envelope.ts:171-173).An empty graph is reported as
index.state = "partial", not as an error (src/core/envelope.ts:162-171).Files a parser could not handle are listed by name in
coverage.unsupported, and an adapter that failed turns the matching edge kind intounsupportedinstead ofno_matches(src/core/envelope.ts:130-154).A kind with no emitters at all shows up as
not_emitted(src/core/envelope.ts:130-132).
Supported layers: JavaScript/TypeScript, Python, nine languages through wasm tree-sitter grammars (C, C++, C#, Go, Java, Kotlin, PHP, Ruby, Rust), SQL (DML plus PostgreSQL DDL), API contracts (OpenAPI, Swagger, proto, GraphQL, AsyncAPI), Dockerfile, Kubernetes, CI YAML, Terraform behind a flag, Markdown, and SCIP indexes.
The invariants are covered by tests/envelope.test.mjs and tests/kinds.test.mjs; the suite has 35 files and 241 tests in tests/.
Quick start
npm install
npm run build
npm run bootstrap
npm testnpm install pulls runtime and dev dependencies. npm run build writes dist/server.mjs, dist/cli.mjs and dist/lib.mjs with esbuild. npm run bootstrap installs the pinned toolchain (dependency-cruiser 18.7.0) into ./toolchain and is idempotent. npm test runs the node test suite (package.json:14, package.json:16, package.json:17).
Connect your MCP client
The server speaks stdio through dist/server.mjs. An opencode v2 config entry looks like this:
{
"mcp": {
"servers": {
"arch-mcp": {
"type": "local",
"command": ["node", "E:/1_Products/arch-mcp/dist/server.mjs"]
}
}
}
}Replace the path with your own checkout. The MCP layer is thin: the tools are registered in src/index.ts:137-141 and executed through src/server_core.ts.
Tools
Tool | Arguments | Returns |
|
| Stacks, git info, index coverage, adapters |
|
| Graph plus |
|
| Graph nodes matching a case-insensitive substring |
|
| Incoming and outgoing edges of one node, |
|
| Reverse reachability: who depends on the target, |
|
| Transitive dependents of changed files |
|
| Test files depending on the change; an empty result carries a |
|
| Added and removed nodes and edges between two refs |
Source: src/index.ts:14-135.
Response envelope
{
"ok": true,
"workspace": "E:/work/my-service",
"root_used": "E:/work/my-service",
"roots": ["E:/work/my-service"],
"schema_version": 6,
"index": {
"state": "ready",
"progress": { "percent": 100, "complete": true },
"coverage": { "files_seen": 226, "parsed": 226, "unsupported": [] },
"adapters": [{ "name": "git", "status": "ok", "version": null }],
"missing": []
},
"data": {},
"truncated": false,
"_meta": { "provenance": { "command": "arch_status", "cwd": "E:/work/my-service", "ts": "…", "cached": false, "exit_code": 0 } }
}Failures come back as {"ok": false, "error": {"code", "message", "hint", "candidates"}} with one of the codes WORKSPACE_NOT_FOUND, NODE_NOT_FOUND, AMBIGUOUS_NODE, INVALID_ARGUMENT, ADAPTER_UNAVAILABLE, INDEX_BUILDING, BUDGET_EXCEEDED, SNAPSHOT_NOT_FOUND, EXTERNAL_TOOL_FAILED (src/core/errors.ts:2-11, src/core/errors.ts:27).
An empty graph gives index.state = "partial" (src/core/envelope.ts:162-171). An answer over the byte budget carries truncated: true and a hint that says to raise max_bytes (src/tools/get_graph.ts:40-59).
index.kinds
index.kinds always holds ten entries in EdgeKind order. Each entry has kind, status, edges, confidence, confidence_min and emitters (src/core/envelope.ts:30, src/core/envelope.ts:100-127). status is one of:
emitted: edges exist;no_matches: no edges, and every emitter for that kind ran;unsupported: no edges, and at least one emitter failed;not_emitted: the kind has no emitters in the registry at all (src/core/envelope.ts:130-154).
The invariant sum(kinds.edges) == graph.edges.length is checked by tests/kinds.test.mjs.
Only index.state = "building" breaks the rule of ten entries: a cold arch_status answers immediately with empty kinds, adapters and missing, zero coverage and data.graph = null, while the index builds in the background (src/core/envelope.ts:182-197, src/tools/get_graph.ts:429-443).
Workspace discovery
workspace is optional. A .git directory anywhere above the working directory wins and is returned at once. Otherwise the server walks up to the nearest manifest (package.json, pyproject.toml, requirements.txt, settings.gradle*, build.gradle*) or to a directory with at least three source files. Markdown, JSON and YAML files do not make a root. No root means WORKSPACE_NOT_FOUND (src/core/workspace.ts:7-12, src/core/workspace.ts:105-112, src/core/workspace.ts:152-163).
A container without its own root resolves into child roots: the envelope reports roots[] and root_used. ARCH_MCP_ALLOWED_ROOTS turns discovery into an allowlist, and a path outside it answers WORKSPACE_NOT_FOUND (src/core/workspace.ts:179-190, src/core/workspace.ts:228-244).
Adapters
All 22 adapters are built in and register at module load, so index.adapters reflects the registry at runtime (src/core/adapters/registry.ts:60-89). An adapter with no matching files reports absent and stays out of index.adapters and missing[] (src/core/envelope.ts:115-117). A broken grammar or ABI mismatch lands in missing[] with state: partial while the core keeps answering (src/core/envelope.ts:150-173).
Adapter | Formats | Precision | What it adds |
| SCIP | semantic |
|
| git repository | manifest | HEAD and status metadata; no edges |
| JavaScript/TypeScript | syntax | import edges, type-only ones included |
| OpenAPI/Swagger, AsyncAPI, GraphQL SDL, | syntax |
|
| CI YAML | syntax |
|
| Dockerfile | syntax |
|
| Markdown | syntax |
|
| Kubernetes YAML | syntax |
|
| TOML/JSON manifests | manifest |
|
| SQL DML, PostgreSQL DDL | syntax |
|
| Terraform HCL | syntax |
|
| C | syntax |
|
| C++ | syntax | same |
| C# | syntax | same |
| Go | syntax | same |
| Java | syntax | same |
| Kotlin | syntax | same |
| PHP | syntax | same |
| Python | syntax |
|
| Ruby | syntax | same as the generic languages |
| Rust | syntax | same |
| JavaScript/TypeScript | syntax |
|
Third-party licenses per dependency are listed in THIRD_PARTY_NOTICES.md; grammars/LICENSE holds the grammar provenance and grammars/SHA256SUMS the binary hashes.
Type-only dependencies
Edges whose dependencyTypes contain type-only get meta.type_only = true. focus, reaches, impact and affected_tests exclude them unless you pass include_type_only: true. Collecting them needs depcruiser with options.parser = tsc, otherwise import type statements never reach the graph (src/adapters/depcruiser.ts:77-83).
Snapshots and arch_diff
arch_snapshot computes snapshot_id = SHA256(graph JSON + git HEAD + adapter versions) and stores the snapshot in the cache. arch_diff compares two refs: current, git HEAD (a hex string of 7 to 39 characters, an ambiguous prefix yields AMBIGUOUS_NODE with candidates), or a snapshot_id. A missing snapshot yields SNAPSHOT_NOT_FOUND, a malformed ref yields INVALID_ARGUMENT; arbitrary git revisions such as HEAD~1 are v1.1 (src/core/snapshots.ts:11-12, src/core/snapshots.ts:136-139, src/core/snapshots.ts:171-175).
CLI
node dist/cli.mjs <status|snapshot|search|focus|reaches|impact|affected-tests|diff> [--workspace <path>] [--json]
node dist/cli.mjs bootstrapOptions include --json, --scope, --query, --kind, --node, --target, --changed, --limit, --max-depth, --depth, --max-bytes, --include-type-only, --from and --to. Exit codes: 0 on success, 1 on a contract error, 2 on a usage error (src/cli.ts:8-26, src/cli.ts:155-187). Without ARCH_MCP_MAX_RESPONSE_BYTES the budget is 65536, and status prints the line budget: 65536 (src/cli.ts:135).
Sample call arguments:
{ "name": "impact", "arguments": { "workspace": "E:\\work\\my-service", "changed": ["server/src/limits.ts"], "depth": 3 } }
{ "name": "affected_tests", "arguments": { "workspace": "E:\\work\\my-service", "changed": ["server/src/limits.ts"] } }Configuration
Variable | Default | Meaning |
|
| Stack filter: |
|
| Timeout for every external process |
|
| Response budget, cap |
| not set | Workspace allowlist separated by |
|
| Cache root override for graphs and snapshots |
| off |
|
| off | Installs the toolchain automatically when missing |
|
| wasm grammar directory override |
| not set | Directory or |
| not set | Indexer command template with |
| off |
|
| off |
|
|
| Interpreter for the sqlglot bridge |
|
| Bridge path override; the file content joins the cache key |
Most variables are read in src/config.ts:42-70; the root allowlist is read in src/core/workspace.ts:179.
What v1 does not do
Run your code. No tests, builds or scripts from the repository; external processes go through one runner, and the trusted core uses git read-only and depcruise (
src/core/exec.ts:5-12).Generate a SCIP index by default. The adapter reads a ready index; an external indexer runs only with
ARCH_MCP_SCIP_INDEXERandARCH_MCP_ALLOW_EXEC=1(src/config.ts:67-70).Write into the repository. Tools only read the workspace; the cache and snapshots stay outside it (
src/cache.ts:8-11).Diff arbitrary git revisions.
arch_diffcoverscurrent,HEADandsnapshot_id(src/core/snapshots.ts:171-175).Drive the Terraform CLI. The adapter parses HCL through
@cdktf/hcl2json; noplan,validateorapplycall is made (src/adapters/infra/terraform.ts:2-3,src/adapters/infra/terraform.ts:78).
Notes and limits
Cache key. Git HEAD, mtimes of changed files, toolchain version, config hashes, the adapter signature,
GRAPH_SCHEMA_VERSIONand the package version (src/cache.ts:112-131). A non-git workspace is keyed by a sha256 signature over all files exceptnode_modulesand.git, so an edit that keeps mtime and size does not invalidate the cache (src/cache.ts:185-196).Build artifacts reach the graph. Only
node_modulesand.gitare excluded from that signature, so.next/and friends are indexed (src/cache.ts:185-190).Schema versions.
SCHEMA_VERSION = 6moves with the response shape,GRAPH_SCHEMA_VERSION = "graph-9"only with the graph or cache entry shape (src/core/envelope.ts:15-19,src/cache.ts:31).Single flight. Identical concurrent calls share one run (
src/tools/get_graph.ts:308-423); a cache hit marks the evidence command with a(cached)suffix and setsprovenance.cached(src/tools/get_graph.ts:361,src/provenance.ts:31).Non-blocking build. The tree-sitter pipeline yields to the event loop every eight files, so a cold
arch_statusanswers within seconds and the graph builds in the background (src/core/adapters/tree-sitter/generic.ts:165,src/tools/get_graph.ts:442-443).
License
MIT (LICENSE:1-3). Third-party components and their licenses are listed in THIRD_PARTY_NOTICES.md.
Available Tools
8 toolsaffected_testsA
Test files transitively depending on changed files (type-only excluded by default). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| changed | Yes | Changed paths inside the workspace | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd | |
| include_type_only | No | Include type-only edges (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden; it does disclose 'Read-only' and the default exclusion of type-only edges, which is genuinely useful. However, it says nothing about truncation or response-budget behavior despite max_bytes governing that, nor about the shape/ordering of results, which are the main behavioral risks here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with zero filler, and the core behavior is stated first. Nothing in it is redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description could have said what the response looks like (a list of test paths) and what happens when the byte budget is exceeded. For a moderate-complexity query with fully documented params, it is adequate but leaves real gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented, including the max_bytes default/max and the workspace discovery rule. The description only restates the include_type_only default, adding no meaning beyond the schema; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a precise resource and scope: test files that transitively depend on changed files, with a default exclusion of type-only edges. An agent can tell this is a dependency-query tool rather than a mutation or status tool. It stops short of naming how it differs from siblings like impact or reaches, which also sound dependency-related.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent infers 'call this after a change to find which tests to run.' There is no explicit when-to-use, when-not-to-use, or pointer to the sibling tools (impact, reaches, focus) that could be confused with it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
arch_diffA
Diff two snapshots (current | git HEAD | snapshot_id): added/removed nodes and edges. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Target ref: "current" | git HEAD | snapshot_id | |
| from | Yes | Baseline ref: "current" | git HEAD | snapshot_id | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral disclosure burden. It usefully states that the tool is read-only and describes the diff output as added/removed nodes and edges, but it omits details such as error behavior, permissions, or whether any limits apply beyond the schema-documented max_bytes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence plus 'Read-only', with the core action and output front-loaded. There is no unnecessary wording and every clause contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only diff tool with a fully described schema and no output schema, the description covers the essential action, accepted refs, and returned difference categories. It is largely complete, though it could say more about error or truncation behavior when max_bytes is exceeded.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents from, to, max_bytes, and workspace. The description repeats the ref values but adds no meaning beyond what the schema provides, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: diffing two snapshots and returning added/removed nodes and edges. Its purpose is clear, but it does not explicitly distinguish itself from siblings such as arch_status or arch_snapshot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool by explaining that it diffs snapshots and accepts current, git HEAD, or snapshot_id refs. However, it gives no explicit guidance on when to choose this over related tools like arch_snapshot or arch_status, and no exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
arch_snapshotB
Architectural snapshot: stacks, git, graph and snapshot_id (scope=summary|full). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | summary (default) or full graph | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the safety burden and does step up by declaring 'Read-only', which is the key behavioral trait for this call. It does not cover whether snapshots are cached, how large responses behave beyond the schema's max_bytes, or whether workspace discovery can fail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One compact sentence, front-loaded with the resource and payload, with no filler. It is telegraphic to the point of being slightly cryptic, but every fragment earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter read tool with a fully documented schema and no output schema, the brief return-content list plus the read-only note are adequate. What is missing is orientation for a complex architectural tool: how it relates to arch_status and arch_diff, and what snapshot_id is used for downstream.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters (scope, max_bytes, workspace) are already documented in the schema; the baseline of 3 applies. The description's '(scope=summary|full)' merely restates the enum and adds no new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (architectural snapshot) and enumerates the payload (stacks, git, graph, snapshot_id), so an agent knows exactly what it gets back. It never distinguishes itself from arch_status or arch_diff, so the sibling boundary is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance is given: nothing says whether this is a first-call orientation tool or when to prefer arch_status/arch_diff. The only hint is the inline scope=summary|full, which is a parameter note rather than usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
arch_statusB
Workspace status: detected stacks, git info, graph index coverage and adapter availability. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = git root or nearest manifest from cwd |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full behavioral burden. It usefully discloses read-only behavior and lists the reported content, but it does not cover permissions or auth requirements, freshness or caching, error behavior, or the response shape. For a simple status tool this is moderate transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted wording. Each clause names a concrete status component, and 'Read-only' is a useful behavioral tag.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity read-only status tool with no output schema, the description names the core return categories and the read-only safety property. It leaves usage routing against siblings and some behavioral details unstated, but the schema covers the parameters fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both optional parameters, including workspace default resolution and max_bytes budget. The description adds no parameter-specific meaning beyond what the schema provides, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and scope—workspace status—and enumerates what it reports: detected stacks, git info, graph index coverage, and adapter availability. It does not explicitly differentiate itself from sibling tools such as arch_snapshot, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance, no named alternatives, and no exclusions. 'Workspace status' and 'Read-only' imply a diagnostic call, but the agent is not told when to choose this tool over arch_snapshot, arch_diff, or the other siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
focusA
Incoming and outgoing edges of one node with types; sqlglot lineage edges additionally carry columns (from/to pairs), stripped from get_graph/arch_snapshot. Type-only edges excluded unless include_type_only=true. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | Node path: absolute inside workspace or repo-relative POSIX | |
| limit | No | Max edges per list (default 50, max 200) | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd | |
| include_type_only | No | Include type-only edges (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry behavioral disclosure; it does state 'Read-only', default exclusion of type-only edges, and extra sqlglot lineage columns. It does not describe ordering, missing-node behavior, or the overall returned edge structure, leaving gaps for a query tool with no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and very short: scope first, then lineage-column nuance, filtering default, and safety. Dense graph terminology ('sqlglot lineage edges') adds information without wasted prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a graph-query tool with five documented parameters and no output schema, it explains scope, filtering default, lineage columns, and read-only status. It still leaves the return shape largely implicit—such as how incoming and outgoing edges are separated—so an agent lacks full context for interpreting results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the input schema already documents node, limit, max_bytes, workspace, and include_type_only. The description only restates the include_type_only default and otherwise adds no parameter-specific semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the resource and operation as 'incoming and outgoing edges of one node with types', and distinguishes the lineage-column behavior from get_graph/arch_snapshot. It does not use an explicit verb and does not position itself against all siblings such as reaches or impact, so clarity is strong but not fully sibling-differentiating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies the tool is for inspecting one node and contrasts the lineage-column output with get_graph/arch_snapshot, which helps select it when columns are needed. It gives no explicit when-not guidance or direct routing versus reaches, impact, search, or affected_tests.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
impactB
What a change affects: transitive dependents of changed files within depth (type-only excluded by default). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Max reverse edges (default 10, integer >= 1) | |
| changed | Yes | Changed paths inside the workspace | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd | |
| include_type_only | No | Include type-only edges (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the safety and behavior burden. It does disclose 'Read-only', the depth bound, and the default exclusion of type-only edges, which is genuinely useful. However, it says nothing about output shape, truncation semantics implied by max_bytes, or error behavior for paths outside the workspace.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core semantics and the read-only guarantee, with zero filler. It is slightly telegraphic ('What a change affects:'), but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a five-parameter analysis tool with no annotations and no output schema, the description omits what the response looks like (file lists, edge counts, truncation indicators) and how max_bytes interacts with depth limits. Adequate to start but leaves real gaps for correct invocation and interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all five parameters are already documented, including depth defaults and include_type_only. The description only echoes the type-only default and depth concept, adding no syntax, format, or interaction detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific computation: transitive dependents of changed files, bounded by depth, with type-only edges excluded by default. That is clearly distinct from forward-reachability or test-selection tools, though it never names a sibling such as 'reaches' or 'affected_tests' to make the distinction explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'What a change affects' implies the situation (you have changed files and want upstream blast radius), but there is no explicit when/when-not guidance and no routing to alternatives like 'affected_tests' for test coverage. Usage must be inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reachesB
Reverse reachability: which nodes depend on target within max_depth. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Target node path: absolute inside workspace or repo-relative POSIX | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| max_depth | No | Max reverse edges (default 10, integer >= 1) | |
| workspace | No | Workspace path; omitted = discovery from cwd | |
| include_type_only | No | Include type-only edges (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it only contributes the phrase "Read-only" to signal safety. It says nothing about truncation when max_bytes is exhausted, how cycles are handled, whether results are ordered, or what the response looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the core semantics front-loaded and zero filler. The clipped "Read-only." fragment is arguably the most useful per-word signal in the whole definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a five-parameter graph-traversal tool with no annotations and no output schema, the definition is minimally viable but thin. It should clarify directionality relative to 'impact', describe truncation behavior tied to max_bytes, and note how workspace discovery affects resolution.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so a baseline of 3 applies – the schema already documents target, max_bytes, max_depth, workspace, and include_type_only with defaults and constraints. The description mentions target and max_depth, but adds no syntax, format, or interpretation guidance beyond those fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Reverse reachability: which nodes depend on target within max_depth" names a specific operation and resource, and the parenthetical defines what the result set actually is. It is clear on its own but never contrasts itself with the sibling 'impact' tool, which a reader would plausibly confuse with reverse dependency traversal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description contains no when-to-use or when-not-to-use guidance and names no alternatives, despite four siblings (impact, search, focus, arch_snapshot) that could plausibly cover adjacent questions. An agent must infer from the name alone that this is the reverse-direction counterpart to a forward traversal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchB
Search graph nodes by case-insensitive substring (kind=file|dir|test|all|module|package|symbol|table|view|api|config|doc|service|container). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Result kind (default file) | |
| query | Yes | Substring to search for | |
| max_bytes | No | Response budget in bytes (default 65536, max 1048576) | |
| workspace | No | Workspace path; omitted = discovery from cwd |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden. It does assert "Read-only", which is meaningful safety context, but it says nothing about where nodes come from (index vs live filesystem scan), whether results are truncated budget-wise, or what a result entry looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with no filler. The long inline enumeration of thirteen kinds largely duplicates the schema enum and is the only wasteful element; the rest is dense and purposeful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Four parameters, no annotations, and no output schema, yet the description never describes the shape of a result (node kind, path, score, truncation signal). For a search tool whose output format is undeclared anywhere else, that is a real gap, though the core selection information is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does add matching semantics for `query` (case-insensitive substring) that the schema only calls "Substring to search for", but it re-lists the `kind` enum values verbatim and says nothing about `workspace` or `max_bytes` budget behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Search graph nodes") plus the matching rule ("case-insensitive substring") and enumerates the selectable kinds, so an agent knows exactly what the tool returns. No sibling in the set (arch_status, focus, reaches, impact, etc.) is a substring search, so it is distinguishable, though the description never names a sibling to contrast against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to choose this over focus, reaches, or impact, nor on when `kind` should be set narrowly versus `all`. A single agent-facing line — e.g. "use for name lookups; use reaches for call-graph traversal" — would be needed for a 4.
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.
8 tool updates
v0.1.0- First observed
affected_tests - First observed
arch_diff - First observed
arch_snapshot - First observed
arch_status - First observed
focus - First observed
impact - First observed
reaches - First observed
search
TDQS
Scored across 8 tools
Most tools have distinct roles, but reaches, impact, and affected_tests all express reverse-dependency/reachability queries and can be confused. Descriptions clarify the differences (generic depth vs changed-file impact vs tests only), but the boundaries are not fully crisp.
All names are snake_case and readable, but the set mixes an arch_ prefix on only some tools and mixes verb-style names (search, focus, reaches) with noun-style names (impact, affected_tests, arch_diff). No predictable verb_noun convention is followed.
Eight tools is well within the typical 3-15 range and the surface is focused on read-only architecture graph analysis. Each tool corresponds to a distinct query shape, so the count is appropriate.
The read-only architecture-analysis surface is broadly covered: status, snapshots, search, edge inspection, reverse reachability, impact, test impact, and diff. A minor gap is the lack of a general get_graph or node-detail tool (focus explicitly references get_graph, which is absent), though arch_snapshot may fill part of that role.
Maintenance
Related MCP Connectors
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Search indexed code, trace dependencies, assess change impact, and recall repository memory.
Deterministic context layer for your codebase: change impact, blast radius, answers with receipts.
Ask who calls a route, what a change breaks or who reads a field, across a system's repos.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI agents and reviewers to query a deterministic code dependency graph for callers, routes, pages, tables, and config with file:line evidence instead of grepping. One server can serve many indexed graphs, supporting cross-repository impact analysis.192 PyPI4MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents and terminal users to query codebases for callers, impact, tests, dependencies, and refactor previews using static AST analysis, with every match accounted for and uncertain relationships clearly marked.331 npm2MIT
- AlicenseNot gradedqualityBmaintenanceExposes three read-only tools—impact, explain, and report—so an agent can query a prebuilt local DuckDB graph of a codebase to find the transitive reverse-dependencies of a symbol or file, inspect a symbol's structural neighbourhood, and introspect the index itself. Runs over stdio or Streamable HTTP, always read-only, with no external service.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to query a local code graph over stdio, so they can see what a Git change may affect, find related tests, routes and nodes, and cite evidence paths — read-only and fully on-machine.6 npmMIT