Skip to content

06 MCP Integration

Mikhail Deynekin edited this page Oct 12, 2026 · 1 revision

MCP Integration

Attaching RAGRAF to an agent as an MCP server: configuration, the working regimen, and the rules that keep the agent honest. Normative source: docs/implementation/INTEGRATION.md.


1. Server configuration

RAGRAF speaks JSON-RPC 2.0 over stdio (MCP protocol version 2024-11-05). No HTTP, no daemon — the client spawns the process.

{
  "mcpServers": {
    "ragraf": {
      "command": "python",
      "args": [
        "/path/to/RAGRAF/tools/ragraf-mcp.py",
        "--project", "/path/to/RAGRAF/config/mycorpus.yaml",
        "--agent", "my-agent",
        "--agent-kind", "external"
      ]
    }
  }
}
Arg Required Meaning
--project yes corpus config. Create it with ragraf init <project-dir> (prints the path)
--agent no agent name for per-agent statistics; without it, clientInfo from initialize is used, else unknown
--agent-kind no autoclaw · external · internal — family-level statistics
--debug no verbose server logging to stderr

Use the venv interpreter explicitly for reliability: ~/.ragraf/venv/Scripts/python.exe (Windows) or ~/.ragraf/venv/bin/python (POSIX).

The config directory config/ is machine-local and git-ignored by design — see Configuration.

2. The 23 tools

All tools are the facade operations (same names, same envelope), prefixed ragraf_:

Group Tools
Session start ragraf_index_status · ragraf_drift_report
Navigation ragraf_search (supports with_text) · ragraf_symbol · ragraf_references · ragraf_repo_map · ragraf_code (entry_ids)
Graph ragraf_callers · ragraf_callees · ragraf_impact · ragraf_slice (needs capability=full)
DB & contracts ragraf_schema · ragraf_table_usage · ragraf_write_check · ragraf_routes
Policy & UI ragraf_policy_trace · ragraf_class_usage
Freshness & meta ragraf_freshness · ragraf_live_read · ragraf_drift_ack · ragraf_usage · ragraf_catalog · ragraf_ensure

There is no graph-query tool and there will be none (FT-15). An attempt to pass MATCH ... RETURN is rejected with JSON-RPC -32602.

⚠️ Known issue: the rejection filter is substring-based and can false-positive on legitimate text arguments containing words like return (e.g. a search query «when does the function return false»). Tracked as defect C-02 / roadmap R-SEC-2 — the structural guarantee (no query endpoint) is what actually enforces FT-15.

Per-tool semantics, parameters and reading rules: Operations Reference.

3. The working regimen

Before any task

1. ragraf_index_status   → revision, parse completeness, capability, ledger size
2. ragraf_drift_report   → if the ledger is non-empty: account for divergences BEFORE any conclusions

Between the index and the code there may be differences: the index is immutable within a revision while the code has been edited. An agent that skips the ledger may rely on a fact that is already false — and not notice.

Question → tool map

The agent asks Tool
«where does this live?» ragraf_symbol; unsure → ragraf_search
«how is the module built?» ragraf_repo_map (budget; chars_used is actual volume)
«who calls this?» / «what does it call?» ragraf_callers / ragraf_callees
«what breaks if I change it?» ragraf_impact — mandatory before the edit
«where else is it used?» ragraf_references
«what data flows here?» ragraf_slice (only at capability=full)
«what's in the table / who touches it?» ragraf_schema · ragraf_table_usage
«is this write valid?» ragraf_write_check — before writing SQL
«who gets this permission?» ragraf_policy_trace
«what is this fragment?» ragraf_search + with_text: true (address+text in one call)
«show me that place in detail» ragraf_code + entry_ids from the hit

Hard rules for the agent

  1. Whole-file reads are the last resort — after «not found» or a stale mark.
  2. A fact with stale_warnings is not a basis for conclusions — ragraf_live_read first.
  3. Bodies don't arrive in impact/slice/repo_map — by design; fetch with search with_text or code entry_ids in ONE call if needed.
  4. Separate stated from derived — conclusions on derived are «requires verification».
  5. Respect capability — degraded means slices/flows are unavailable (refusal with reason), not an empty result.
  6. Read limits — every answer lists what it cannot see.
  7. The index is not updated mid-task — edits go to the ledger.

During and after the change effort

after edits:      ragraf drift --scan      (register deltas; index untouched)
extract-method:   → a slice_boundary entry appears; revisit conclusions around it after reindex
effort finished:  ragraf reindex           (new revision; ledger archived into a 3-section report)

4. Ready-to-paste AGENTS.md block

## Code knowledge base (RAGRAF)

Before working with code, use RAGRAF instead of reading files blind.

Order:
1. `ragraf_index_status` — index state.
2. `ragraf_drift_report` — if the ledger is non-empty, account for divergences first.
3. Questions about code — through operations: `ragraf_symbol`, `ragraf_callers`,
   `ragraf_impact`, `ragraf_search`, `ragraf_repo_map`.
4. `rg` and whole-file reads — only if the index answered «not found» or a fact is
   marked `stale` (then `ragraf_live_read` first).
5. Before an edit touching a public method or a table, `ragraf_impact` is mandatory.
6. After edits: `ragraf drift --scan` (the index is NOT updated).
7. When the change effort is done: `ragraf reindex`.

Forbidden:
- writing graph queries (Cypher/CPGQL) — only the fixed operation set exists;
- relying on a `stale`-marked fact without a prior `ragraf_live_read`;
- treating `derived` links as proven;
- ignoring `limits` and `capability` in answers.

5. Protocol notes for client authors

  • Lifecycle: initialize → server answers protocolVersion: 2024-11-05, capabilities.tools.listChanged: false, serverInfo {name: "ragraf", version} → notifications/initialized → tools/list / tools/call / ping.
  • Errors: unknown method → -32601; query-language attempt → -32602; unknown tool → isError: true content (per MCP); operation-layer refusal → normal result with error + exit-code-3 semantics surfaced in the payload.
  • Known protocol gaps (roadmap R-MCP-1): the server replies to unknown notifications (JSON-RPC forbids it); no negotiation against newer protocol versions (2025-03-26, 2025-06-18); telemetry attribution falls back to clientInfo.name.
  • Telemetry: every tools/call is journaled (op, rev, capability, duration, found, fact counts, chars, arg hash+digest, agent, task). Read back via ragraf_usage. Reading usage never writes.

6. Verifying the connection

# one-shot handshake over stdio (PowerShell)
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}',
'{"jsonrpc":"2.0","method":"notifications/initialized"}',
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' |
  python tools/ragraf-mcp.py --project config/mycorpus.yaml --agent probe

Expect: serverInfo in response 1; 23 tools in response 2. Then in your client, first call of the session: ragraf_index_status.


Next: Configuration →

Clone this wiki locally