RepoGraph-Honest MCP Server

RepoGraph-Honest MCP Server

An MCP server that validates generated code against project structure and installed dependencies, catching undefined symbols, wrong API calls, dead code, and type mismatches in real time. It provides tools for project indexing, symbol/API checking, sandboxed execution, file scanning, and code analysis.

Category
访问服务器

README

<div align="center">

HonestCode MCP Server

Catch AI code hallucinations before they reach your editor.

CI PyPI version Python versions License: MIT Downloads

A lightweight Model Context Protocol (MCP) server that verifies AI-generated code against your actual project structure and installed dependencies — detecting undefined symbols, wrong API calls, dead code, and type mismatches in real time.

100% local. No data leaves your machine.

</div>


Contents


Why HonestCode?

AI coding assistants hallucinate. They invent function names, fabricate library APIs, and produce dead code. HonestCode acts as a deterministic verification layer between the model and your editor — pure AST analysis, no LLM calls, no network requests.

graph LR
    A["AI Model generates code"] -->|sends code| B["HonestCode verifies against project"]
    B -->|clean code| C["Editor receives verified code"]

One tool by default: scan_file

By default the server exposes one primary toolscan_file. Give it a Python file and it returns every undefined symbol, incorrect API call, and structural issue in a single trip.

Exposing a single tool is deliberate. Measured agent behavior shows that one well-aimed tool steers agents to a direct answer better than a menu of narrower ones — fewer mis-picks, fewer round-trips. 16 additional tools exist for power users; opt in via the HONESTCODE_TOOLS environment variable (see Environment Variables).

Key differentiators

HonestCode grep / Read RAG over code
Deterministic AST-based, reproducible Exact string match Embedding variance
Cross-file Module-qualified symbols Single-file only Chunk-level
Type-aware Argument counts, None iteration No No
Zero latency Pre-indexed, cached Per-query scan Per-query embed
100% local No network calls No Often requires API

Performance

Numbers below are measured, not estimated. Re-run them yourself:

# Local project
python scripts/benchmark.py --target /path/to/project --repeat 5
# External real-world repos (clones them into a temp dir)
python scripts/benchmark.py --repos psf/requests pallets/flask --format markdown

Measured on this repository (43 Python modules, ~7400 LOC, Python 3.14, median of 3 runs on a developer laptop, Windows):

Operation Measured Note
index_project (cold) ~143 ms Content-hash cached; skips unchanged files
index_project (cached) < 1 ms In-memory cache hit
scan_file ~35 ms AST parse + symbol lookup
check_api < 1 ms Dictionary lookup on cached API index
explore_call_graph (hot) ~1 ms SQLite graph cache hit; cold rebuild ~278 ms
find_dead_code ~1.4 ms Reads the persisted reference graph
find_similar_code ~3750 ms O(n²) SequenceMatcher; dominated by pair count
search_code ~16 ms FTS5 candidate narrowing + regex on hits

The call graph (definitions + references) is persisted to SQLite next to the symbol index, keyed by content hashes of every source file. Graph queries (explore_call_graph, find_dead_code, explore_impact, affected_files) read from disk instead of re-parsing the project on each call — the first call after a change pays the cold rebuild, every later call is a cache hit. find_similar_code uses a length-ratio pre-filter but is still quadratic in the number of functions; this is fine for small/medium projects but will need a token-hash scheme for large codebases.

Token savings vs. grep + Read exploration: ~60% fewer tool calls, ~45% fewer tokens on architecture questions spanning multiple files.


Quick Start

1. Install

pip install honestcode

Or from source:

git clone https://github.com/Fengrru/honestcode.git
cd honestcode-mcp
pip install -e .

Requires Python >= 3.10

2. Configure your MCP client

Claude Code

claude mcp add honestcode -- honestcode-mcp

Or manually add to ~/.claude.json:

{
  "mcpServers": {
    "honestcode": {
      "command": "honestcode-mcp"
    }
  }
}

Cursor

Add to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "honestcode": {
      "command": "honestcode-mcp"
    }
  }
}

VS Code

Add to .vscode/mcp.json:

