job-assistant-mcp
Integrates with Google Gemini models for the agent and retrieval layers: use Gemini as the agent LLM via LLM_PROVIDER=gemini, generate dense embeddings with gemini-embedding-001 via EMBEDDINGS=gemini, and configure access with a GEMINI_API_KEY from Google AI Studio.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@job-assistant-mcpcompare this job posting against my profile and flag missing requirements"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
job-assistant-mcp
An MCP job-search assistant: a tool-calling agent over an MCP server, a lightweight RAG layer over your own profile, and a small eval harness that tells you whether a change made things better.
Status: M4 (evals). MCP server, provider-neutral agent loop, profile retrieval and an eval harness work end to end; a Gemini baseline is recorded in docs/EVALS.md. Roadmap: docs/PLAN.md.
What works today
MCP tool | Reads/writes | Notes |
| read | Deterministic JD structuring (sections, years, work mode, skills). No model inside the server. |
| read | Filter by status / company. |
| read | Open applications with a follow-up due in N days (overdue included). |
| read | BM25 search over your Markdown profile; returns passages with citable chunk ids. Works for English and Chinese. |
| read | Compares a JD to the profile: per requirement |
| write | Returns a preview unless |
| write | Same confirm gate; unknown ids return an error the model can recover from. |
About the application tracker
add_application, update_application, list_applications and list_followups work on a plain JSON file
(APPLICATIONS_FILE, default data/sample/applications.json): a status-tracked list of applications with follow-up
dates, not a visual kanban board. There is no export tool, and the file format is not yet compatible with the
Pensum board's import/export format (planned, see
docs/PLAN.md). Writes are previews until confirm=true is passed. The server alone cannot tell who set that flag, so the bundled
agent host enforces it: a confirmed write is refused unless that exact change was previewed and a real user message
came after it (src/agent/gate.ts). Other MCP clients get only the preview step. The gate proves a human turn happened,
not that the answer was yes.
Models and retrieval seams
The agent host (src/agent) connects to the server over stdio and drives any model through a small
LLMClient interface, so the model can be swapped without touching the loop.
Seam | Choose with | Status |
Agent model: Gemini |
| Verified live (free tier), baseline in docs/EVALS.md |
Agent model: Claude |
| Implemented; unit-tested and checked against the real SDK's HTTP request shape with a fake network. Not yet run against the live API |
Eval judge |
| Independent of the agent model; never inherits its model id |
Dense retrieval |
| Gemini embeddings verified live ( |
The Claude adapter replays the model's own content blocks between tool calls (thinking blocks must come back
unchanged) and enables server-side refusal fallback by default; set LLM_FALLBACK=off on Bedrock/Vertex/Foundry.
Related MCP server: Job Application MCP
Retrieval
data/sample/profile/*.md (or PROFILE_DIR) is chunked by heading (Resume > Experience > Role), indexed with
BM25, and with EMBEDDINGS=gemini fused with dense vectors via reciprocal rank fusion. search_profile returns
keyword coverage and semantic similarity per hit. match_resume combines word overlap with embedding similarity, but
similarity can only add weak evidence (never supported on its own), and quantities such as "5+ years" never
exceed weak.
Known limits: numeric requirements ("5+ years") are flagged, not computed. On the hand-labelled set, embeddings improved
requirement matching from 71% to 79% (two related passages surfaced) but recognised no extra supported paraphrase,
because correct and wrong matches have overlapping similarity; details in docs/EVALS.md.
Quick start
pnpm install
cp .env.example .env # add GEMINI_API_KEY (from Google AI Studio)
pnpm test # no API key needed
pnpm agent "Which applications need a follow-up this week?"
pnpm agent # interactiveThe server can also be mounted directly in any MCP client (e.g. Claude Desktop):
{ "mcpServers": { "job-assistant": {
"command": "node",
"args": ["--import", "tsx", "src/server/index.ts"],
"cwd": "/absolute/path/to/job-assistant-mcp",
"env": { "APPLICATIONS_FILE": "data/sample/applications.json" }
} } }Evals
pnpm eval:retrieval # recall@k / MRR of the retriever, no API key needed
pnpm eval --judge --judge-model gemini-3.5-flash-lite --repeat 3 --rpm 12
# 33 cases (29 core + 4 extended), 3 samples each, separate judge modelRule-based graders check tool choice, arguments, the write-confirmation gate, citations and number grounding; an LLM
judge (a different model from the agent) covers the rest. Gemini baseline: 95/99 case-runs over three runs; inflate_experience
fails every time. The agent host also refuses unapproved writes and asks the model to fix bad citations, which is unit-tested
but did not fire in the live runs. Details, caveats and what the failures showed: docs/EVALS.md.
Observability
Runs can write a JSONL trace (model calls with API time, retries and tokens; tool calls with duration; host guard
actions). TRACE_DIR=.traces pnpm agent "..." then pnpm trace .traces/ prints a timeline and performance
percentiles; eval reports include a performance section. Real example and caveats: docs/OBSERVABILITY.md.
Demo
Unedited runs against Gemini, including the model's mistakes: docs/demo.md.
Privacy
Only synthetic data lives in data/sample/. Your real profile and applications go in
data/profile/ and data/applications.json, both git-ignored. The Gemini free tier may use
requests to improve Google's products, so keep real personal data out of it; use synthetic data
until you switch to a paid or local model.
Layout
src/server/ MCP server (tools, JD parser, resume matching)
src/rag/ tokenizer, heading-aware chunker, BM25, hybrid fusion
src/store/ application tracker storage (JSON file)
src/agent/ agent loop, host write gate and citation guard, tracing, CLI, llm/ (provider-neutral client, adapters, cache, limiter)
data/sample/ synthetic resume, JD, applications
evals/ case files, graders, runner, retrieval metrics
tests/ vitest; the agent loop is tested against the real server with a scripted modelThis server cannot be deployed
Maintenance
Related MCP Connectors
Analyze job listings against your resume, track applications, and generate cover letters.
Job search for your AI: save jobs, research companies, keep stories, track applications.
1Manage job applications — jobs, companies, boards, notes, and profile — from your AI client.
Search jobs, prepare resumes and cover letters, retrieve PDFs, and track your applications.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceEnables Claude Desktop to manage a job search end-to-end: find and score job listings, tailor resumes, generate application messages, and track application history, while leaving final external actions to the user.-
- FlicenseNot gradedqualityAmaintenanceEnables Claude Web users to manage their job application workflow by storing profile and resume data, analyzing job descriptions, preparing applications, and tracking progress — all with manual submission and no platform automation.1-
- AlicenseAqualityCmaintenanceEnables Claude to search public DOU and Djinni job postings concurrently, score each result against a stored profile with explainable skill, role and seniority matching, and track applications through a SQLite-backed pipeline. Also supports saving jobs, updating statuses, and generating tailored cover letters and talking points.8MIT
- AlicenseNot gradedqualityBmaintenanceExposes the entire job-search workflow as 13 chat-driven tools, letting users refresh a ranked feed of live postings from employers' public hiring APIs, view and score job descriptions, tailor and render truthful one-page LaTeX resumes, review skill gaps and screening answers, and log applications. It keeps a human in the loop, since nothing is ever submitted automatically.MIT