Skip to main content
Glama
firyomaefx

Job Application MCP

by firyomaefx

Job Application MCP

A local-first, open-source job application assistant built on the Model Context Protocol.

Analyse jobs · Match against your CV · Tailor documents · Preview forms · Track applications — all on your machine, nothing uploaded, submission stays in your hands.

License: AGPL-3.0-or-later Node TypeScript Status: Alpha


Table of contents


Why

Job hunting is repetitive: read a posting, check it against your CV, tweak a cover letter, fill the same fields on yet another form, and remember where you applied.

Job Application MCP turns that into a set of tools any MCP-compatible AI client (Claude Desktop, Claude Code, others) can drive for you — while keeping you in control:

  • Your CV and applications never leave your machine in the free core.

  • The assistant prepares and previews; you review and submit.

  • It's open source under AGPL-3.0, so you can audit exactly what it does.

ℹ️ This repository is the free community core described in BUSINESS_PROPOSAL.md. Paid AI/cloud/business services are intentionally out of scope here.


What it does (free core)

Capability

Description

🧩 Local MCP server

A stdio server you connect from any MCP client.

👤 Candidate profile

One local profile: skills, headline, contact, summary.

📄 CV parsing

Parse PDF / DOCX / TXT locally — no upload, no network.

🔍 Job analysis

Paste a job description; get extracted key skills + a short summary.

🎯 Match scoring

Heuristic 0–100 score with matched / missing skills.

✂️ Tailoring suggestions

Structural advice on which skills to surface or add.

✍️ Answer drafting

A template starter for screening questions (you rewrite it).

📝 Form autofill preview

Maps your profile onto form fields — preview only, never submits.

📊 Application tracking

Local SQLite store with a status pipeline (draft → submitted → offer…).

What it deliberately does NOT do

  • No automated submission. You submit manually on the employer's site.

  • No automation of LinkedIn or Indeed — their Terms of Service prohibit it. Paste the description and complete those by hand.

  • No CAPTCHA solving, 2FA bypass, or login recovery — it pauses for manual action.

  • No AI rewriting, cloud sync, or premium adapters — those are future Pro/cloud services.

These aren't missing features; they're the design.


How it works

┌─────────────────┐      stdio (JSON-RPC)      ┌──────────────────────┐
│  MCP client     │  ◀────────────────────────▶│  job-application-mcp │
│  (Claude, etc.) │                             │  (this server)       │
└─────────────────┘                             └──────────┬───────────┘
                                                           │ reads / writes
                                                           ▼
                                                ┌──────────────────────┐
                                                │  local SQLite DB     │
                                                │  + parsed CV text    │
                                                │  (JOB_MCP_DATA_DIR)  │
                                                └──────────────────────┘

You (or an AI client) call tools. Each tool does a small, auditable thing and returns structured JSON. Tools that touch external sites do not exist; everything operates on data you provide and store locally.


Quick start

Requirements

  • Node.js ≥ 22 (uses the built-in node:sqlite — no native compilation needed)

  • npm

Install & build

git clone https://github.com/<your-user>/job-application-mcp.git
cd job-application-mcp
npm install
npm run build      # -> dist/

Verify it works

npm test           # 40 unit tests (scoring, store, licence, credits, ai, payments, audit-fixes)
node dist/cli/cli.js --help

Connect an MCP client

Build the project, then add the server to your MCP client's config.

Claude Desktop / Claude Code

{
  "mcpServers": {
    "job-application-mcp": {
      "command": "node",
      "args": ["/ABSOLUTE/path/to/job-application-mcp/dist/src/index.js"]
    }
  }
}

⚠️ Use an absolute path — MCP clients launch the server from their own working directory, not yours.

Run directly (no client)

node dist/cli/cli.js serve      # equivalent to: node dist/src/index.js

The server speaks JSON-RPC over stdio. See A full example flow for raw request examples.


Tools reference

All 23 tools are local and synchronous-ish (CV parsing and AI calls are async). Arguments are validated with zod; the MCP client receives a JSON Schema for each. The 13 free-core tools (profile → autofill) are the everyday workflow. The credits/Pro and admin/business tools are wire-ready seams for the hosted Pro service (see Business model); they run locally today and do not require any subscription.

