pip install jcodemunch-mcpVerify:
jcodemunch-mcp --helpRecommended: use
uvxinstead ofpip installwhen configuring MCP clients.uvxruns the package on demand without requiring it to be on your system PATH.
Or from source:
git clone https://github.com/jgravelle/jcodemunch-mcp.git
cd jcodemunch-mcp
pip install -e .The fastest way to add jCodeMunch to Claude Code is a single command:
claude mcp add jcodemunch uvx jcodemunch-mcpThis registers the server at user scope (~/.claude.json) so it is available in every project. To limit it to a single project, pass --scope project:
claude mcp add --scope project jcodemunch uvx jcodemunch-mcpTo include optional environment variables at the same time:
claude mcp add jcodemunch uvx jcodemunch-mcp \
-e GITHUB_TOKEN=ghp_... \
-e ANTHROPIC_API_KEY=sk-ant-...Restart Claude Code after running the command.
Manual config — if you prefer to edit the config file directly:
| Scope | Path |
|---|---|
| User (global) | ~/.claude.json |
| Project | .claude/settings.json (in the project root) |
{
"mcpServers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
}
}Environment variables are optional — see the list in the Claude Desktop section below.
Config file location:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Linux | ~/.config/claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
Add to your claude_desktop_config.json:
{
"mcpServers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
}
}Environment variables are optional:
GITHUB_TOKENenables private repositories and higher GitHub API rate limits.ANTHROPIC_API_KEYenables AI-generated summaries via Claude Haiku.ANTHROPIC_MODELoverrides the Claude model (default:claude-haiku-4-5-20251001).GOOGLE_API_KEYenables AI-generated summaries via Gemini Flash (used ifANTHROPIC_API_KEYis not set).GOOGLE_MODELoverrides the Gemini model (default:gemini-2.5-flash-lite).- If neither key is set, summaries fall back to docstrings or signatures.
JCODEMUNCH_CONTEXT_PROVIDERS=0disables context providers (dbt metadata enrichment, etc.) during indexing.
Restart Claude Desktop after saving the config.
Open Cursor Settings (Ctrl+Shift+J) → Tools & MCP → + New MCP Server to open mcp.json, then add:
{
"mcpServers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"]
}
}
}Save and check Tools & MCP — it will confirm whether the server started successfully. You may need to restart Cursor.
WSL users: Configure separately for Windows and your Linux distro, and switch between them via the Tools & MCP panel as needed.
Add to .vscode/settings.json:
{
"mcp.servers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"],
"env": {
"GITHUB_TOKEN": "ghp_..."
}
}
}
}If you use Claude Code, you can display a live token savings counter in the status bar:
Claude Sonnet 4.6 | my-project | ░░░░░░░░░░ 0% | 1,280,837 tkns saved · $6.40 saved on Opus
Ask Claude Code to set it up:
"Add jcodemunch token savings to my status line"
Claude Code will add a segment that reads ~/.code-index/_savings.json and calculates cost avoided at the Claude Opus rate ($25.00 / 1M tokens). The counter updates automatically after every jcodemunch tool call — no restart required.
To add it manually, read ~/.code-index/_savings.json and extract total_tokens_saved:
// Node.js snippet for a statusline hook
const f = path.join(os.homedir(), '.code-index', '_savings.json');
const total = fs.existsSync(f) ? JSON.parse(fs.readFileSync(f)).total_tokens_saved ?? 0 : 0;
const cost = (total * 25.00 / 1_000_000).toFixed(2);
if (total > 0) output += ` │ ${total.toLocaleString()} tkns saved · $${cost} saved on Opus`;- Open the Agent pane → click the
⋯menu → MCP Servers → Manage MCP Servers - Click View raw config to open
mcp_config.json - Add the entry below, save, then restart the MCP server from the Manage MCPs pane
{
"mcpServers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
}
}index_repo: { "url": "fastapi/fastapi" }
get_repo_outline: { "repo": "fastapi/fastapi" }
get_file_tree: { "repo": "fastapi/fastapi", "path_prefix": "fastapi" }
get_file_outline: { "repo": "fastapi/fastapi", "file_path": "fastapi/main.py" }
index_folder: { "path": "/home/user/myproject" }
list_repos: {}
get_repo_outline: { "repo": "myproject" }
search_symbols: { "repo": "myproject", "query": "main" }
Local folder indexes use stable hashed repo ids under the hood. list_repos shows the exact stored id, and bare display-name lookup works when it is unique.
Context enrichment: When indexing local folders, jCodeMunch auto-detects ecosystem tools like dbt and enriches the index with business metadata — model descriptions, tags, and column documentation flow into AI summaries, file summaries, and search keywords. No configuration required. See CONTEXT_PROVIDERS.md for details and how to add support for other tools.
search_symbols: { "repo": "owner/repo", "query": "authenticate", "kind": "function" }
get_symbol: { "repo": "owner/repo", "symbol_id": "src/auth.py::authenticate#function" }
get_file_outline: { "repo": "owner/repo", "file_path": "src/auth.py" }
get_symbols: {
"repo": "owner/repo",
"symbol_ids": [
"src/auth.py::AuthHandler.login#method",
"src/auth.py::AuthHandler.logout#method"
]
}
get_symbol: {
"repo": "owner/repo",
"symbol_id": "src/main.py::process#function",
"verify": true
}
The response _meta.content_verified will be true if the source matches the stored hash and false if it has drifted.
search_text: { "repo": "owner/repo", "query": "TODO", "file_pattern": "*.py", "context_lines": 1 }
Use search_text for string literals, comments, configuration values, or anything that is not a symbol name. Results are grouped by file and include optional before / after context lines for each match.
get_file_content: {
"repo": "owner/repo",
"file_path": "src/main.py",
"start_line": 20,
"end_line": 40
}
invalidate_cache: { "repo": "owner/repo" }
index_repo: { "url": "owner/repo" }
| Tool | Purpose | Key Parameters |
|---|---|---|
index_repo |
Index GitHub repository | url, use_ai_summaries |
index_folder |
Index local folder | path, extra_ignore_patterns, follow_symlinks |
list_repos |
List all indexed repositories | — |
get_file_tree |
Browse file structure | repo, path_prefix |
get_file_outline |
Symbols in a file | repo, file_path |
get_file_content |
Cached file content | repo, file_path, start_line, end_line |
get_symbol |
Full source of one symbol | repo, symbol_id, verify, context_lines |
get_symbols |
Batch retrieve symbols | repo, symbol_ids |
search_symbols |
Search symbols | repo, query, kind, language, file_pattern, max_results |
search_text |
Full-text search | repo, query, file_pattern, max_results, context_lines |
get_repo_outline |
High-level overview | repo |
invalidate_cache |
Delete cached index | repo |
Symbol IDs follow the format:
{file_path}::{qualified_name}#{kind}
Examples:
src/main.py::UserService#class
src/main.py::UserService.login#method
src/utils.py::authenticate#function
config.py::MAX_RETRIES#constant
IDs are returned by get_file_outline and search_symbols. Pass them to get_symbol or get_symbols to retrieve source code. search_text returns file-and-line matches, not symbol IDs.
jCodeMunch contributes an anonymous token savings delta to a live global counter at j.gravelle.us with each tool call. Only two values are ever sent: the tokens saved (a number) and a random anonymous install ID. No code, paths, repo names, or anything identifying is transmitted. Network failures are silent and never affect tool performance.
The anonymous install ID is generated once and stored locally in ~/.code-index/_savings.json.
To disable, set JCODEMUNCH_SHARE_SAVINGS=0 in your MCP server env:
{
"mcpServers": {
"jcodemunch": {
"command": "uvx",
"args": ["jcodemunch-mcp"],
"env": {
"JCODEMUNCH_SHARE_SAVINGS": "0"
}
}
}
}AI summaries can be generated by a local LLM via any OpenAI-compatible server (e.g. LM Studio). Set OPENAI_API_BASE and OPENAI_MODEL in your MCP server env to point at it.
Recommended model: Qwen3-8B — fast, fits in 12 GB VRAM, and produces quality one-line summaries. In benchmarks it was ~5× faster than Devstral 24B with comparable summary quality.
Critical for Qwen3: Set the LM Studio system prompt to /no_think (and leave the "Enable thinking" toggle ON). Without this, the model wastes GPU time on chain-of-thought reasoning and leaks artifacts into summaries. Disabling thinking via the checkbox instead produces summaries that are too terse.
"env": {
"OPENAI_API_BASE": "http://127.0.0.1:1234/v1",
"OPENAI_MODEL": "qwen/qwen3-8b",
"OPENAI_API_KEY": "local-llm"
}Performance tuning:
OPENAI_CONCURRENCY— number of parallel batch requests to the LLM server (default:1). Higher values keep the GPU saturated.OPENAI_BATCH_SIZE— symbols packed per request (default:10).OPENAI_MAX_TOKENS— max output tokens per batch response (default:500).
"Repository not found"
Check the URL format (owner/repo or full GitHub URL). For private repositories, set GITHUB_TOKEN.
"No source files found"
The repository may not contain supported language files (.py, .js, .ts, .go, .rs, .java, .c, .h, .cpp, .cc, .cxx, .hpp, .hh, .hxx), or files may be excluded by skip patterns.
Rate limiting
Set GITHUB_TOKEN to increase GitHub API limits (5,000 requests/hour vs 60 unauthenticated).
AI summaries not working
Set ANTHROPIC_API_KEY (Claude Haiku) or GOOGLE_API_KEY (Gemini Flash). Anthropic takes priority if both are set. Without either, summaries fall back to docstrings or signatures.
Stale index
Use invalidate_cache followed by index_repo or index_folder to force a clean re-index.
Encoding issues Files with invalid UTF-8 are handled safely using replacement characters.
Indexes are stored at ~/.code-index/ (override with the CODE_INDEX_PATH environment variable):
~/.code-index/
├── owner-repo.json # Index metadata + symbols
└── owner-repo/ # Raw source files
└── src/main.py
- Start with
get_repo_outlineto quickly understand the repository structure. - Use
get_file_outlinebefore reading source to understand the API surface first. - Narrow searches using
kind,language, andfile_pattern. - Batch-retrieve related symbols with
get_symbolsinstead of repeatedget_symbolcalls. - Use
search_textwhen symbol search does not locate the needed content. - Use
verify: trueonget_symbolto detect source drift since indexing.