{
  "servers": {
    "honestcode": {
      "command": "honestcode-mcp"
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "honestcode": {
      "command": "honestcode-mcp"
    }
  }
}

Python (direct invocation)

{
  "mcpServers": {
    "honestcode": {
      "command": "python",
      "args": ["-m", "honestcode.mcp.server"]
    }
  }
}

3. Verify setup

Restart your MCP client. The agent should be able to call scan_file. If not, see Troubleshooting.

4. Use it

1. Index your project      →  index_project("/path/to/project")
2. Load dependency APIs    →  load_project_deps("/path/to/project")
3. Verify generated code   →  scan_file("/path/to/project/generated.py")

Typical agent workflow — one call answers the question:

Agent: "Does this code have any hallucinated APIs?"
Tool:  scan_file("src/services/auth.py")
Result: 2 issues found — undefined_call: validate_token (line 12),
                           undefined_call: db.fetch_all (line 27)

Environment Variables

Variable Default Description
HONESTCODE_TOOLS scan_file Comma-separated tool names to expose (or all). scan_file is always included.
HONESTCODE_INDEX_DIR ~/.cache/honestcode Directory for cached symbol indices
HONESTCODE_CACHE_DIR ~/.cache/honestcode Directory for SQLite graph caches (override for CI/tests)
HONESTCODE_TIMEOUT 10 Seconds before execute_code is killed
HONESTCODE_MEMORY_MB 256 MB memory limit for sandboxed execution (POSIX)
HONESTCODE_LOG_LEVEL INFO Logging verbosity (DEBUG, INFO, WARNING, ERROR)

HONESTCODE_TOOLS

Controls which tools the MCP server exposes. By default only scan_file is registered; set this to a comma-separated list to expose more, or to all to expose every tool:

export HONESTCODE_TOOLS=index,check_symbol,check_api,validate_types
export HONESTCODE_TOOLS=all

scan_file is always included even if not listed. Unknown names are ignored with a warning. Available tool names: scan_file, index, deps, check_symbol, check_api, execute_code, validate_types, find_dead_code, find_similar_code, explore_call_graph, explore_impact, affected_files, stop_watching, search_code, load_package_apis, get_project_stats, choose_tool.

A honestcode.toml config file for per-project rules and ignore patterns is planned — tracked on the Roadmap.


Multi-language support (optional)

Python is the fully supported language (stdlib ast). For JavaScript, TypeScript, Go, Rust and Java, symbol extraction is available via the optional tree-sitter extras:

pip install -e "honestcode[multi-language]"

Once installed, scan_file accepts .js/.ts/.go/.rs/.java files and reports undefined call sites using tree-sitter's grammar. Without the extras, scan_file returns a clear message pointing at the install command instead of failing. This keeps the default install dependency-free.


Supported Platforms and Agents

Runs anywhere Python 3.10+ does — no native build step, no node_modules, no external services.

Platform Support
Windows First-class (stdio + SSE, sandboxed execution)
macOS First-class (stdio + SSE, sandboxed execution)
Linux First-class (stdio + SSE, sandboxed execution, RLIMIT limits)
Agent / Client Config file Auto-install
Claude Code ~/.claude.json honestcode install --client claude
Cursor .cursor/mcp.json honestcode install --client cursor
VS Code .vscode/mcp.json honestcode install --client vscode
Windsurf ~/.codeium/windsurf/mcp_config.json Manual (see Quick Start)
Any stdio MCP client command: honestcode-mcp
Any SSE MCP client --transport sse --port 8000

See Quick Start for the manual JSON snippets and the CLI Usage section for install/init/root project binding.


Tool Reference

Primary tool (always exposed)

scan_file(file_path)

AST-based scan for undefined calls, missing imports, and incorrect API usage in a Python file.

scan_file("/path/to/project/src/auth.py")
# {
#   "success": true,
#   "file": "/path/to/project/src/auth.py",
#   "issues": [
#     {"type": "undefined_call", "name": "validate_token", "line": 12},
#     {"type": "undefined_call", "name": "db.fetch_all", "line": 27}
#   ],
#   "defined_symbols": 342
# }

Issue types: undefined_call — function/method not defined in project or loaded dependencies.

Additional tools (opt-in)

Enable via the HONESTCODE_TOOLS environment variable (see Environment Variables):

export HONESTCODE_TOOLS=index,check_symbol,check_api,execute_code,validate_types
Tool Purpose Speed
index_project Build module-qualified symbol index with content-hash caching < 1s
load_project_deps Parse requirements.txt / pyproject.toml and load dependency APIs < 5s
check_symbol Verify an identifier is defined in the project < 5ms
check_api Verify a library API call exists (with fuzzy typo suggestions) < 10ms
validate_types Structural checks: None iteration, wrong arg counts, calling constants < 20ms
execute_code Run code in sandboxed subprocess with timeout and memory limits varies
explore_call_graph Return callers, callees, and blast-radius summary of a symbol < 5ms (hot)
explore_impact Blast radius of a symbol: transitively impacted symbols/files < 10ms (hot)
affected_files Files/tests affected by a git diff, via reverse call-graph trace < 50ms
find_dead_code Find unused symbols with entrypoint support < 10ms (hot)
find_similar_code Detect function-level code clones via sequence similarity < 2s
search_code Regex search across project source files (FTS5-accelerated) < 100ms
load_package_apis Load API signatures for a single installed package < 3s
get_project_stats Return index statistics (symbol count, dependency APIs) < 5ms
stop_watching Stop the background file watcher started by index_project(watch=True) < 5ms
choose_tool Map a natural-language query to the best tool (debugging) < 5ms

<details> <summary>Detailed parameter reference</summary>

index_project(root_path, force_rebuild=False, watch=False)

Build or reuse the project symbol index. Returns indexed symbol count, root path, and cache status. Set watch=True to start a background file watcher that re-indexes (and invalidates the graph cache) whenever a source file changes, keeping the index fresh for long-running sessions.

explore_impact(symbol_name, max_depth=3)

Compute the blast radius of a symbol: which other symbols and files would be affected if it changed, following callers and callees up to max_depth hops.

affected_files(base="HEAD", head=None, max_depth=4)

Trace a git diff through the call graph to find which files — especially tests — may be affected by uncommitted changes (base vs the working tree) or a range of commits (base..head). CI-friendly: run it after each commit to know exactly which tests to run.

load_project_deps(root_path)

Parse requirements.txt or pyproject.toml and load public API signatures of installed packages.

check_symbol(symbol_name, file_path=None)

Verify a symbol is defined in the indexed project. Symbols use module-qualified names (pkg.core.main).

check_api(api_name)

Check if a library API exists. Returns fuzzy suggestions for typos.

check_api("math.sqrt")    # valid
check_api("math.sqrtt")   # invalid → suggests "math.sqrt"

validate_types(code)

Lightweight structural checks on code snippets:

  • Iterating over None (including dict.get() without default)
  • Wrong argument counts for common builtins (len, sum, etc.)
  • Calling constant values
  • String methods on non-string constants

execute_code(code, prelude="", known_names=None)

Run code in a sandboxed subprocess with timeout and temp working directory.

explore_call_graph(symbol_name)

Return definitions, callers, and callees of a symbol.

find_dead_code(entrypoints=None, ignore_patterns=None, include_tests=True)

Find unused symbols. Provide entrypoints to keep known roots alive.

find_similar_code(threshold=0.85)

Find function-level code clones across the project. Uses length-ratio pre-filter for performance.

search_code(pattern, glob="*.py")

Regex search across project source files.

load_package_apis(package_name)

Load and cache API signatures for a specific installed package.

get_project_stats()

Return statistics about the currently indexed project.

</details>


CLI Usage

Every MCP tool has a CLI equivalent under the honestcode command, for scripts and non-MCP harnesses. Output is JSON; exit code is non-zero when issues are found (so it drops into CI pipelines cleanly).

# Index a project
honestcode index /path/to/project
honestcode index /path/to/project --force

# Load dependency APIs
honestcode deps /path/to/project

# Check a symbol
honestcode check-symbol pkg.core.helper

# Check an API
honestcode check-api pandas.read_csv

# Scan a file (exit 1 if issues found)
honestcode scan src/main.py

# Validate a code snippet (exit 1 if issues found)
honestcode validate "for x in None: pass"

# Execute code in a sandbox
honestcode execute "print(1+1)"

# Find dead code (exit 1 if any dead symbols found)
honestcode dead-code --entrypoints pkg.cli.main --no-tests

# Find similar code (exit 1 if any clones found)
honestcode similar --threshold 0.85

# Explore callers/callees of a symbol (includes blast-radius summary)
honestcode call-graph pkg.core.helper

# Blast radius of a symbol
honestcode impact pkg.core.helper --depth 3

# Files/tests affected by uncommitted changes (CI killer)
honestcode affected --base HEAD
honestcode affected --base main --head feature-branch

# Search code (exit 1 if matches found)
honestcode search "def \w+_helper"

# Load a single package's APIs
honestcode load-package numpy

# Show index statistics
honestcode stats

# Show which tool a query maps to
honestcode choose-tool "is my_symbol defined"

# Bind a directory as a project (creates .honestcode/) and discover the root
honestcode init /path/to/project
honestcode root

# Register the MCP server with Cursor / VS Code / Claude Code
honestcode install --dry-run
honestcode install --client cursor

# Keep an index fresh during long work sessions (Ctrl+C to stop)
honestcode watch /path/to/project

You can also invoke it as a module:

python -m honestcode.cli scan src/main.py

The honestcode-mcp command starts the MCP server (stdio by default); use honestcode-mcp --transport sse --port 8000 for SSE.


Library Usage

Every MCP tool is also a plain function in honestcode.mcp.tools, so the same verification logic can run inside your own Python code — no MCP client required:

from honestcode.mcp.tools import check_symbol, index_project, scan_file

index_project("/path/to/project")          # build/reuse the symbol index
print(scan_file("/path/to/project/src/auth.py"))   # hallucination scan
print(check_symbol("pkg.core.main"))               # symbol lookup

Runnable examples live in examples/ — index & check, API typo detection, scan & validate, and dead-code discovery:

pip install -e .
python examples/01_index_and_check.py /path/to/project

Architecture

Data flow

graph TD
    Client["MCP Client"] -->|tool call| Tools["tools.py (17 tools)"]
    Tools -->|parse file| Extractor["StructureExtractor (Python ast)"]
    Tools -->|lookup symbol| Index["Symbol Index (cache)"]
    Tools -->|graph queries| Graph["Graph Store (SQLite + FTS5)"]
    Tools -->|check API| KB["Knowledge Base (dep APIs)"]
    Index -->|persists| Graph

Module layout

honestcode/
├── mcp/                    # MCP server layer
│   ├── server.py           # FastMCP entry point (stdio + SSE), tool whitelist
│   ├── tools.py            # 17 tool implementations
│   └── knowledge_base.py   # Dependency API signature cache
├── honest/                 # Core hallucination detection
│   ├── router.py           # NL query → tool routing
│   ├── symbol_index.py     # Project-wide symbol index + caching
│   └── project_binding.py  # .honestcode/ binding + MCP client auto-config
├── graph/                  # Persistent graph layer
│   ├── graph_store.py      # SQLite call graph (definitions/refs) + FTS5 index
│   └── watcher.py          # Zero-dependency polling file watcher
├── structure/              # Code structure extraction
│   ├── extractor.py        # AST-based parser (Python ast)
│   ├── multi_lang.py       # Optional tree-sitter extraction (JS/TS/Go/Rust/Java)
│   ├── relations.py        # Edge/relation data structures
│   └── utils.py            # Shared AST utilities
├── sandbox/                # Sandboxed execution
│   └── __init__.py         # Subprocess executor with timeout + resource limits
└── cli.py                  # Command-line interface (every tool as a subcommand)

Class responsibilities

Module Class/Function Responsibility
mcp/server.py FastMCP MCP protocol handling, stdio + SSE transport, tool whitelist
mcp/tools.py Tool functions 17 hallucination-detection tools
mcp/knowledge_base.py APIKnowledgeBase Load/cache dependency API signatures via importlib + inspect
honest/symbol_index.py ProjectIndex Module-qualified symbol index with content-hash caching
honest/project_binding.py init/install .honestcode/ project binding + MCP client auto-configuration
honest/router.py HonestRouter Map natural-language queries to tool intents
graph/graph_store.py GraphCache SQLite call graph (definitions/refs) + FTS5 full-text index
graph/watcher.py ProjectWatcher Polling file watcher with debounce for auto-re-indexing
structure/extractor.py StructureExtractor Parse Python AST, extract defs/imports/edges
structure/multi_lang.py extract_symbols() Optional tree-sitter extraction (JS/TS/Go/Rust/Java)
structure/utils.py call_name() Extract dotted names from AST call nodes
sandbox/__init__.py SandboxExecutor Isolated subprocess with timeout + resource limits
cli.py main() Argparse-based CLI mirroring every MCP tool

Design decisions

Decision Rationale
Standard-library ast Call graphs and file scans use Python's ast module — no native parser dependency, reproducible across platforms
Module-qualified symbols Index stores pkg.module.func so cross-file references are unambiguous
Persistent graph (SQLite + FTS5) The call graph is stored on disk keyed by content hashes, so graph queries skip re-parsing; FTS5 narrows regex searches to candidate files
Lazy loading + caching Dependency APIs and project indices are cached with content-hash invalidation
Zero-dependency watcher File watching uses stdlib polling + debounce instead of a native watcher, keeping the install footprint small
Thread-safe global state Tool state protected by RLock for concurrent MCP requests
Subprocess sandbox execute_code runs in isolation with timeout, memory limits, and restricted PYTHONPATH
Primary tool pattern One well-aimed tool (scan_file) reduces agent mis-picks vs. 17-tool menu
CLI parity Every MCP tool has a 1:1 CLI subcommand so the same checks run in CI without an MCP client

Output safety

All tools enforce output limits to prevent context window bloat:

Tool Max output Strategy
scan_file 50 issues Truncated with "truncated": true
check_api 3 suggestions Fuzzy match capped at top-3
find_dead_code 200 symbols Filtered by ignore_patterns
find_similar_code 50 pairs Length-ratio pre-filter
search_code 100 matches Regex finditer with line limits
explore_call_graph Full No limit (bounded by project size)

When NOT to use HonestCode

Scenario Why it doesn't fit Alternative
Runtime behavior questions AST is static; can't trace execution cProfile, py-spy, logging
Non-Python projects Python is first-class; other languages need [multi-language] extras CodeGraph (20+ languages)
Type inference across packages Structural checks only, not full type solver mypy, pyright
Tiny repos (< 20 files) Index overhead exceeds benefit Direct grep
Highly active monorepos Index may lag behind rapid changes watch mode or CI-integrated checks

Troubleshooting

Symptom Likely cause Fix
No tools visible in agent Server not started Restart MCP client; check MCP config JSON
Project not indexed error index_project not called Call index_project("/path/to/project") first
All symbols report undefined Dependencies not loaded Call load_project_deps("/path/to/project")
execute_code timeout Code contains infinite loop Increase timeout or fix the code
SyntaxError on scan File has invalid Python Fix syntax before scanning
Slow index_project Large project, first run Subsequent runs use cache; use force_rebuild=False
Windows: no memory limit OS limitation Use Docker/WSL2 for untrusted code

Verify setup

# Check the server is importable
python -c "from honestcode.mcp.server import main; print('OK')"

# Check the CLI works
python -m honestcode.cli --help

# Run tests
python -m pytest tests/ -q

Development

# Clone and install
git clone https://github.com/Fengrru/honestcode.git
cd honestcode-mcp
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

# Run tests
pytest

# Lint & format
ruff check honestcode tests scripts
ruff format honestcode tests scripts

# Pre-commit hooks
pre-commit install
pre-commit run --all-files

See CONTRIBUTING.md for pull request guidelines.


Security

execute_code runs in a subprocess with:

  • Timeout protection (default 10s, configurable)
  • Memory limits (256 MB on POSIX via RLIMIT_AS)
  • CPU time limits (POSIX via RLIMIT_CPU)
  • Restricted PYTHONPATH (empty, no inherited modules)
  • Temporary working directory (cleaned up after execution)
  • No console window on Windows (CREATE_NO_WINDOW)

This catches accidental mistakes but is not a hardened security boundary. For untrusted code, use a container or dedicated VM.

See SECURITY.md for vulnerability reporting.


Telemetry

HonestCode collects no telemetry. There are no analytics libraries, no background services, and no phone-home endpoints:

  • All parsing, indexing, and verification run 100% locally — source code never leaves your machine.
  • The server makes no outbound network requests of its own. The only network traffic in your stack comes from the LLM provider your MCP client is configured to use.
  • Every tool returns deterministic JSON you can diff, so verification results are auditable in CI.

This is a design invariant, not a toggle.


Roadmap

  • [x] Persistent call graph (SQLite) + FTS5 full-text search
  • [x] explore_impact blast-radius analysis
  • [x] affected_files git-diff → affected tests (CI killer)
  • [x] File watcher for automatic re-indexing
  • [x] Project binding (.honestcode/) + install for MCP clients
  • [x] Multi-language symbol extraction via optional tree-sitter extras
  • [ ] VS Code extension with inline diagnostics
  • [ ] GitHub Action for PR-level hallucination checks
  • [ ] Remote dependency API caching (PyPI index)
  • [ ] Configurable rules and ignore patterns
  • [ ] Adaptive output budgeting based on project size

Changelog

See CHANGELOG.md for release history.


Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.


License

MIT - Copyright (c) 2026 HonestCode Team

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选