Profile

Tool

Args

Returns

get_profile

The local candidate profile (auto-created on first call).

update_profile

full_name?, email?, phone?, location?, headline?, summary?, skills?, experience_years?

Updated profile. skills replaces the list.

CVs

Tool

Args

Returns

parse_cv

file_path? or text, label?

Parsed CV stored locally; detected skills + a short preview.

list_cvs

All stored CVs.

parse_cv supports .pdf (pdf-parse), .docx (mammoth), and plain text. If you pass text, it's stored as-is. file_path must be inside the data dir (or a folder listed in JOB_MCP_CV_DIRS) — paths outside the allow-list are rejected, so an MCP client can't read arbitrary files.

Jobs

Tool

Args

Returns

analyze_job

description (≥20 chars), title?, company?, url?, store?=true

Extracted keywords + summary; stored as a job (unless store: false).

get_job

job_id

A stored job with its keywords.

Matching & prep

Tool

Args

Returns

match_cv

job_id, cv_id, save?=false

0–100 score, matched/missing/extra skills; optionally creates a draft application.

tailor_cv

job_id, cv_id

Tailored CV draft. With your own AI API key (AI_API_KEY): AI-rewritten prose; without: heuristic local draft.

cover_letter

job_id, cv_id

Cover-letter draft (AI with your own key, else heuristic).

draft_answer

question, cv_id?, job_id?

Screening-answer draft (AI with your own key, else heuristic template). Always review.

AI tools and your own key. tailor_cv, cover_letter, and draft_answer use a real AI provider when you set AI_PROVIDER (openai or anthropic) and AI_API_KEY — on the Free or Pro plan. Without a key they fall back to a local heuristic. The Pro hosted path additionally debits an AI credit; using your own key is never debited. See Business model.

Applications & forms

Tool

Args

Returns

save_application

job_id, cv_id?, match_score?, tailored_cv_text?, cover_letter?, answers?, notes?

A draft application record. Does not submit.

list_applications

status?

Application records (optionally filtered by status).

update_application_status

application_id, status, notes?

Updates status; sets submitted_at when status is submitted.

autofill_form

application_id, form_fields?

A preview mapping of profile data onto form fields. Nothing is submitted.

Status pipeline: draft → ready → submitted → interview → offer → rejected → closed.

Analytics & status

Tool

Args

Returns

application_analytics

Counts by status, average match score, recent activity. Pro entitlement adds an advanced breakdown.

status

Server/plan/credits snapshot (plan label, AI credit balance, active features).

Credits & Pro (wire-ready seams)

Tool

Args

Returns

credits

Current AI credit balance + recent ledger entries.

topup_credits

code, amount

Apply an AI-credit top-up code (idempotent per code). Admin/test.

grant_monthly_credits

amount?

Grant the monthly AI allowance (idempotent per calendar month). Admin/test.

Admin / business (wire-ready seams)

Tool

Args

Returns

admin_create_account

email, name, plan?

Create a business account.

admin_add_candidate

account_id, profile_id, role?

Add a candidate/coach to an account.

admin_list_team

account_id

List an account's team members.

admin_usage_report

account_id

Usage summary for an account.


A full example flow

Here's a complete session using the stdio JSON-RPC interface directly. (An MCP client like Claude does this for you in natural language.)

node dist/src/index.js

Send these lines (one JSON-RPC object per line):

// 1. handshake
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"demo","version":"0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}

// 2. set up your profile
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"update_profile","arguments":{"full_name":"Ada Lovelace","headline":"Backend Engineer","skills":["python","sql","aws","docker"]}}}

// 3. analyse + store a job (paste the description text)
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"analyze_job","arguments":{"title":"Backend Engineer","company":"Acme Co","description":"We need a backend engineer with Python, SQL, and AWS to build data pipelines. PostgreSQL and Docker are a plus."}}}

// 4. parse a CV (file path or pasted text)
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"parse_cv","arguments":{"label":"main-cv","text":"Ada Lovelace — Backend Engineer. Python, SQL, AWS, PostgreSQL. Built ETL pipelines..."}}}

