honestcode について
HonestCodeは、コードベース内のシンボルやAPIに照らして、コーディングエージェントが作成したPythonコードを検証するローカルのMCPサーバーです。ASTベースで判定し、LLM呼び出しやネットワークアクセスなしで修正に使える根拠を返します。
主な機能
- 01架空のAPIや誤った呼び出しを検出
- 02リポジトリ内のコードからシンボルを解決
- 03構造化された指摘と根拠を返却
- 04構造的な型チェックを実施
- 05外部副作用の重複実行を抑制
活用シーン
- 01エージェントの作業継続前に生成コードを検証
- 02プロジェクトに存在しないメソッドを特定
- 03修正用の指摘をエージェントに提示
- 04ツール呼び出しの再試行による副作用の重複を防止
MCP 対応
HonestCodeは、`scan_file`や`verify_file`などのコード検証ツールをMCPクライアントに公開します。任意のツールとして、プロジェクトのインデックス作成、シンボル検査、構造的な型検証も利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
2掲載時のツール一覧 · 6 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| file_path | string | はい |
詳細
HonestCode
AI コーディングエージェントのための決定論的な検証レイヤーです。
エージェントが先に進む前に、存在しない API、未定義のシンボル、誤った呼び出しなど、コードのハルシネーションを検出します。

