Skip to content

MCP tools

kivgraph serve registers twelve tools over stdio once a generation is published. Eleven are read-only. index_project is the only one that mutates anything, and only after explicit consent. A server with no published generation registers index_project alone; see Before a generation is published.

Every tool answers from the published HotSnapshot. serve does not open the database and does not run the TypeScript worker.

The questionThe tool
I do not know its name; which files do I openfind_by_intent
Who calls this, what references thisfind_references
What breaks if I change thisget_blast_radius
What does this reach outwardstrace_dependencies
Who uses it from another repositoryfind_cross_repo_consumers
Where is it declaredfind_symbol
What is declared in this packageget_file_outline
Give me the code of these symbolsget_source
Everything known about one symbolget_symbol
What is indexed, and is it currentgraph_status
Which repositories are registeredlist_repositories
Index a project and rebuildindex_project

Edges are resolved by language analyzers, never by matching names, and the resolution is not uniform across the five languages: Go, TypeScript and Rust edges are type-checked; Dart edges are resolved by Dart Analysis Server; Python uses exact semantic facts when a configured analyzer provides them and CANDIDATE facts in its bundled AST fallback. Where the edge is type-checked, an empty reference list means nobody calls it, and two homonymous methods are two different symbols. grep can say neither.

It is not always the cheaper route either way. On the 29-question benchmark grep costs fewer tokens than these tools on five questions — rare names in a single repository, where both sides answer correctly. See the comparison.

See Using it from an agent for the response envelope, the cursor contract, and how to read coverage, guidance and completeness.

Read-only, symbols and source:

Read-only, graph traversal:

Read-only, the index itself:

Mutating:

Every tool that takes a symbol accepts either a stable_key or the triple repository, repository-relative path and qualified_name — exactly one of the two. Supplying both is rejected rather than resolved quietly, because two selectors can disagree and answering one of them answers a question nobody asked.

Every row a tool returns already carries a repository, a path, a qualified name and a line range, so the next call is built from the answer just received and stable keys never have to enter the conversation.

With no published generation there is no query surface. The server completes the handshake, publishes only index_project, and puts the rebuild command in its instructions.

A client launches the process itself, so exiting would read as a crash, and publishing tools that answer INDEX_NOT_READY to everything would teach the agent that the tools do not work. See Troubleshooting.

Inspecting the catalog before there is an index

Section titled “Inspecting the catalog before there is an index”

kivgraph serve --introspection publishes the complete tool catalog even when no generation exists. It is meant for MCP inspectors, registries and development tooling that need to read tool definitions before a repository has been indexed, and that have nothing to read when the handshake publishes nothing.

Terminal window
kivgraph serve --introspection --config ~/.config/kivgraph/config.yaml

It is not the configuration to give a client. What it changes is what is listed:

  • it does not create an index, and starting it publishes no generation;
  • every read tool it lists still answers INDEX_NOT_READY until one is published — graph_status is the exception it always was, and reports an empty graph rather than refusing;
  • index_project stays behind the same consent gate and answers PERMISSION_REQUIRED without approval;
  • the handshake still carries the rebuild instructions, because what a client is told depends on the graph and not on this flag;
  • the definitions are the ones a published server serves, not a schema-only copy;
  • kivgraph serve without the flag is unchanged.

Only serve has the flag. A serve given it answers from its own process rather than relaying to a running daemon, since the catalog it is being asked about is its own.

No tool publishes an outputSchema. With one, the SDK marshals the typed result into structuredContent and repeats the same JSON in the text block, so the response is paid for twice.

get_source goes further and answers in prose: source inside a JSON string costs more than the same source as text.