// 5. score the CV against the job (save=true creates a draft application)
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"match_cv","arguments":{"job_id":1,"cv_id":1,"save":true}}}

// 6. preview autofill for a form (no submission)
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"autofill_form","arguments":{"application_id":1,"form_fields":[{"name":"name","label":"Full name"},{"name":"email","label":"Email"},{"name":"salary","label":"Salary expectation"}]}}}

// 7. after you submit on the employer's site, mark it submitted
{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"update_application_status","arguments":{"application_id":1,"status":"submitted"}}}

Step 6 returns a mapping where the salary field is flagged requires_user_review: true — sensitive fields always need your eyes.


Configuration

All config is via environment variables. The free core needs none of them.

Variable

Default

Purpose

JOB_MCP_DATA_DIR

./data

Where the SQLite DB and parsed data live.

JOB_MCP_CV_DIRS

Extra folders parse_cv may read from (OS path separator: ; on Windows, : elsewhere).

JOB_MCP_HTTP_PORT

8787

Port for the local HTTP bridge (loopback only).

JOB_MCP_HTTP_TOKEN

Optional bearer token the bridge requires on /call.

The following enable your own AI key (works on Free or Pro) and are placeholders for future hosted Pro/cloud services (see .env.example):

Variable

Purpose

AI_PROVIDER / AI_API_KEY

openai or anthropic + your own key → real AI drafts for tailor_cv / cover_letter / draft_answer. Free users use this without any subscription.

AI_MODEL / AI_BASE_URL

Optional model + base URL override (e.g. an OpenAI-compatible endpoint).

JOB_MCP_LICENCE_SERVER

Pro licence activation endpoint (hosted service).

SUPABASE_URL / SUPABASE_ANON_KEY

Cloud sync & auth (Pro, hosted).


Project layout

job-application-mcp/
├── src/
│   ├── index.ts           # stdio MCP server entrypoint
│   ├── http.ts            # local HTTP bridge entrypoint (127.0.0.1)
│   ├── server.ts          # server factory + tool registry
│   ├── tools/             # one file per MCP tool (23 total)
│   │   ├── types.ts       # ToolDef / AnyTool / result helpers
│   │   ├── profile.ts     # get/update_profile
│   │   ├── cv.ts          # parse_cv, list_cvs
│   │   ├── job.ts         # analyze_job, get_job
│   │   ├── matching.ts    # match_cv, tailor_cv, cover_letter, draft_answer
│   │   ├── application.ts # save/list/update_application, autofill_form
│   │   ├── analytics.ts   # application_analytics, status
│   │   ├── pro.ts         # credits, topup_credits, grant_monthly_credits
│   │   └── admin.ts       # admin_create_account / add_candidate / list_team / usage_report
│   ├── store/             # SQLite layer (node:sqlite)
│   │   ├── db.ts          # open / migrate / close / reset
│   │   ├── profile.ts     # profile CRUD
│   │   └── applications.ts# cv / job / application CRUD
│   ├── cv/parser.ts       # PDF / DOCX / TXT parsing (path allow-listed)
│   ├── ai/                # provider abstraction (mock / openai / anthropic)
│   ├── licence/           # entitlement tokens + credits + referrals
│   ├── payments/          # payment-webhook seam (server-side, not in clients)
│   ├── sync/              # cloud-sync seam (local no-op until Pro)
│   ├── features.ts        # feature gating (plan + credits + AI mode)
│   └── lib/
│       ├── types.ts       # domain types
│       ├── crypto.ts      # HMAC-SHA256 + constant-time compare
│       ├── entitlement.ts # Entitlement value type + plan limits
│       └── scoring.ts     # keyword extraction + match scoring (pure)
├── cli/cli.ts             # human CLI: job-mcp serve | serve:http | --help
├── extension/             # Chrome MV3 extension (form capture → preview)
├── desktop/               # Electron wrapper UI (launches the bridge)
├── .github/workflows/ci.yml  # build + typecheck + test + stdio smoke
├── tests/                 # node:test suite
├── BUSINESS_PROPOSAL.md   # open-core + paid-service model
├── CLAUDE.md              # guide for Claude Code working in this repo
└── LICENSE                # AGPL-3.0-or-later

Companion apps