問題
AI コーディングエージェントはハルシネーションを起こします。関数名をでっち上げたり、ライブラリの API を捏造したり、存在しないメソッドを呼び出したりします。
HonestCode は、エージェントがたった今書いたコードを、その根拠とすべきリポジトリと照合するレイヤーです。
Agent
↓
writes code
↓
HonestCode
↓
evidence
↓
Agent fixes
↓
verified code
LLM の呼び出しはありません。ネットワークも使いません。純粋な AST とシンボル解決のみです。
デモ
エージェントは 「既存の UserClient を使って認証を追加してください」 と依頼されました。
生成されたコードは次のとおりです。
client.refresh_token()
実際のプロジェクトにあるのは、次のものだけです。
class UserClient:
def refresh(self): ...
def refresh_access_token(self): ...
HonestCode はこれを決定論的に検出します。
✗ verification failed — 1 issue in app/login_broken.py
[invented_api] app/login_broken.py:9
`UserClient.refresh_token()` does not exist.
did you mean: refresh_access_token()?
available methods:
- refresh()
- refresh_access_token()
confidence: deterministic · action: revise
実際に試してみましょう。
cd demos/invented-api
python run.py
Ruff / Pyright だけでは不十分な理由
HonestCode は置き換えツールではありません。次の具体的な問いに答える検証レイヤーです。エージェントのコードは、実際にこのリポジトリを根拠にしているか?
| エラー | Ruff | Pyright | HonestCode |
|---|---|---|---|
| 構文エラー | ✓ | ✓ | ✓ |
| 型の不一致 | — | ✓ | 構造上の不一致のみ |
| 未定義のシンボル | ✓ | ✓ | ✓ |
| 存在しない API | 一部 | 一部 | 中核機能 |
| 誤ったメソッド呼び出し | — | 一部 | 中核機能 |
| エージェントが生成した API の不一致 | — | — | 中核機能 |
主な違いはリポジトリに基づく検証です。Ruff はファイルをチェックします。Pyright は呼び出しの型をチェックします。HonestCode は、その呼び出しがエージェントの編集対象であるコードベースに実在するシンボルへ解決されるかをチェックします。(HonestCode は完全な型推論は行いません。構造チェックで検出するのは、引数の数の不一致、None の反復、定数の呼び出しであり、一般的な型エラーではありません。)
呼び出し箇所のチェック対象は、レシーバーの型がどのように判明するかによって異なります。注釈(client: UserClient)、コンストラクターの代入(client = UserClient())、self/cls、インラインのコンストラクター(UserClient().refresh())はいずれも解決されます。ファクトリー関数が返すレシーバー(make_client().refresh())は判定対象になりません。この表層モデルでは関数シグネチャに戻り値の型が含まれておらず、ここで推測すると、検出漏れを誤検出と引き換えにすることになるためです。
インストール
1 行で完了します。クローンも仮想環境も不要です。
claude mcp add honestcode -- uvx honestcode-mcp
初回使用時に uvx がサーバーを隔離環境へ取得します。uv がインストールされていない場合は、先に uv をインストールしてください。チェックアウトから使う場合(コードを変更する場合や、uv を使いたくない場合)は、次のとおりです。
git clone https://github.com/Fengrru/honestcode
cd honestcode
pip install -e .
claude mcp add honestcode -- honestcode-mcp
Cursor / VS Code / Claude Desktop: honestcode install コマンドは各クライアントの設定ファイルを検出し、サーバーを登録します。
honestcode install # all detected clients
honestcode install --client cursor --dry-run # preview without writing
Python >= 3.10 が必要です。処理はすべてローカルで実行されます。
Claude Code での 30 秒セットアップ
# Add HonestCode as an MCP server
claude mcp add honestcode -- honestcode-mcp
または、Claude Code の設定(macOS/Linux では ~/.claude.json、Windows では %USERPROFILE%\.claude.json)に手動で追加します。
{
"mcpServers": {
"honestcode": {
"command": "honestcode-mcp",
"args": []
}
}
}
Claude Code を再起動します。次の 2 つの検証ツールが使えるようになります。
scan_file(path)— 従来のツールです。issuesと新しい形式のエビデンスを返します。verify_file(path)— エージェント向けのツールです。status、evidenceを含むfindings、および人が読めるtextの要約を返します。
Claude に次のように指示してみてください。
Add a login endpoint using the existing UserClient, then run verify_file on the
file you just wrote and fix anything it reports.
HonestCode はファイルパスからプロジェクトのルートを自動検出し、コードベースをインデックス化して、根拠に基づくエビデンスを返します。
自動化する方法(プロンプトで指示する必要はありません)
MCP ツールが実行されるのは、モデルが呼び出しを選択した場合のみです。検証を無条件に行うには、scripts/claude_hook.py のフックを Claude Code の PostToolUse イベントに接続します。エージェントが作成する .py ファイルはすべて検証され、問題が見つかると編集をブロックし、根拠をそのまま会話に返します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python /absolute/path/to/honestcode/scripts/claude_hook.py"
}
]
}
]
}
}
これを ~/.claude/settings.json(すべてのプロジェクト)または
.claude/settings.json(1つのプロジェクト)に設定します。このフックは、自身のエラーによって処理をブロックすることはありません。入力が読み取れない場合、Python 以外のファイルの場合、検証がクラッシュした場合はすべて無言で終了するため、あらゆる編集を妨げる障壁にはなりません。
実例
# auth/client.py
class UserClient:
def refresh_access_token(self): ...
# auth/login.py
from auth.client import UserClient
def login(client: UserClient):
client.refresh_token() # invented API
>>> from honestcode.mcp.tools import verify_file
>>> verify_file("auth/login.py")
{
"status": "fail",
"file": "auth/login.py",
"findings": [
{
"line": 7,
"kind": "invented_api",
"symbol": "refresh_token",
"owner": "UserClient",
"message": "`UserClient.refresh_token()` does not exist.",
"evidence": {
"available_methods": ["refresh", "refresh_access_token"],
"did_you_mean": "refresh_access_token"
},
"confidence": "deterministic",
"action": "revise"
}
],
"text": "✗ verification failed — 1 issue in auth/login.py\n ..."
}
エージェント出力プロトコル
verify_file は、単なるエラーメッセージではなく、エージェントが直接対処できる根拠を返します。
{
"status": "fail",
"file": "auth/client.py",
"line": 42,
"kind": "invented_api",
"symbol": "refresh_token",
"owner": "UserClient",
"message": "UserClient.refresh_token() does not exist.",
"evidence": {
"available_methods": ["refresh", "refresh_access_token"]
},
"confidence": "deterministic",
"action": "revise"
}
仕組み
- プロジェクトを自動インデックス化します(またはキャッシュされたシンボルインデックスを再利用します)。
- 標準ライブラリの
astモジュールで対象ファイルを解析します。 - すべての呼び出し箇所を具体的なシンボルに解決します。
- アノテーション、コンストラクター、インポートからレシーバーの型を推論します。
- リポジトリの AST からクラスのメンバー構成を再構築します。
- 基底クラスを解決できない場合や、クラスで
__getattr__が定義されている場合は、メンバー構成を不明として扱います。
kind、owner、evidence、confidence、actionを含む検出結果を出力します。
このループは決定論的で、監査可能です。
対象範囲と制限事項
検証ツールは、不在を証明できない場合には何も報告しません。これはこの機能の特長ですが、検出範囲には既知の制限があります。
- デコレーター付きクラスでは、存在しないメンバーを検出しません。 クラスデコレーター(
@dataclassを含む)はメンバーを追加または書き換える可能性があるため、そのようなクラスに対する存在しないメソッド呼び出しは報告されません。デコレーターのないクラスはすべて検査されます。 - 標準ライブラリのメンバー呼び出しは検査されません。
from typing import TypeVarr(存在しないインポート)は検出されますが、os.path.joinn()(実在するモジュールに対する存在しない呼び出し)は検出されません。検査対象はサードパーティおよびプロジェクトのメンバーです。 - ファクトリー関数のレシーバーは検査されません。
make_client().refresh()はスキップされます。アノテーション、コンストラクターへの代入、self/cls、インラインコンストラクター(UserClient().refresh())は解決されます。 undefined_symbolのconfidenceはdeterministicではなくhighです。 リポジトリから証明できるのは、メンバー構成に関する主張(メンバーが完全に列挙されたクラスに存在しない API)だけです。名前が存在しないという判断は構文上のバインディングモデルに基づくため、信頼度は低くなります。同じスコープ内で型をまたいで再代入される変数は不明として扱われ、判定対象になりません。- グラフツールは、最後にインデックス化されたプロジェクトを基準にします。
scan_file/verify_fileはファイルごとにプロジェクトルートを解決します(モノレポ内のサブプロジェクトを含みます)。find_dead_code、explore_call_graph、search_codeなどは、直近でindex_projectに渡されたプロジェクトを対象にします。 check_apiは必要に応じてベースパッケージをインポートしますが、実際にインストールされている場合(または標準ライブラリの場合)に限られます。ワークスペースに置かれた単独のファイルがインポートされることはないため、エージェントが作成したコードがこのツールを通じてサーバー側で実行されることはありません。
MCP ツール
デフォルトでは、scan_file と verify_file が公開されています。以下を含むすべてのツールを有効にするには、HONESTCODE_TOOLS=all
を設定してください。
| ツール | 目的 |
|---|---|
scan_file | ファイルをスキャンし、架空の API、未定義の呼び出し、誤った引数の数を検出します。 |
verify_file | エージェント向けの構造化されたエビデンスプロトコルを返します。 |
index_project | プロジェクトのシンボルインデックスを作成または再利用します。 |
load_project_deps | requirements.txt / pyproject.toml から依存関係の API を読み込みます。 |
check_symbol | シンボルが定義されているか確認します。 |
check_api | ライブラリの API 呼び出しが存在するか確認します。 |
validate_types | 構造的な型チェックを行います。 |
依存関係マニフェスト(requirements.txt、pyproject.toml)は、最初のスキャン時に
自動的に宣言されます。そのため、MCP サーバーのインタープリターにインストールされていない
依存関係からのインポートは、架空のものとして報告されず、信頼されます。これを無効にするには、
HONESTCODE_AUTO_DEPS=0 を設定してください。
完全な一覧については、以下の以前のツールリファレンスをご覧ください。
クラッシュに強い副作用
verify_file はコードの実行前にチェックします。実行後に起きることは guards/ が扱います。
ツール呼び出しを再試行するエージェントは、カードへの請求を二重に行う可能性があります。また、永続的な実行エンジンであっても、
それを防ぐことはできません。Temporal と Restate はどちらも
オーケストレーション の決定論的なリプレイを保証しますが、外部への副作用を一度だけ実行する責任は
アプリケーションに委ねています。
from honestcode.guards import EffectStore, SideEffectGuard, durable_scope
guard = SideEffectGuard(session_id="run-42", store_path=".agent/effects.db")
outcome = guard.run(
"charge",
target="cus_123",
payload={"cents": 4200},
execute=lambda: charge_card("cus_123", 4200),
approve_irreversible=True,
scope=durable_scope("order-4711", "charge", "cus_123"),
)
outcome.executed # False on the retry — a receipt, not a second charge
outcome.effect_id # stable across a restart, because the key is on disk
重要なのは、scope が何をするかです。これを渡すと、副作用の識別情報はセッションではなくスコープから得られます。
これが、再試行が認識されるか、顧客への請求が二重に行われるかの違いです。再起動すると
新しいセッション ID が割り当てられるためです。何も渡さなければ、ガードはセッション単位のままです。
デフォルトでは、拒否する方向に動作します。認識されないアクションは冪等ではなく、
取り消し不能なものとして扱われ、取り消し不能な副作用には明示的な承認が必要です。
呼び出しから記録までの間に実行が停止すると、副作用は executing のままになり、
次の試行では推測することなく、結果は不明として報告されます。これにより再試行が防止されます。
スコープ付きの副作用は guard.recover(scope=durable_scope(...)) で復旧でき、
guard.effects(scope=...) / guard.summary(scope=...) で確認できます。記録はスコープから
派生した名前空間に保存されるため、再起動後も見つけることができます。
フレームワーク向けには、integrations/ がガードを pydantic-ai にバインドします。コミット済みの副作用がある場合、
ツールを再実行する代わりに、そのツールの結果が置き換えられます。
honestcode/integrations/README.md をご覧ください。
ベンチマーク
HonestCode には 4 つのベンチマークスイートが含まれており、main へのプッシュや
プルリクエストのたびに、CI で自動的に実行されます。
エージェント精度ベンチマーク
benchmarks/agent_accuracy/ は決定論的で LLM を使わないベンチマークで、よくあるエージェントのハルシネーションを HonestCode がどれだけ検出できるか(再現率)を測定します。
各タスクは小規模なエージェントのエピソードです。エージェントが壊れたファイルを書き、HonestCode が検証した後、ファイルを修正後の内容に置き換えて再度検証します。
cd benchmarks/agent_accuracy
python run.py
現在の結果(6 タスク、決定論的検証):
| タスク | 想定される問題 | 壊れた状態を検出 | 修正後に問題なし | 壊れた状態の時間(ms) | 修正後の時間(ms) |
|---|---|---|---|---|---|
| invented_method | invented_api (UserClient.refresh_token) | はい | はい | 4.18 | 3.78 |
| invented_module_attr | invented_api (Connection.query) | はい | はい | 4.19 | 3.95 |
| undefined_import | undefined_symbol (delete_user) | はい | はい | 2.69 | 3.55 |
| wrong_signature | wrong_call (add()) | はい | はい | 3.56 | 3.35 |
| cross_file_new_symbol | invented_api (fly) | はい | はい | 3.85 | 2.45 |
| dep_alias_and_pypi_name | invented_api (toll) | はい | はい | 3.44 | 2.9 |
概要: 適合率 1.0、再現率 1.0、F1 1.0、偽陽性率 0.0、ノート PC での検証時間の中央値は 4~7 ms です。
上記のタスクごとのミリ秒値は、ある 1 回の実行結果であり、保証値ではありません。同じマシンでも実行ごとに数十パーセント程度変動します。安定しているのは、最初の 4 列と概要に示された件数であり、ベンチマークの合否判定にもこれらが使われます。
概要行には、このファイルに転記した値ではなく、python benchmarks/agent_accuracy/run.py の出力をそのまま掲載しています。ここに記載した時間は、コードが高速化した瞬間に古くなるためです。実際にそうなったことがあります。--format markdown を指定すると再現できます。
cross_file_new_symbol タスクでは、エージェントセッションのフロー(モジュールを書き、その後にそれをインポートするファイルを書く。インデックスは古くならず、常に最新であること)を固定します。dep_alias_and_pypi_name タスクでは、エイリアス付きサブモジュールと PyPI 名の要件(PyYAML → yaml)を通じた依存関係の特定を固定します。
実コードの偽陽性ベンチマーク
benchmarks/realworld_fp/ は実コードでの適合率を測定します。ベンダーに含めた psf/requests のスナップショット(19 ファイル、約 6.4k LOC、Apache-2.0)をスキャンし、HonestCode が検出結果をゼロ件報告することを確認します。実コードでは、合成タスクでは決して使われない構文、つまり標準ライブラリのインポート、キーワード引数を使った呼び出し、@staticmethod メンバー、標準ライブラリの ABC を継承するクラス、互換性のための再エクスポートモジュールなどが使われます。このコーパスで検出結果が出れば、構成上、それは偽陽性です。
同じ実行で benchmarks/realworld_fp/regressions/ もスキャンします。ここには、実際に見つかった偽陽性の種類ごとに、小規模なプロジェクトが 1 つずつ含まれています(異なる型をまたいで再束縛されたレシーバー、with ... as バインディング、モノレポのサブプロジェクトのインポート、ローカルバインディング形式)。回帰が再発した場合、シナリオ名を示してベンチマークが失敗します。
python benchmarks/realworld_fp/run.py
# files: 25 findings: 0 elapsed: 0.7s (~26 ms/file)
検出件数が主張の根拠です。経過時間は参考値であり、マシンによって異なります。
値のずれに関するベンチマーク
benchmarks/value_drift/ では、別の問いを検証します。書式の違いを許容する編集マッチャーが検索文字列を解決したとき、編集は呼び出し元が指定した領域に適用されたのか、それとも異なる値を持つ、よく似た別の箇所に気づかないまま適用されたのか、という問いです。ガード付きのマッチャーの連鎖とガードなしのものを使い、10 個のシナリオを実行して、各編集を correct、silent_drift、no_match、wrong_span のいずれかに分類します。ガード付きマッチャーは、すべてのシナリオで意図した編集を行わなければなりません。no_match は拒否を意味し、合格ではありません。
python benchmarks/value_drift/run.py # human-readable
python benchmarks/value_drift/run.py --json # machine-readable (status on stderr)
パフォーマンスベンチマーク
scripts/benchmark.py は、リポジトリ自体に対するコア操作(インデックス作成、スキャン、グラフ、デッドコード検出、類似性検索)のレイテンシを測定します。
python scripts/benchmark.py # text output
python scripts/benchmark.py --format markdown # table for README
python scripts/benchmark.py --repo psf/requests # benchmark a real-world repo
4 つのベンチマークはすべて、CI(.github/workflows/ci.yml)で個別のジョブとして実行されます。ジョブ名は benchmark-accuracy、benchmark-realworld、benchmark-value-drift、benchmark-performance です。accuracy ジョブでは適合率と再現率が 1.0 を維持していること、real-world ジョブでは検出結果がないこと、またはスキャンが失敗していること、value-drift ジョブでは保護対象のすべてのシナリオが正しく実行されることをゲート条件としています。performance ジョブは数値を報告しますが、ゲート条件にはしません。
データセットの形式と精度タスクの追加方法については、benchmarks/agent_accuracy/README.md を参照してください。
アーキテクチャ
honestcode/
├── verify/ # Evidence protocol + repository-grounded verification
├── mcp/ # MCP server layer
├── honest/ # Symbol index + project binding
├── graph/ # Persistent call graph (SQLite)
├── structure/ # AST extraction
├── sandbox/ # Sandboxed execution
├── guards/ # Crash-safe side effects (stdlib-only, extractable)
├── integrations/ # Framework bindings — pydantic-ai today
└── cli.py # Command-line interface
verify_file はエージェント向けのインターフェースです。デフォルトでは scan_file も併せて公開され、新しいエビデンス形式と従来の issues リストの両方を返します。
これらのディレクトリのうち 2 つは、ほかとは異なる問いに答えます。guards/ より上のすべては、このコードはリポジトリと整合しているか を問います。guards/ が問うのは、この処理はすでに実行されたか です。クラッシュ後にエージェントがツール呼び出しを再試行すると、カードに二重請求してしまう可能性があります。また、永続実行エンジンでは、外部への副作用を厳密に 1 回だけ実行する処理はアプリケーションに任されています。integrations/ はガードをフレームワークに結び付けます。最初の対応は pydantic-ai の wrap_tool_execute で、副作用がすでにコミットされている場合、ツールの結果は再実行されずに置き換えられます。
guards/ は意図的に標準ライブラリのみに依存し、このパッケージのプロトコルには依存しないため、独立したディストリビューションとして切り出せます。tests/test_guards.py は AST インポートチェックでこれを保証します。
ロードマップ
v0.1 — リポジトリに基づく検証(完了)
- シンボル/API/関数/クラス/メソッド/インポート/呼び出しの検証
- 構造化エビデンスによる、架空の API の検出
scan_fileでの自動インデックス作成
ロードマップ以降 — クラッシュセーフな副作用(現在)
検証レイヤーではないため、以下の v0.2/v0.3 の流れには含まれません。guards/ はクラッシュをまたいで副作用を冪等にし、integrations/ はそれを pydantic-ai に結び付けます。これは「すでに実行されたか」という、静的なものではなく実行時の問いに答えます。
v0.2 — セマンティックな契約の検証
- 関数が
UserIDを想定しているのに、エージェントがUserを渡す → 要注意
v0.3 — 実行の検証
- 静的検証 → テスト → 実行時エビデンス
v1.0 — コーディングエージェント向け検証ランタイム
Coding Agent
│
┌───────▼───────┐
│ HonestCode │
│ Verification │
│ Runtime │
└───────┬───────┘
│
┌──────────────┼──────────────┐
↓ ↓ ↓
Static Semantic Runtime
Verification Verification Verification
│ │ │
└──────────────┼──────────────┘
↓
Evidence
↓
Agent
開発
git clone https://github.com/Fengrru/honestcode.git
cd honestcode
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS/Linux
pip install -e ".[dev]"
pytest
ruff check honestcode tests scripts
ベンチマークをローカルで実行します。
# Accuracy benchmark
python benchmarks/agent_accuracy/run.py
# Performance benchmark
python scripts/benchmark.py
プルリクエストのガイドラインについては、CONTRIBUTING.md を参照してください。
セキュリティ
脆弱性の報告については、SECURITY.md を参照してください。
テレメトリ
HonestCode はテレメトリを一切収集しません。 分析ライブラリも、バックグラウンドサービスも、外部へのデータ送信エンドポイントもありません。
ライセンス
MIT - Copyright (c) 2026 HonestCode Team
MCP Registry: mcp-name: io.github.Fengrru/honestcode
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。