Job Application MCP
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 Application MCPAnalyze this job description and tailor my resume for it"
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 Application MCP
A remote MCP server that turns an AI assistant into a structured job-application workspace. It manages your profile, resumes, job analysis, application tracking, and interview history, with Claude Web as the primary documented client.
The project is designed as a serious, extensible platform rather than a one-off personal script. The core repository is source-available for learning and contribution, while commercial use, hosted use, and use inside paid products require a separate commercial license. See LICENSE.
It does not scrape or automate any job platform — job descriptions are supplied by the user (pasted or typed), and the final submission is always done by the user, manually.
v1.0.0: the core server is implemented and deployed to Azure Container Apps with 21 MCP tools, Streamable HTTP, OAuth 2.1 resource-server authentication, Docker, GitHub Actions CI/CD, and Auth0 integration. The public deployment is configured for Claude Web custom connectors.
Table of contents
Related MCP server: resume-tailor-mcp-server
Why no scraping or automation
Platforms like LinkedIn explicitly prohibit automated scraping and bot-driven activity in their Terms of Service, and have pursued account suspensions and legal action over it. This project deliberately stays on the right side of that line: it only ever works from information you provide directly (pasted job descriptions, uploaded resumes), and it never logs into, scrapes, or automates form submission on a third-party site. You stay in control of every application you actually send.
Features
Profile management — one structured profile (education, skills, projects, experience, research interests, certifications, achievements) that every other tool reads from. Nothing about you is hard-coded into the source.
Resume/CV management — upload multiple resumes (PDF, DOCX, TXT, MD), keep multiple versions of each, and get a transparent, keyword-based recommendation for which resume fits a given job description.
Job tracking — save jobs with full description/requirements text, automatic duplicate detection (by URL, then by company+title), and a status workflow (
saved → analyzing → ready_to_apply → applied → screening → interview → offer, withrejected/withdrawnreachable from most states).Transparent job analysis — literal keyword comparison between a job's text and your stored skills. No fabricated "hireability score" — matches and gaps are reported plainly so you can judge fit yourself.
Application tracking — persistent records per job, full event history, and duplicate-application prevention. Nothing is ever marked
appliedexcept in response to you telling Claude you submitted it — the tools never submit anything themselves.Interview tracking — scheduled interviews, prep/post-interview notes, linked to the application they belong to.
Architecture
The system is split into transport/authentication, MCP tools, business services, persistence, and external identity infrastructure so new clients and features can be added without rewriting the core domain logic.
flowchart TB
CLIENT["AI Client<br/>Claude Web / MCP Client"]
CLIENT -->|"Streamable HTTP + OAuth 2.1"| SERVER["Remote MCP Server<br/>Starlette + MCP SDK"]
SERVER --> AUTH["OAuth 2.1 Resource Server<br/>JWT/JWKS validation"]
AUTH --> AUTH0["Auth0"]
SERVER --> TOOLS["MCP Tool Layer<br/>21 tools"]
TOOLS --> SERVICES["Application Services"]
SERVICES --> PROFILE["Profile Service"]
SERVICES --> RESUME["Resume / CV Service"]
SERVICES --> JOB["Job Service<br/>duplicate detection + analysis"]
SERVICES --> APP["Application Service<br/>pipeline + event history"]
SERVICES --> INTERVIEW["Interview Service"]
PROFILE --> DB["SQLAlchemy Async"]
RESUME --> DB
JOB --> DB
APP --> DB
INTERVIEW --> DB
DB --> SQLITE["SQLite<br/>development"]
DB --> POSTGRES["PostgreSQL<br/>production"]
SERVER --> FILES["Resume File Storage"]Design principles
AI-client agnostic: MCP is the interface; Claude Web is the first documented client, not a hard dependency of the domain layer.
User-controlled applications: the server prepares and tracks applications but never submits them to third-party job platforms.
Transparent analysis: current job/resume matching is deliberately inspectable keyword-based logic rather than an opaque hiring score.
Authentication at the edge: OAuth 2.1 protects the remote MCP endpoint while application services remain focused on business logic.
Extensible domain services: contributors can add deeper AI analysis, cover-letter generation, integrations, migrations, durable storage, and other capabilities without replacing the existing architecture.
MCP tools
Domain | Tools |
Profile |
|
Resume |
|
Job |
|
Application |
|
Interview |
|
Every tool's description is explicit about what it does and doesn't do. For example: job_create states it never fetches or scrapes a URL itself — the job description must come from you; application_update_status states that moving an application to applied only records what you report, it never submits anything on your behalf; destructive tools (resume_delete, application_delete) require an explicit confirm=true flag.
Tech stack
Python 3.12+, official
mcpSDK v2.x (MCPServer, Streamable HTTP transport)Starlette for the ASGI app, Pydantic for validation, SQLAlchemy (async) + Alembic for the database
SQLite in development, PostgreSQL in production — swap by changing
DATABASE_URLonly, no code changespypdf / python-docx for resume text extraction
Docker for packaging; pytest + ruff for tests and linting
Project structure
job-application-mcp/
├── src/job_application_mcp/
│ ├── server.py # ASGI app: health/ready routes, OAuth auth, uvicorn entrypoint
│ ├── mcp_app.py # shared MCPServer instance
│ ├── config/settings.py # env-driven configuration
│ ├── database/ # SQLAlchemy engine/session + models
│ ├── models/ # Pydantic schemas at the MCP tool boundary
│ ├── services/ # business logic (profile, resume, job, application, interview)
│ ├── mcp/tools/ # MCP tool definitions, one module per domain
│ └── utils/ # document text extraction, upload validation
├── tests/unit/ # service-layer unit tests
├── Dockerfile, docker-compose.yml
├── pyproject.toml
└── .env.exampleGetting started
Requires Python 3.12+.
git clone https://github.com/Mzaq1559/job-application-mcp.git
cd job-application-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
# edit .env: at minimum, set MCP_AUTH_TOKENS to a random secret
python -c "import secrets; print(secrets.token_urlsafe(32))"
# For local development, configure the OAuth variables in .env
python -m job_application_mcp.serverThe server starts on http://0.0.0.0:8000 by default. Check it's alive:
curl http://localhost:8000/health
# {"status": "ok"}Environment variables
See .env.example for the full, current list. The essentials for the deployed OAuth configuration are:
Variable | Purpose | Default |
| SQLAlchemy async connection string |
|
| Auth0 issuer URL | (required) |
| Auth0 API Identifier / JWT audience | (required) |
| Exact public | (required) |
| Optional Auth0 JWKS URL | derived from issuer |
| Scope required on MCP access tokens |
|
| Bind address |
|
| Where resume files are stored on disk |
|
| Reserved for the AI-assisted analysis layer (not yet implemented) | — |
Database
Development uses SQLite and creates tables automatically on server startup — nothing to run manually. Production should point DATABASE_URL at PostgreSQL; Alembic migrations for that path are on the roadmap but not yet implemented (the auto-create-on-startup behavior works against Postgres too in the meantime).
Running tests
pip install -e ".[dev]"
pytest -q # 16 tests, run against an isolated per-test SQLite database
ruff check . # lintDocker
docker compose up --buildThis starts the app plus a PostgreSQL container. The compose file is intended for local development; configure the OAuth variables in your local .env when testing authenticated MCP requests.
To build and run standalone (SQLite, no Postgres container):
docker build -t job-application-mcp .
docker run -p 8000:8000 job-application-mcpDeployment
Any platform that runs a long-lived container works — the server just needs a public HTTPS URL and a couple of environment variables. Options that fit a personal, single-user deployment like this one:
Render or Railway — connect the GitHub repo, they build the
Dockerfileautomatically, set env vars in their dashboard, get a public HTTPS URL.Azure Container Apps — a good fit if you have Azure for Students credit; deploy the same
Dockerfileviaaz containerapp upor the portal's "deploy from GitHub" flow.Fly.io —
fly launchagainst this repo'sDockerfile.
For the current Azure deployment, configure the OAuth environment variables shown above. Do not add an Auth0 client secret to the repository or GitHub Actions. Azure stores deployment configuration separately from source control.
The production deployment currently runs on Azure Container Apps. GitHub Actions builds the Docker image, pushes it to Azure Container Registry, updates the Container App to the exact Git SHA image, and verifies /health after deployment.
Connecting to Claude Web
Once deployed, add it in Claude Web as a custom remote MCP connector, pointing at the public /mcp endpoint:
https://<your-deployed-domain>/mcpAuthentication is OAuth 2.1 through Auth0; Claude signs in through the OAuth authorization flow rather than receiving a shared bearer secret. The Auth0 API requires the mcp:access scope. The Claude Web application uses the callback https://claude.ai/api/mcp/auth_callback. See docs/claude-web.md for the setup details.
Example prompts
Once connected, things like:
"Here's a job description I found — [paste text]. Save it and tell me how well I match it."
"Which of my resumes fits this job best?"
"I just submitted the ML intern application at Example Co — mark it as applied."
"What applications do I have in the interview stage?"
Security
The
/mcpendpoint is protected by OAuth 2.1 bearer access tokens issued by Auth0. JWT signatures, issuer, audience, expiry, and required scope are verified before MCP requests are served.No secrets,
.envfiles, or database files are committed — see.gitignore/.dockerignore.File uploads are validated by extension and size, and filenames are checked for path traversal before being written to disk.
The Docker image runs as a non-root user.
This is a single-user server by design — see Limitations for what that means for auth.
Limitations
Personal deployment. Authentication is delegated to one Auth0 tenant and the MCP tools operate on the database attached to this deployment. Add application-level authorization rules before turning this into a multi-user service.
No AI-assisted analysis yet. Resume selection and job analysis are transparent keyword-matching heuristics, not LLM-based reasoning — by design, so there's nothing to audit for fabrication yet. A proper AI-assisted layer (with explicit no-fabrication prompt rules) is on the roadmap.
No migrations yet. Schema changes currently mean dropping and recreating tables in development; Alembic migrations for safe production upgrades aren't wired up yet.
Never submits anything. By design, not a bug — this project prepares and tracks applications; you always click submit yourself.
Roadmap
Repo scaffold, license,
.gitignore,pyproject.tomlSettings (env-driven config)
Database models (Profile, Resume, ResumeVersion, Job, Application, ApplicationDocument, ScreeningQuestion, Interview, InterviewNote, ApplicationEvent)
Service layer (profile, resume, job, application, interview)
MCP server + tools, verified end-to-end over HTTP (health check, bearer auth,
initialize,tools/list)Unit tests (16 passing) + clean
rufflintDocker + docker-compose, verified with a production-equivalent install and boot
CI/CD (GitHub Actions for lint + tests + Docker build/push + Azure deployment)
Public Azure Container Apps deployment
Alembic migrations
AI provider abstraction + prompts (no-fabrication rules) for deeper job analysis and cover-letter generation
Integration tests against the running HTTP server
Azure Container Apps deployment documentation
Public Azure deployment
OAuth 2.1 resource-server authentication for Claude Web
Durable resume-file storage
Contributing
Community development happens on the community branch. Contributors should fork the repository, create a focused branch from community, and open pull requests back into community. The main branch is reserved for reviewed, release-ready changes.
Before contributing, read:
CONTRIBUTING.md — development workflow, coding guidelines, and PR checklist
CODE_OF_CONDUCT.md — community standards
SECURITY.md — vulnerability reporting
Contributions are especially useful around the AI-assisted analysis layer, Alembic migrations, integrations, durable storage, testing, observability, authentication/authorization, multi-user support, and deployment.
If you want to build on this project commercially, host it for customers, or include it in a paid product, contact the maintainer for commercial licensing.
This started as a personal project, but issues and PRs are welcome. Contributions are especially useful around the AI-assisted analysis layer, Alembic migrations, integrations, durable storage, testing, observability, and additional ATS-adjacent tooling that does not involve scraping or unauthorized automation.
If you want to build on this project commercially, host it for customers, or include it in a paid product, contact the maintainer for commercial licensing.
License
This project is source-available, not open-source under an OSI-approved license. Personal evaluation, learning, and non-commercial contribution are permitted under the project license. Commercial use, hosted/SaaS use, and inclusion in paid products require a separate commercial license.
See LICENSE for the full terms.
This server cannot be deployed
Maintenance
Related MCP Connectors
Manage job applications — jobs, companies, boards, notes, and profile — from your AI client.
Analyze job listings against your resume, track applications, and generate cover letters.
AI job search MCP — fact-checked jobs, application tracker, alerts. ChatGPT, Claude, Cursor.
Career assistant: resumes, job-match analysis, interview results and career memory.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables users to search for jobs, prefill applications using AI, and automate submissions across major platforms like Lever and Ashby directly from Claude or Cursor. It provides a full suite of tools for managing job queues, profile data, and resumes within a chat interface.37MIT
- FlicenseNot gradedqualityCmaintenanceHelps job seekers tailor their resume and generate cover letters against a specific job posting, powered by Claude.-
- FlicenseNot gradedqualityCmaintenanceEnables Claude to parse CVs, search job boards (Remotive, Arbeitnow, Adzuna, Greenhouse/Lever), tailor resumes and cover letters, and prepare application packages with direct apply links—without ever auto-submitting. It runs 100% locally and free, storing jobs and applications as JSON files.-
- FlicenseAqualityBmaintenanceEnables managing a job search through natural language: tracking applications, discovery leads, interview prep, and resume generation. Connects to Claude via MCP to read and update local Excel files and documents.35-