The free core is the stdio MCP server above. Two optional companions live in this repo and talk to a local HTTP bridge (same tools, loopback only):

HTTP bridge

npm run serve:http      # 127.0.0.1:8787 by default

Endpoints: GET /health, POST /call with {"name","arguments"}. Optional bearer auth via JOB_MCP_HTTP_TOKEN. Source: src/http.ts.

Chrome extension — extension/

Captures form fields on a career page and asks the bridge to preview an autofill mapping. Never submits. Load it unpacked from extension/. See extension/README.md.

Desktop app — desktop/

An Electron wrapper that launches the bridge and shows a dashboard (status, profile, applications). Run with cd desktop && npm install && npm start. See desktop/README.md.

Both companions are read/preview only and reach only 127.0.0.1. They inherit the project's no-submission, no-LinkedIn/Indeed-automation rules.


Develop

npm run build       # tsc -> dist/
npm run typecheck   # tsc --noEmit
npm test            # node --test (scoring + store)
npm run dev         # tsc --watch

Adding a tool

  1. Create src/tools/<name>.ts exporting a ToolDef<z.ZodObject<…>>.

  2. Register it in src/tools/index.ts (add to the tools array).

  3. Add a test in tests/ if it has pure logic worth covering.

Tools receive parsed, typed input and return a ToolResult ({ summary, data?, notes? }). The server handles JSON Schema generation, validation, and error wrapping for you.


How matching works

Matching is a pure, heuristic function in src/lib/scoring.ts — no AI, no network.

  1. Extract keywords from the job description: tokenize, drop stopwords and filler verbs, weight tech hints and frequent terms.

  2. Score: for each job keyword, check the candidate's curated profile skills plus skills detected in the CV text. Stem-ish matches count (e.g. reactreactjs).

  3. Result: score (0–100), matched, missing, extra, and notes (e.g. "Below 50% — consider tailoring or skipping").

Formula: score = matched/total × 100 plus a small, capped breadth bonus for extra skills (only when there are job keywords). It's intentionally simple and auditable — a baseline you can replace with the Pro AI scorer later.


Privacy & data

  • Local-first. CVs, profile, and applications live in JOB_MCP_DATA_DIR (default ./data), which is gitignored. The free core makes no network calls.

  • No PII in logs. CV text and personal fields aren't logged at info level.

  • Sensitive fields are flagged. autofill_form marks salary, authorization, gender, disability, and consent fields as requires_user_review: true.

  • You can wipe everything by deleting the data directory.


Roadmap / Pro upgrade

The free core is the foundation. BUSINESS_PROPOSAL.md describes the open-core model. Likely next steps:

  • Free core: match_cv + tailor_cv integration test through the MCP layer; richer keyword extraction (skill taxonomy).

  • Distribution: Windows installer via GitHub Releases; Chrome Web Store extension for form-field capture.

  • Pro (separate hosted services): AI CV tailoring & cover letters, encrypted cloud backup, multi-device sync, maintained site adapters, application analytics.

  • Business: multi-candidate accounts, team dashboards, white-label.

Tool handlers are written so a Pro upgrade can slot in without changing the public tool surface — e.g. tailor_cv returns heuristic suggestions today and could call an AI service tomorrow.


Limitations

  • Keyword extraction is heuristic and will miss or mis-rank some skills. Confirm against the source posting before relying on a match score.

  • No browser automation. Form fields must be supplied to autofill_form (manually or, later, via the extension). The tool previews; it doesn't fill.

  • LinkedIn / Indeed: analysis-only, paste the description, submit manually.

  • Alpha status: APIs and stored schemas may change before 1.0.


License

Copyright © 2026 Job Application MCP contributors.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See LICENSE.

A separate commercial licence is available for embedding without AGPL obligations — see BUSINESS_PROPOSAL.md §8.


Contributing

Issues and PRs welcome. By contributing you agree your contributions will be licensed under the same AGPL-3.0-or-later terms.

Please keep the free core fully local and free — no feature in this repo may gate a free-core capability behind a paid/network service. See CLAUDE.md for the conventions used in this codebase.

-
license - not tested
-
quality - not tested
-
maintenance - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/firyomaefx/job-application-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server