Code-RAG's server is a stock MCP implementation: standard JSON-RPC
over HTTP, the published MCP 2025-06-18 handshake, no client-specific
extensions. Any MCP-capable agent can drive it — this file documents
the specifics for OpenAI's Codex CLI,
which is the most common alternative to Claude Code.
The repo's existing documentation
(Setup.md, Running.md, RAGPlan.md)
explains how to bring the server up, index your projects, and operate it
day-to-day. That part is unchanged — start the server the same way,
maintain the same application.ini and rag-projects.json, run scans
with ./bld scan. The only difference here is on the client side:
where Claude Code registers an MCP server via claude mcp add, Codex
registers one via an entry in ~/.codex/config.toml.
Working with Code-RAG through Codex CLI touches two distinct config files, owned by opposite sides of the system. The most common point of confusion is mixing up their roles, so:
| File | What it does | Who edits it | When you touch it |
|---|---|---|---|
src/main/backend/rag-projects.json |
Tells the Code-RAG server which code trees to index. One JSON entry per project: name, absolute roots[], optional excludeGlobs. Gitignored — the committed .example is just a template. |
You (hand-edit). | When adding/removing a project or changing its roots. Restart Kiss after editing so the new schema gets bootstrapped. |
~/.codex/config.toml |
Tells Codex CLI which MCP servers exist. Holds Codex's general configuration plus a [mcp_servers.*] section per server. A .codex/config.toml inside a trusted project directory provides per-project scoping. |
You (hand-edit TOML). | When registering this Code-RAG instance with Codex, or when the shared secret rotates. |
The two files don't communicate directly. The bridge is the URL: in
~/.codex/config.toml you set
url = "http://127.0.0.1:17080/rag-mcp/<X>", and <X> must equal a
name in rag-projects.json. If they don't match the server replies
404 when Codex tries to call a tool.
Worth being precise about one subtlety: the TOML section name
([mcp_servers.<name>]) is just Codex's local label for the server.
The server, on the other hand, routes on the URL path segment after
/rag-mcp/. We use the same string for both by convention — usually the
name from rag-projects.json — so all three agree, but they are
technically independent variables. The thing the server actually
requires to match is the URL path segment.
rag-projects.json is documented end-to-end in Setup.md §3
and Running.md §4. ~/.codex/config.toml is Codex's own
file — its schema and behavior live with Codex's MCP
reference.
Codex reads MCP config from up to two places at startup:
~/.codex/config.toml— global. Loaded regardless of the directory you launchcodexfrom..codex/config.tomlinside a trusted project directory — per-project overrides and additions, loaded only whencodexis started inside that tree and Codex has been told the project is trusted.
Unlike Claude Code — which keys its default-scope MCP entries by the absolute working directory — Codex's global entries are visible everywhere by default. Practical consequences:
- A single
[mcp_servers.myproj]in~/.codex/config.tomlworks from any cwd. You don't have to re-register from every project directory. - Renaming or moving the Code-RAG working tree does NOT invalidate
the entry, because the entry isn't keyed by cwd. The only thing
the entry references is the loopback URL (
http://127.0.0.1:17080/…) and the project name in the URL path. - If you want an entry that only applies inside one checkout, put
a
[mcp_servers.<name>]block in that checkout's.codex/config.tomland mark the project trusted. See Codex's advanced-configuration docs for the trust mechanism. - Multiple Code-RAG projects can coexist as separate global entries — pick a different TOML section name and URL path segment per project; both are independent of the cwd.
- Code-RAG is installed and the server is running on its default
loopback URL
http://127.0.0.1:17080/. (See Setup.md.) - At least one project is configured in
src/main/backend/rag-projects.jsonand its index is populated. Test with./bld status— under "Projects" you should see at least one entry with a non-zero file count. - Codex CLI is
installed and you can run
codexfrom your shell.
Shortcut: if you've installed the
code-ragwrapper (Setup.md §10),code-rag new-project <name> <root>...adds the project torag-projects.json, scans it, AND appends the[mcp_servers.<name>]section to~/.codex/config.tomlautomatically (and registers with Claude Code ifclaudeis also on$PATH). The manual procedure below is what that shortcut runs; read it to understand the wiring or when registering a project you didn't create viacode-rag.
Codex's MCP config lives in ~/.codex/config.toml. The HTTP-transport
schema is documented in
Codex's MCP reference. For
Code-RAG with the default port and a project named myproj, add:
[mcp_servers.myproj]
url = "http://127.0.0.1:17080/rag-mcp/myproj"
http_headers = { "X-RAG-Token" = "PASTE-YOUR-SECRET-HERE" }Replace PASTE-YOUR-SECRET-HERE with the value of RAGMCPSharedSecret
from src/main/backend/application.ini — the same secret Claude Code
sends. Look it up with:
grep '^RAGMCPSharedSecret' src/main/backend/application.iniIf you prefer not to hard-code the secret in the TOML file, Codex
supports pulling header values from environment variables via
env_http_headers — same TOML section, replace http_headers with:
env_http_headers = { "X-RAG-Token" = "CLAUDE_RAG_TOKEN" }then export the secret in your shell:
export CLAUDE_RAG_TOKEN="$(grep '^RAGMCPSharedSecret' src/main/backend/application.ini | sed 's/.*=\s*//' | tr -d ' ')"The URL path segment (/rag-mcp/<project>) is how the server scopes the
search; it must match a configured project. If you index more than one
project, register them as separate MCP entries:
[mcp_servers.stack360]
url = "http://127.0.0.1:17080/rag-mcp/stack360"
http_headers = { "X-RAG-Token" = "..." }
[mcp_servers.other_project]
url = "http://127.0.0.1:17080/rag-mcp/other_project"
http_headers = { "X-RAG-Token" = "..." }The TOML section name (stack360, other_project) is the Codex name
for the MCP server — pick whatever's convenient. The URL path segment
must exactly match the project's name in rag-projects.json.
Codex supports a per-project config at .codex/config.toml inside a
trusted project directory. If you want a particular checkout to use the
RAG and nothing else, that's the cleaner place to put the entry.
Otherwise, ~/.codex/config.toml registers the server globally.
Caveat (Ollama load): because Codex's global entries are visible from every directory, Codex sessions in unrelated cwds may still speculatively call
search_code_<project>, embedding the query through Ollama for nothing. Claude Code avoids this by registering at project scope (see ClaudeCode.md); Codex has no equivalent for the defaultbld new-projectflow. If you find the Ollama spikes meaningful, the per-project.codex/config.toml+ trusted-directory mechanism above is the manual workaround.
Restart any open Codex session so it re-reads the config, then run a prompt that invokes the tool, for example:
"Search the project index for where login is handled. Use the
search_codetool from thestack360MCP server."
Codex should call the tool, get back a list of hits (each with a
repo, path, start_line, end_line, absolute_path, score, and
snippet), then typically follow up with a file read on the top hit.
If Codex can't reach the server, sanity-check from the same shell:
SECRET=$(grep '^RAGMCPSharedSecret' src/main/backend/application.ini | sed 's/.*=\s*//' | tr -d ' ')
curl -s -X POST http://127.0.0.1:17080/rag-mcp/stack360 \
-H "X-RAG-Token: $SECRET" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}' | python3 -m json.toolIf this returns the four tools (search_code, get_chunk, list_repos,
index_status), the server is healthy and the problem is in Codex's
config. If it doesn't, the server isn't running or the secret is
wrong — see Running.md.
The four tools are identical for any MCP client. The server doesn't know which agent is calling. So both Codex and Claude Code can register against the same Code-RAG instance and even hit it simultaneously — pgvector reads are concurrent-safe and there's no client identity in the per-project lock model. Multiple agents on the same project at once is fine; they only contend on the shared Ollama GPU during query embedding, which is ~30 ms anyway.
Tool name prefix. Codex surfaces the four tools under whatever
naming convention it currently uses — that's a Codex implementation
detail, not something the server controls. The four tool names
themselves (search_code, get_chunk, list_repos, index_status)
are stable.
Per-project MCP entry rather than one shared. This isn't strictly necessary — you could write a Codex hook that injects the project name into each request URL based on the current working directory — but the "one MCP entry per project" pattern matches what we recommend for Claude Code, and Codex's TOML config makes it easy to keep them separate.
If your Codex version doesn't yet support http_headers. Look at
the
Codex MCP reference for
your installed version. As a fallback, you can set
RAGMCPSharedSecret to an empty string in application.ini, which
turns off the auth check (Tomcat is already loopback-only, so any
process on the host could connect anyway). Restart the server after
changing the secret.
Nothing changes for the operator. You still:
- Start the server:
./bld start - Check status:
./bld status - Scan one project:
./bld scan <project> - Scan all projects:
./bld scan all - Stop the server:
./bld stop
The startup auto-scan, the per-project lock, the SHA-based change detection, the disabled-by-default cron — all of it is independent of which agent is asking questions on the read side. Codex sessions and Claude Code sessions both work the same way as far as the indexer is concerned.
- ClaudeCode.md — same instructions for Claude Code.
- Setup.md — installing and starting the server.
- Running.md — day-to-day operations.
- RAGPlan.md — design reference; §6 covers the MCP server.
- OpenAI Codex MCP reference — authoritative source for Codex's MCP config format.