Skip to content

feat: MCP server — let agents call session search over stdio#6

Open
lupuletic wants to merge 2 commits into
mainfrom
feat/agent-integration
Open

feat: MCP server — let agents call session search over stdio#6
lupuletic wants to merge 2 commits into
mainfrom
feat/agent-integration

Conversation

@lupuletic
Copy link
Copy Markdown
Owner

@lupuletic lupuletic commented May 20, 2026

Summary

Adds an MCP stdio server so a coding agent (Claude Code and Codex) can call fast, ranked session retrieval instead of grepping ~/.claude / ~/.codex transcripts by hand.

One-line install + setup for both agents:

pip install 'code-recall[all]' && code-recall mcp install

code-recall mcp install registers the server with every agent CLI on PATH (idempotent). Restart the agent and ask it to find a past session.

Why MCP-over-stdio (and not a remote server or a bare CLI)

  • The CLI already has --json, so "build a CLI" was largely done — the real gap was agent-native integration.
  • MCP docs name stdio as the transport for local tools with direct filesystem/DB access — exactly code-recall (local SQLite). No network, no auth surface.
  • Claude Code's Tool Search loads MCP tools on demand, so a focused two-tool surface doesn't bloat the agent's context.
  • Shipping it as a subcommand of the existing binary = one install, no separate package.

Tools exposed

Tool Returns
search_sessions(query, limit, provider, project) Ranked hits: title, project, provider, score, why-matched, snippet, ready-to-run resume command. Supports file: / cmd: / branch: prefixes.
get_session_detail(session_id) Files touched, commands run, branch, model, first/last prompts, resume command.

Built with FastMCP, structured output via TypedDict (typing_extensions.TypedDict for pydantic schema-gen on Python < 3.12).

Install command

code-recall mcp install runs, idempotently (removes stale entry first):

claude mcp add --scope user code-recall -- code-recall mcp   # if claude on PATH
codex  mcp add code-recall -- code-recall mcp                # if codex on PATH

Missing CLIs are skipped with a note; succeeds if at least one agent is configured.

Notes

  • Honors the same --db / --claude-dir / --codex-dir flags as the rest of the CLI (paths captured in the tool closures), runs a quick incremental index before each query, stays local-only.
  • mcp is a new optional dependency: code-recall[mcp], also folded into [all].
  • stdout is reserved for JSON-RPC; diagnostics go to stderr.

Testing

  • 8 tool-layer tests (tests/test_mcp_server.py): tool listing, hit shape, limit, provider filter, detail round-trip, missing-id handling, plus install fallback (no CLI → exit 1) and dual-agent registration.
  • Real end-to-end: ran code-recall mcp install against actual CLIs — Claude Code reports ✓ Connected; Codex registers as an enabled stdio server. Confirmed a full stdio round-trip (initializelist_toolssearch_sessionsget_session_detail) against the installed code-recall mcp binary returns well-formed structured results.
  • Full suite: 344 passing.

Test plan

  • pip install 'code-recall[all]' && code-recall mcp install
  • claude mcp list shows code-recall ✓ Connected; codex mcp list shows it enabled
  • Ask Claude/Codex to "find the session where I did X" and confirm it calls search_sessions

Adds a `code-recall mcp` subcommand that serves an MCP stdio server,
turning code-recall into a retrieval tool any agent (Claude Code, Codex)
can call instead of grepping ~/.claude transcripts by hand.

Why MCP-over-stdio rather than a remote server or a bare CLI: the CLI
already has --json, so the real gap was agent-native integration. stdio
is the documented transport for local tools with direct filesystem/DB
access, and Claude Code's Tool Search loads MCP tools on demand so a
focused tool set doesn't bloat context. Shipping it as a subcommand of
the existing binary keeps it to one install.

Tools exposed (FastMCP, structured output):
- search_sessions(query, limit, provider, project) -> ranked hits with
  title, project, provider, score, why-matched, snippet, resume command.
  Supports file:/cmd:/branch: prefixes.
- get_session_detail(session_id) -> files, commands, branch, model,
  prompts, resume command.

The server honors the same --db / --claude-dir / --codex-dir flags as the
rest of the CLI (paths captured in the tool closures), runs a quick
incremental index before each query, and stays local-only.

mcp is a new optional dependency: `code-recall[mcp]`, also folded into
`[all]`. Uses typing_extensions.TypedDict for pydantic schema-gen on
Python < 3.12.

Tests: 6 new tool-layer tests (call_tool against a temp index with the
reindex stubbed) plus a manual stdio round-trip against a real index.
342 pass.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bbdd7cc00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +151 to +154
results = search(query, db_path=db_path, limit=limit, project_filter=project)
if provider:
results = [r for r in results if r.session.provider == provider]
return [_to_hit(r) for r in results[:limit]]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Apply provider filter before limiting search candidates

search_sessions fetches only limit unfiltered results and then applies the provider filter in Python, so in mixed-provider datasets a valid provider can appear to have no matches just because its sessions rank below the first limit global hits. This makes MCP results incomplete/incorrect for provider="claude" or provider="codex" queries when both providers are indexed.

Useful? React with 👍 / 👎.

Comment on lines +164 to +168
conn = get_connection(db_path)
try:
row = conn.execute(
"SELECT * FROM sessions WHERE session_id = ?", (session_id,)
).fetchone()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh index before serving session detail requests

get_session_detail reads directly from SQLite without calling _ensure_fresh_index, unlike search_sessions. If a new session has been written to transcripts but not yet indexed, this tool can return None or stale metadata for an otherwise valid session_id, which violates the freshness behavior documented for MCP queries.

Useful? React with 👍 / 👎.

Comment thread pyproject.toml
Comment on lines +34 to +35
mcp = ["mcp>=1.2"]
all = ["code-recall[semantic,tui,mcp]"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bump package version for new MCP user-facing feature

This commit introduces a new user-visible command (code-recall mcp) and documentation surface but keeps the package version unchanged (0.2.5). Under this repo’s versioning policy, user-visible behavior changes must bump version metadata, otherwise installed artifacts are indistinguishable across feature boundaries and release/version checks can drift.

Useful? React with 👍 / 👎.

Adds `code-recall mcp install` — registers the MCP server with every
supported agent CLI found on PATH, so setup for both providers is a
single command:

    pip install 'code-recall[all]' && code-recall mcp install

Under the hood it runs (idempotently — removes any stale entry first):
    claude mcp add --scope user code-recall -- code-recall mcp
    codex  mcp add code-recall -- code-recall mcp

Verified end-to-end against real CLIs: Claude Code reports "✓ Connected";
Codex registers as an enabled stdio server (the "Unsupported" it shows is
the Auth column — stdio servers don't do OAuth, same as any other local
MCP server). If an agent CLI is absent it's skipped with a note rather
than failing.

README now leads the MCP section with the one-liner and documents the
manual commands in a details block.

Tests: +2 (no-CLI fallback returns 1; both-CLIs path issues add for each).
344 pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant