mcpforwork
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., "@mcpforwork start a job hunt for remote data analyst positions"
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.
mcpfor.work
Open-source, MCP-first job-search copilot — any sector, any country. Self-hostable for free; hosted at a flat $5/mo.
Status: pre-alpha. Self-host works end-to-end (profile → hunt → briefs → supervised apply); hosted is not launched yet.
Quickstart (self-host, zero account)
uvx --from mcpforwork mcpforwork init # creates ~/.mcpforwork/mcpforwork.dbAdd the connector to Claude Code / Desktop (.mcp.json):
{ "mcpServers": { "mcpforwork": { "command": "uvx",
"args": ["--from", "mcpforwork", "mcpforwork-mcp"] } } }Then, in your client: /setup (build your profile, < 3 min) → /hunt
(browser-verified job-portal searches; UK, Spain, US, DE + remote boards) →
/review → /apply (honest drafts + coverage check; you click Submit —
the copilot never auto-submits). Zero server-side LLM calls, ever.
Related MCP server: jobkit-mcp
What makes it different
The LLM is the client. All intelligence runs inside your own Claude or ChatGPT/Codex subscription connected to this MCP server. We never make server-side LLM calls, so the hosted plan is infrastructure, not token resale.
Graduated autonomy, consent-based. Default is supervised: the copilot prepares, you review and submit. Autopilot is explicit opt-in, policy-governed, and only ever runs in your own browser session.
Open-core. The full product self-hosts on SQLite with no account. Hosted adds convenience: remote MCP connector, web dashboard, sync, backups.
Never fabricate. Generation briefs carry a facts inventory — drafts may only claim what your profile proves.
Sector- and country-agnostic by data. Job-site knowledge ships as versioned, community-contributable packs, not code releases.
You own your data. Export and delete built in.
Architecture
Pragmatic hexagonal (ports & adapters) over a modular monolith. The full product specification lives in docs/PRODUCT_PLAN.md; contributor rules in AGENTS.md.
Development
uv sync
uv run pytest
uv run ruff format --check . && uv run ruff check .
uv run lint-importsLicense
Apache-2.0
Available Tools
41 toolsabandon_applicationA
Close an application you decided not to pursue (any open state). A later start_application for the same match opens a fresh session.
Inputs: application_id (required), reason. Returns: result
add_achievementsB
Append quantified wins (each needs a metric) to the achievements bank.
Inputs: items (required), profile_id. Returns: result
approve_matchB
Approve a match (human decision) so materials/apply can proceed.
Inputs: finding_id (required). Returns: result
ats_coverage_checkB
Deterministic check of the posting's keywords vs a stored draft: covered / missing_but_have (truthfully addable) / genuine_gaps (acknowledge, never stuff).
Inputs: asset_id (required), finding_id (required). Returns: result
autopilot_queueA
The L2 work queue: approved matches on auto_apply_safe boards scoring at/above the policy min, not dedup-blocked, with no open application. Empty when autopilot is off or no board is flagged safe. Read-only.
Inputs: no named parameters. Returns: result
check_seenA
Report which URLs the copilot already knows (scouted or applied). Only browse/apply the ones marked 'new'.
Inputs: urls (required). Returns: result
confirm_submittedB
AFTER the human confirms they clicked Submit: close the loop (state, dedup record, audit).
Inputs: application_id (required), evidence. Returns: result
create_profileA
Create a new profile (made active) and return it. patch is the intake
fields (name, titles, sectors, work mode, …).
Inputs: label, patch. Returns: result
delete_my_dataA
GDPR erasure, two-step (S7.2d): called WITHOUT a token, returns a per-table summary of what would be deleted plus a single-use confirm_token (valid 5 minutes) — show both to the human. Called WITH that token, permanently deletes ALL their data (every table + the account row). IRREVERSIBLE. The token is the consent artifact: never invent one — only the human can read it back to you. Consider export_my_data first.
Inputs: confirm_token. Returns: result
discard_matchA
Discard a match (human decision); it will never be re-surfaced.
Inputs: finding_id (required), reason. Returns: result
export_my_dataA
GDPR data portability: everything stored about you (profile, findings, applications, assets, audit trail) as one JSON object. Read-only.
Inputs: no named parameters. Returns: result
get_asset_fileC
A local file path for the asset (for form uploads).
Inputs: asset_id (required). Returns: result
get_assetsC
The stored drafts for a match, newest version first.
Inputs: finding_id (required), asset_type. Returns: result
get_autopilot_policyA
The active autopilot (L2) policy: min_score, max_per_day, since when. null policy = autopilot off, every submit awaits the human. Policies are written ONLY from the dashboard (human session) — never here.
Inputs: no named parameters. Returns: result
get_generation_briefB
The structured brief (job keywords + facts inventory + style + honesty rules) YOU draft the cv/cover_letter from. Only claim what the facts_inventory proves.
Inputs: asset_type (required), finding_id (required). Returns: result
get_matchB
Inspect one scouted match by id.
Inputs: finding_id (required). Returns: result
get_profileA
Return the active profile (or a given one), JSON fields parsed.
Inputs: profile_id. Returns: result
hunt_planA
Per-source search playbooks for the active profile — the URLs YOU open in the user's browser to find postings.
Inputs: no named parameters. Returns: result
import_from_url_findingsA
Apply client-LLM-extracted structured fields (LinkedIn/GitHub/portfolio) to the active profile, recording the source url for provenance. Call ONLY after preview_url_import + human CONFIRM — this tool writes.
Inputs: url (required), fields (required). Returns: result
list_matchesC
The scouted matches, best score first.
Inputs: limit, status, min_score. Returns: result
list_profilesA
List the user's profiles (the active one has is_active=1).
Inputs: no named parameters. Returns: result
list_sourcesA
List enabled sources, optionally filtered by country/sector tags. Pack data only — no DB.
Inputs: sectors, countries. Returns: result
parse_cvA
Zero-LLM regex extraction of contact fields from pasted CV text. Returns candidate fields (None = unknown — ask the human, never invent). Does NOT write the profile: CONFIRM with the human, then call update_profile.
Inputs: cv_text (required). Returns: result
pipeline_statsA
Pipeline counts for a status summary: new matches, awaiting the human, submitted/verified, responses. The same read the dashboard shows.
Inputs: no named parameters. Returns: result
preview_url_importA
Read-only LinkedIn/GitHub/portfolio import preview (S5.4).
YOU open the URL in the user's browser and paste the visible page text.
The server never fetches. Returns the same contact + setup_hints shape as
parse_cv plus source_url. Does NOT write — CONFIRM with the human, then
import_from_url_findings(url, confirmed_fields).Inputs: url (required), page_text (required). Returns: result
profile_gapsA
What the profile is still missing (required first, then progressive). Offer ONE gap at a time when contextually useful — never a form-wall.
Inputs: no named parameters. Returns: result
record_applicationA
Record that the HUMAN submitted an application (any channel) so the copilot never re-surfaces the posting. Idempotent per URL.
Inputs: url (required), notes, method, channel. Returns: result
record_outcomeB
Record what happened (no_reply|rejected|interview|offer|hired) — feeds calibration.
Inputs: outcome (required), application_id (required), notes. Returns: result
report_apply_progressA
Report a step's outcome (ok | blocked | mismatch). The server answers with the next step, a repair, or a human-pause — never a submit.
Inputs: status (required), step_id (required), application_id (required), observed, +1 more. Returns: result
report_playbook_resultB
Opt-in crowd-learning: report what worked/moved/broke on a source (kind: success | drift | break) to improve the next pack version.
Inputs: kind (required), source_slug (required), diff. Returns: result
request_submitB
THE consent gate. Ask permission to move to submission: at consent level 0 the answer is always await_human — show the filled form; the HUMAN clicks Submit.
Inputs: application_id (required), summary. Returns: result
resolve_fieldA
Deterministic answer for an unpredicted form question — from the profile or saved answers; otherwise ask_user (never invent).
Inputs: field_label (required), application_id (required), options, field_type. Returns: result
save_form_answerA
Persist a HUMAN-confirmed screener answer so it is never asked twice.
Inputs: answer (required), field_label (required). Returns: result
server_infoA
Version + capability handshake: server version, registered tools, and the load-bearing invariants the client must respect.
Inputs: no named parameters. Returns: result
set_active_profileC
Switch the active profile.
Inputs: profile_id (required). Returns: result
set_style_profileC
Capture the user's writing voice so drafts sound like them.
Inputs: writing_sample (required), directives, profile_id. Returns: result
source_playbookC
The full search + apply playbook for one source. Pack data only — no DB.
Inputs: slug (required), query. Returns: result
start_applicationA
Start a supervised application session for an APPROVED match: runs the preflight (dedup gate, daily cap) and returns the step plan YOU execute in the user's browser. The plan never contains a submit step — request_submit is the only submission route and the human decides.
Inputs: finding_id (required). Returns: result
submit_assetB
Store YOUR draft (markdown) for a match; versions auto-increment.
Inputs: content (required), asset_type (required), finding_id (required). Returns: result
submit_findingsA
Ingest postings YOU extracted from a source: deduped, scored against the profile, and persisted. Each finding needs at least url + title.
Inputs: findings (required), source_slug (required). Returns: result
update_profileA
Apply a partial update. With no profile_id, updates the active profile — or creates it if the user has none yet (the /setup path).
Inputs: patch (required), profile_id. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 41 tools
Most tools have clearly distinct purposes, but a few pairs like hunt_plan/source_playbook and parse_cv/preview_url_import could be confused without careful reading. However, the detailed descriptions effectively disambiguate them, and the application workflow tools each have specific roles.
The majority of tools follow a verb_noun pattern (e.g., get_profile, create_profile, submit_asset), but some read-only data tools use noun phrases (e.g., pipeline_stats, autopilot_queue, ats_coverage_check, profile_gaps) and a few use less standard verbs (preview, hunt, check, request). Overall, the naming is readable and mostly consistent.
With 41 tools, the surface is very large and exceeds the threshold for 'too many'. The domain is broad, but the granularity exposes many fine-grained workflow steps (e.g., confirm_submitted, record_outcome) that could be grouped into higher-level tools, making the set overwhelming for agents.
The tool surface covers the full lifecycle: profile creation/import, job hunting, match management, drafting, application execution, and GDPR data rights. Minor gaps exist, such as no dedicated tool to get an application's current status and no update/delete for achievements, but core workflows are well covered.
Related MCP Connectors
GetJobzi MCP server for job search, application tracking, and career forecasting.
Public MCP server for discovering open jobs. Search, filter, and get application links.
Job search and interview prep MCP. 15 tools, OAuth 2.1, cross-LLM. four-leaf.ai.
Search 33,000+ MCP servers by job, see safety grades and reviews, and call them from one endpoint.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA job-search MCP server that ranks roles, drafts cover letters, and rehearses Q&A answers using a candidate profile, with live listings from five public sources.66 npmMIT
- AlicenseBqualityDmaintenanceMCP server for managing job application materials, including resume compilation, job posting fetching, and interview preparation.10MIT
- AlicenseCqualityCmaintenanceAn MCP server that enables AI-assisted job search workflows including job discovery, application tracking, resume evaluation, and cover letter generation, with support for multiple job sources and scheduled scraping.8320 npm1AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceAn MCP server that exposes job-search and application-management capabilities to compatible AI clients, enabling discovery of vacancies, drafting of tailored application materials, and coordinated human-approved submissions.MIT