Batcave-MCP
Batcave — レジュメレビューMCPサーバー
2つのドキュメント — レジュメ と 求人情報 — を受け取り、3段階のレビューを実行するMCPサーバーです。各段階は次の段階に受け渡されます。マッチレポートができる前に書き換えはできず、書き換えができる前にATSパスは実行できません。
パイプライン
ツール | 機能 |
| 受け付け。レジュメと求人情報を生テキストまたは |
| ステージ1。 対象企業のシニアリクルーター: 100点満点のマッチスコア、不足しているキーワード上位5件、採用担当者が10秒以内に見つける3つのレッドフラグ。 |
| ステージ2。 経験セクションを、ステージ1のキーワードを盛り込みレッドフラグを除去する形で書き換えます。すべての箇条書きはGoogle XYZ形式 — Xを達成し、Yで測定され、Zを行うことによって。 |
| ステージ3。 ATSパーサーパスに加え、200件中147件目のレジュメを見る採用担当者: どのセクションがスキップされるかを特定し、スクロールを止めるように書き換えます。最終レジュメを返します。 |
| どのステージが完了済みか、結果待ちか、未開始か、次に何を呼ぶべきかを示します。 |
| 保存済みセッションを、最近更新された順に表示します。 |
| レビュー全体 — 3つのステージすべてと最終レジュメ — を1つのマークダウンドキュメントとして返します。 |
| セッションとそれに関連付けられたすべてのデータを削除します。自動的に期限切れになるものはありません。 |
Related MCP server: resume-fit-scanner
ステージの実行方法
サーバーはモデルを呼び出しません。ブリーフを構成し、状態を保持し、順序を強制します。推論を行うのは接続されたクライアントのモデルです。したがって、各ステージツールは2回呼び出されます:
{ session_id }— そのステージの分析ブリーフを返します。レジュメ、求人情報、およびそれ以前のすべてのステージの出力がすでに埋め込まれています。{ session_id, result }— 回答を記録します。resultはステージのスキーマに対して検証されるため、4つのキーワードしかないレポートは保存されずに拒否されます。
ステージ2は記録されたステージ1のレポートを読み取ります。ステージ3はオリジナルではなく、ステージ2の updated_resume を読み取ります。順序を無視して呼び出されたステージは、最初に呼び出す必要があるツール名とともに失敗します。
ブリーフに組み込まれた2つのルール
捏造された数値は禁止。 元のレジュメに数値がない場合、書き換えは
[QUANTIFY: 測定するもの]を出力し、それをplaceholders_needing_user_inputにリストします。キーワードの詰め込みは禁止。 キーワードは実際の経験がそれを裏付ける場合にのみ入れられ、残りは理由とともに
keywords_not_addressedに返されます。
トランスポート
2つのエントリーポイント、同じツール:
エントリー | トランスポート | 用途 |
| stdio | 同じマシン上のクライアント — Claude Code、IDE |
|
| リモートクライアント — コンテナ内で実行されるのはこちら |
stdioは1台のマシン上の2つのプロセス間のパイプであり、ネットワーク経由で到達することはできません。stdioを提供するコンテナは接続を受け付けないため、EC2パスが serve.ts を使用するのはそのためです。
serve.ts は2つの変数を必要とし、どちらかがなければ起動を拒否します:
DB_URL— Postgres接続文字列MCP_AUTH_TOKEN— 共有シークレット。すべてのリクエストにAuthorization: Bearer <token>が必要です。
GET /healthz は認証不要の唯一のルートです。データベース接続を開かないため、それをポーリングするロードバランサーがPostgresを起動することはありません。
ストレージ
すべてはPostgresに保存されます。サーバーはローカルディスクに何も書き込みません — ローカルで読み取るのは、指定したレジュメと求人情報のファイルのみです。
resume_sessions(id, created_at, updated_at, company, role,
resume jsonb, job_description jsonb)
resume_stages(session_id -> resume_sessions.id on delete cascade, stage, status,
issued_at, completed_at, result jsonb, primary key (session_id, stage))
schema_migrations(module, id, applied_at) -- shared, owned by src/platform/db.ts1つのドキュメントではなく2つのテーブルを使用するため、ステージの記録は両方のレジュメを書き換えるのではなく1行を書き込むだけで済み、list_sessions はドキュメントテキストをまったく選択しません。テーブルにはモジュールのプレフィックスが付けられ、マイグレーションはそのモジュールの最初のクエリで遅延実行されます — サーバーの起動はデータベースを起動しません。
マイグレーションは追記のみで、schema_migrations に記録されるため、各マイグレーションはデータベースごとに正確に1回実行されます。bun run db:migrate は保留中のものを適用します。サーバーはフォールバックとして、モジュールの最初のクエリでも遅延実行します。
自動的に期限切れになるものはありません。セッションは delete_session が削除するまで蓄積されます。
実行方法
bun install
bun run dev # Postgres + the server, hot reload, nothing to configureこれは docker compose -f docker-compose.dev.yml up --build です: Postgresを起動し、開発用とテスト用のデータベースを作成し、マイグレーションを実行し、トークン dev-token-not-a-secret で http://127.0.0.1:3000/mcp でMCPを提供します。src/ 配下の何かを編集すると、実行中のサーバーがリロードされます。
代わりにホスト上でサーバーを直接実行するには:
export DB_URL='postgres://postgres:postgres@localhost:55432/batcave'
bun start # stdio, for a client on this machine
bun run serve # HTTP on :3000, also needs MCP_AUTH_TOKENサーバーの実行を必要としない2つのデータベースコマンド:
bun run db:check # can this machine reach DB_URL, and what is in it?
bun run db:migrate # create or update the tables; safe to run repeatedlydb:check は、サービスを提供せずに接続を開く唯一のものです。両方のエントリーポイントは起動時に DB_URL を検証しますが、最初のクエリで遅延接続するため、クリーンな起動は何も証明しません。
チェック:
bun run check # Biome format + lint (check:fix to apply)
bun run typecheck
bun test # unit tests; no database needed
TEST_DB_URL='postgres://postgres:postgres@localhost:55432/batcave_test' bun testエンドツーエンドテストは、実際のPostgresに対して実際のワイヤープロトコルで通信し、ティアダウン時にテーブルを削除します。これらは DB_URL ではなく、意図的に TEST_DB_URL を読み取るため、サーバーを実際のデータベースに向けてもティアダウンを仕掛けることはできません — また、開発スタックには別の batcave_test データベースが同梱されているため、テストを実行しても実行中のサーバーを妨げることはありません。
このディレクトリの .mcp.json は、Claude Code用にstdioサーバーを登録します。別のクライアントの場合:
{ "command": "bun", "args": ["index.ts"], "cwd": "/path/to/Batcave" }EC2での実行方法
export DB_URL='postgres://user:pass@host/db?sslmode=require'
export MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
bun run db:check # confirm the instance is reachable from this box
docker compose run --rm mcp bun scripts/migrate.ts # create the tables
docker compose up -d --build
docker compose logs -f mcpサーバーがトラフィックを受ける前にマイグレーションを実行してください。 これをスキップすると、最初のツール呼び出しで自動的にマイグレーションされますが、その場合、壊れたマイグレーションはデプロイの失敗ではなくユーザーリクエストの失敗として表面化し、最初の呼び出し元がスキーマを待つことになります。新しいマイグレーションを同梱するデプロイのたびに db:migrate を再実行してください。適用するものがない場合は何もしません。
Composeは、どちらかの変数が未設定の場合、起動を拒否します。シェルプロファイルまたはインスタンスシークレットに保管してください — このリポジトリのファイルには入れないでください。
公開ポートは意図的に 127.0.0.1:3000 です。 エンドポイントは平文HTTPで通信し、ベアラートークンで認証します。オープンインターネット上では、そのトークンは経路上の誰にでも読み取られます。その前にTLSを配置してください — HTTPSを終端してインスタンスに転送するALB、または同じボックス上のnginx/Caddyが 127.0.0.1:3000 にプロキシする方法です。その後、セキュリティグループはクライアントからの443のみを許可し、それ以外は許可しないようにします。ポート3000は外部に閉じたままにします。
トークンのローテーションは export MCP_AUTH_TOKEN=... && docker compose up -d で、コンテナが再起動されます。全員に1つのトークンがあります — 誰も特定しないため、あなたのセッションと友人のセッションを区別できません。ユーザーごとのアクセスには、実際の認証と resume_sessions のオーナー列が必要ですが、どちらもまだ存在しません。
resume_path はコンテナ内で解決されるため、リモートの呼び出し元はそれを使用できません — 彼らのラップトップ上のパスはサーバーにとって意味がありません。HTTP経由では、resume_text と job_description_text を渡してください。ボックス上のファイルでパス形式を機能させたい場合は、ボリュームをマウントしてください。
docker-compose.yml は本番スタックのみです。ローカル開発では docker-compose.dev.yml を使用し、独自のPostgresを同梱し、この構成を一切共有しません。
レイアウト
サーバーはモジュールのホストです。モジュールとは、独自のテーブルと独自の語彙を持つ、自己完結型のツールファミリーです。レジュメレビューは今日のところ唯一のものであり、2つ目の無関係なモジュールは src/features/ 配下のフォルダーと、index.ts のリストの1エントリです。
index.ts stdio entrypoint
serve.ts HTTP entrypoint (the container runs this)
src/modules.ts the one list of mounted modules, shared by both entries
src/module.ts the ToolModule contract every feature implements
src/server.ts mounts modules onto an McpServer
src/http.ts Streamable HTTP handler, bearer auth, /healthz
src/platform/ feature-agnostic; knows nothing about resumes
db.ts lazy Postgres pool + per-module migration runner
documents.ts text / pdf / docx extraction
stored-document.ts what an extracted document looks like
tool-result.ts keeps `content` and `structuredContent` in step
src/features/resume-review/
index.ts the ToolModule: name, migrations, register()
migrations.ts this module's tables
sessions.ts repository, domain types, stage gating
briefs.ts the three briefs
schemas.ts zod schema per stage result
stage-tool.ts the brief-then-record tool shape
dossier.ts markdown rendering
tools/ one file per group of registered tools
intake.ts, stages.ts, dossier.ts, session-admin.ts構造を支える2つのルール:
src/platformはsrc/featuresからインポートしません。 2つ目のモジュールも必要とするものはplatformに属し、レジュメレビューのみが必要とするものはフィーチャーに残ります。モジュールは他のモジュールをインポートしません。 互いを知る必要がある2つのモジュールは、1つのモジュールです。
stage-tool.ts はplatformではなく、意図的にフィーチャー内に配置されています。ブリーフ→記録の形状は再利用可能になるかもしれませんが、今日のところ消費者は正確に1つであり、2つ目が存在する前に一般的なケースを推測することは、プラットフォーム層が腐る方法です。
モジュールの追加
// src/features/interview-prep/index.ts
export const interviewPrep: ToolModule = {
name: "interview-prep",
migrations, // its own tables, namespaced in schema_migrations
register(server) {
registerWhateverTools(server);
},
};// index.ts
const server = createServer([resumeReview, interviewPrep]);これが契約のすべてです。マイグレーションはそれぞれ1回適用され、schema_migrations でモジュールごとに追跡され、そのモジュールが最初にデータベースに触れたときに遅延実行されます — 未使用のモジュールはラウンドトリップを消費しません。tests/modules.test.ts は、レジュメとは無関係のスタブモジュールでシームをテストします。
貢献
CONTRIBUTING.md を参照してください — bun run dev がセットアップ全体です。セキュリティの問題は公開イシューではなく、SECURITY.md を通じて報告してください。
ライセンス
MIT。
This server cannot be deployed
Maintenance
Related MCP Connectors
Tailor a CV to a job posting: score the match, propose a reviewable rewrite, export PDF or Word.
Free ATS resume score and job-match checker: scores a resume against a job description.
Score and tailor your CV/resume against a job posting — for AI agents and humans, no-login trial.
Recruiter-style resume checker: scores, shortlist decisions, risks, CV rewrites and interview prep
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables tailoring resumes to job descriptions by scraping JDs, applying rules, and generating optimized DOCX resumes.11-
- AlicenseNot gradedqualityDmaintenanceAnalyzes resume text against job descriptions to provide ATS fit scores, missing keywords, and suggestions.MIT
- AlicenseNot gradedqualityBmaintenanceEnables JD-aware resume matching through MCP tools, providing deterministic scoring, gap analysis, bullet rewrites, and tailored cover letter generation.13 npmMIT
- AlicenseAqualityDmaintenanceEnables MCP clients to analyze resumes for ATS compatibility, parse job descriptions, get optimization and roast-style critiques, and generate tailored resumes with shareable preview links.60MIT