Skip to main content
Glama
mcpforwork
by avivancos

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.db

Add 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-imports

License

Apache-2.0

Available Tools

41 tools
abandon_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

    B3.2/5.0

    Scored across 41 tools

    Disambiguation4/5

    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.

    Naming Consistency4/5

    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.

    Tool Count2/5

    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.

    Completeness4/5

    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

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A 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 npm
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      An 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.
      83
      20 npm
      1
      AGPL 3.0
    • A
      license
      Not graded
      quality
      C
      maintenance
      An 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