JobApplication
This MCP server exposes a local job-application assistant for Claude.
Search job sites now via
find_jobs, optionally by source and with a wait time.List saved jobs with sorting, search, status, minimum match, and hidden-job filtering via
list_jobs.View full details and keyword match for one job via
job_details.Build a tailored PDF resume for a job, optionally choosing a resume variant, via
build_resume.Update application status (
new,interested,applied,interview,rejected,offer,ignored) viamark_job.Import a Word/PDF resume: prepare the import prompt and submit LaTeX for verification via
import_resume_prepareandimport_resume_submit_tex.Prepare, verify, and generate tailored cover letters in English/Norwegian via
cover_letter_prepareandcover_letter_submit.Run installation/settings diagnostics via
doctor.Update job filters in
config.yaml(titles, companies, locations, languages, job types, max age) viaupdate_config_filters.Start and open the local dashboard via
open_dashboard.
Searches the Simplify GitHub lists for US student job postings, integrating GitHub-hosted job data into the search results.
Provides an optional connector to write one note per job into an Obsidian vault, including job details, status checklists, and dashboard updates. Supports two-way status synchronization and optional git commits/pushes.
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., "@JobApplicationfind new jobs and show me the ones that match my skills best"
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.
JobApplication
Find jobs on the sites you choose, hide the ones you don't want, see how well each one matches your skills, and get a tailored PDF resume for each job — in one click.
Made for people who don't code. You use it by talking to Claude (Claude Code or Claude Desktop); Claude runs the tool, explains things in plain English, and fixes settings for you.
📸 Screenshot of the dashboard goes here (
docs/screenshots/dashboard.png)
What it does
Searches LinkedIn (public job pages, no login), FINN.no (Norway) and the Simplify GitHub lists (US students). The BI Norwegian Business School portal needs a login and is planned for a later version.
Filters by job title words, words to avoid (e.g. "senior"), places, job type, age of the ad, companies and ad language. Hidden jobs are kept with the reason, so nothing disappears silently.
Scores each job: which of your skills the ad mentions, and which skills in the ad you didn't list.
Builds a tailored resume: only the two Skills lines change per job (the ad's matching keywords go first); every other letter of your resume stays exactly as you wrote it. The PDF is named
First_Last_Company_Role.pdf.Writes a tailored cover letter (English or Norwegian): Claude writes the text, the tool checks that every number and name in it comes from your resume or the ad, that it fits on one page and avoids clichés.
Tracks what you did: interested → applied → interview → offer.
Imports your Word or PDF resume into the PDF template. Claude types it; the tool checks every word, link and the page count against your original file.
Runs on your computer only. Your jobs, resume and settings stay in a private folder (
~/JobApplication-data), never in this repository.
Related MCP server: career-agent
Install with Claude (easiest)
Install Claude Code (or use Claude Desktop, see below).
Download this folder (green Code button → Download ZIP, then unzip it, or
git clone).Open Claude Code in that folder and paste this sentence:
Set up JobApplication for me on this computer, step by step, and ask me what jobs I'm looking for.
(or type
/setup). Claude installs what's needed, creates your private folder, asks about the jobs you want, and runs a first check.
Then just ask things like "find new jobs", "make a resume for the DNV one", "I applied to it",
or use the shortcuts /find-jobs, /tailor, /cover-letter, /applied, /import-resume, /report-bug, /update.
Manual install (Mac)
# 1. tools (Homebrew from https://brew.sh first, if you don't have it)
brew install uv tectonic pandoc
# 2. the app (in this folder)
uv sync
# 3. your private folder with example settings and an example resume
uv run jobapp init
# 4. check everything
uv run jobapp doctorLinux works the same (curl -LsSf https://astral.sh/uv/install.sh | sh; TeX Live or tectonic; pandoc).
Everyday use
uv run jobapp poll # search the job sites now
uv run jobapp list --sort match # best matches first
uv run jobapp show <id> # one job in detail
uv run jobapp build <id> --reveal # tailored PDF, shown in Finder
uv run jobapp mark <id> applied # keep track
uv run jobapp serve --background # dashboard in your browser (keeps running; --stop to stop)
uv run jobapp schedule install # search automatically at the times in config.yaml
uv run jobapp connectors sync obsidian # optional: one note per job in Obsidian (see below)
uv run jobapp rescore # after editing keywords.yamlYour settings are in ~/JobApplication-data/config.yaml; after editing run uv run jobapp config validate —
it explains mistakes and suggests the right spelling. Filter words match whole words; add * for
word beginnings/endings (robot* → robotics, *analytiker → Finansanalytiker).
Word or PDF resume import
uv run jobapp resume import ~/Desktop/resume.docx --prepare # or resume.pdf; Claude follows import/prompt.md
uv run jobapp resume import --verify # checks words, links, pages, markers
uv run jobapp resume import --accept # use it (old resume is backed up)With your own API key (uv run jobapp key set ANTHROPIC_API_KEY, stored in the Mac Keychain) the whole
loop runs automatically: uv run jobapp resume import resume.docx --api (or resume.pdf).
A Word file gives the best result (bold/italic are kept); a PDF works too as long as its text can be selected
(not a scan).
Cover letters
uv run jobapp letter <id> --prepare # Claude follows letters/<id>/prompt.md and writes letters/<id>/body.md
uv run jobapp letter <id> --verify # facts, length, one page, banned phrases, keywords, language
uv run jobapp letter <id> --accept # output/First_Last_Company_Role_CoverLetter.pdf + .txt for web formsOr just ask Claude: /cover-letter <id> (or click Cover letter ✉ on a job in the dashboard).
--language no writes a Norwegian søknad; --api runs the loop with your own API key.
Settings live in ~/JobApplication-data/coverletter/: template.tex (layout), style.yaml (language, tone,
word limit, banned phrases like "passionate" or "I am writing to express", sign-off) and samples/ (drop in
your own past letters — used for tone only). Profiles made before this feature: uv run jobapp coverletter init.
Obsidian (optional)
If you keep notes in Obsidian, JobApplication can write one note per job into your
vault — same layout as a hand-made job note: details table, Apply link, a Status checklist and room for your
own notes. It is off until you switch it on in config.yaml:
connectors:
obsidian:
enabled: true
vault: ~/Documents/Obsidian Vault # the folder you opened as a vault in Obsidian
folder: Jobs # notes go in Jobs/Full-Time, Jobs/Internships, Jobs/Part-TimeThen uv run jobapp connectors sync obsidian writes notes for the jobs you already have (--dry-run shows
what it would do first). After that every search adds notes for new jobs and keeps _Dashboard.md and
_New Today.md up to date. Your own writing in a note is never changed — only the status, match and link
fields at the top and the "Applied" tick box. You can rename or move notes; they are found by job_id.
Extras: two_way: true lets you change a job's status in the note (or tick "Applied") and have it show up
here at the next search; git_push: true commits the Jobs folder (and pushes it) if your vault uses git;
min_match: 40 only writes notes for good matches; one_note_per_title: true keeps one note per company + title
(reposts share it). The two generated notes can have other names
(dashboard_file: "_JobApplication Dashboard.md", new_today_file: ...); an existing file at that name that
JobApplication didn't make is never overwritten (doctor says so; connectors sync obsidian --adopt-dashboards
replaces it on purpose).
Several resumes (optional)
Have two versions of your resume (say one for robotics jobs and one for ML jobs)? List them in config.yaml:
resume:
variants:
perception: {tex: resume/perception.tex, keywords: resume/keywords.yaml, prefer_if: [perception, vision, slam, "robot*"]}
mle: {tex: resume/mle.tex, keywords: resume/keywords.yaml, prefer_if: [machine learning, ml, llm]}
default_variant: perceptionEach job uses the resume whose prefer_if words best fit its title (then its description), else the default.
Choose yourself with uv run jobapp build <id> --variant mle (remembered for that job; --variant auto goes
back to automatic) or the "Resume" drop-down on the dashboard. list/show show which one a job uses.
Keyword match
matched = words from your keywords.yaml found in the ad. missing = skills from a built-in vocabulary
(src/jobapp/resume/skills_vocab.yaml: tech, business/analytics, Norwegian equivalents) that the ad mentions
and your list doesn't have — never names, slogans or "About us" text. Add your own terms to it in
keywords.yaml:
extra_vocab:
Foxglove: []
Isaac ROS: [isaac-ros]After editing keywords run uv run jobapp rescore.
Moving from the older jobdesk tracker
uv sync --extra mongo, then uv run jobapp migrate --from-mongo --dry-run (and without --dry-run) copies the
jobs from its Mongo database (read-only; safe to run again). Status, applied date, saved job descriptions, the
resume variant, the date found and each job's existing Obsidian note are kept; the next search recognises the
same LinkedIn/Simplify jobs instead of adding copies. Contacts and messages stay in the old system.
Claude Desktop
JobApplication includes an MCP server, so Claude Desktop can use it too. Print your personal config snippet:
uv run jobapp mcp-configand paste it into ~/Library/Application Support/Claude/claude_desktop_config.json
(Claude Desktop → Settings → Developer → Edit Config), then restart Claude Desktop. It looks like:
{
"mcpServers": {
"jobapplication": {
"command": "<HOME>/.local/bin/uv",
"args": ["--directory", "<HOME>/JobApplication", "run", "jobapp", "mcp"],
"env": { "JOBAPP_HOME": "<HOME>/JobApplication-data" }
}
}
}Tools: find_jobs, list_jobs, job_details, build_resume, mark_job, import_resume_prepare,
import_resume_submit_tex, doctor, update_config_filters.
Something wrong?
uv run jobapp doctor explains each problem with a fix. uv run jobapp report-bug makes a zip of logs and
diagnostics with your name, email, phone numbers and passwords removed — send that to the developer.
uv run jobapp version shows which version you have (mention it when you ask for help).
Being a good citizen
JobApplication is a personal tool, not a crawler: it waits at least 2 seconds between requests to the same
site, slows down when a site asks it to (HTTP 429), uses only public pages, never logs in for you, and follows
the site rules we know about (e.g. FINN.no: no abTestKey, never industry + occupation together, nothing
under /job/salary/). Note that FINN.no's robots.txt asks AI training crawlers to stay away from /job/;
JobApplication doesn't train anything, but if you want to be extra careful, leave the FINN source switched off.
It never applies or sends emails for you.
For developers
docs/ARCHITECTURE.md, docs/ADDING_A_SOURCE.md, CHANGELOG.md. Tests: uv run pytest (offline);
real network checks: uv run pytest -m live. scripts/privacy_scan.sh keeps personal data out of the repo.
MIT licensed.
Available Tools
12 toolsbuild_resumeB
Build the tailored PDF resume for a job. variant: which resume to use if the user has several (saved for this job; 'auto' = pick automatically; leave empty to keep the current choice).
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | ||
| variant | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose non-obvious behavior about how the variant argument resolves ('saved for this job', 'auto' picks automatically, empty keeps the current choice), which is real value. However, it says nothing about side effects (where the PDF is written, whether it overwrites a prior build), permissions, or repeat-call behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, purpose front-loaded, with the parameter explanation compactly parenthesized. The parenthetical is dense but every clause adds information; nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema and no annotations, so the description should be more self-sufficient than it is. It covers what is produced and how variant resolves, but omits the job_id source, the output destination, and any side effects, leaving an agent to guess at invocation context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It compensates well for variant, effectively enumerating its accepted values despite no enum in the schema. The required job_id parameter gets no explanation at all (format, source, or validity), so half the parameters remain undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (build) and a concrete artifact (tailored PDF resume) tied to a job, which clearly separates it from siblings like cover_letter_prepare or find_jobs. It stops short of naming an alternative tool or stating the full workflow context, but the action and resource are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance: nothing says this is the step after selecting a job, that job_id must come from find_jobs/job_details, or that a prepare/submit flow does not apply here. The variant note implies the tool is called on an already-chosen job, but that is inference, not stated guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cover_letter_prepareA
Start a tailored cover letter for a job (language 'en' or 'no'; default from coverletter/style.yaml): returns the prompt. Write only the letter body following it, then call cover_letter_submit.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | ||
| language | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the non-obvious return behavior (a prompt, not letter content) and the required follow-up call, plus that language defaults come from coverletter/style.yaml. It says nothing about permissions, error cases, idempotency, or job_id validity, so the behavioral picture is only partially covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded: the action comes first, then the language/default caveat, then the workflow instruction. No filler sentences, though the telegraphic phrasing around 'returns the prompt' reads slightly clipped.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter prompt-generation tool with no output schema, the description supplies what an agent needs: the input semantics, the fact that output is a prompt to be obeyed, and the next call. Only failure/permission behavior is absent, which is a minor gap for this tool class.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and neither property has a description, but the description supplies the real semantics for 'language' ('en' or 'no', default sourced from coverletter/style.yaml) which the schema lacks entirely. 'job_id' is left at name-only inference, so compensation is partial rather than complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Start a tailored cover letter for a job') and clarifies the surprising mechanic that the tool returns a prompt rather than a letter. It also names the follow-up sibling (cover_letter_submit), so an agent can place it in the workflow, though it never explicitly contrasts itself with that sibling's own purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operational context: call this first, write only the letter body from the returned prompt, then call cover_letter_submit. There are no explicit when-not conditions or scope exclusions, but the sequencing guidance is unambiguous for this tool's role.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cover_letter_submitB
Check a cover letter body (facts traceable to the resume/ad, length, banned phrases, keywords, language, one page). If it passes and accept_if_ok, makes the PDF + plain text in the output folder.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| job_id | Yes | ||
| accept_if_ok | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose a real side effect (creates PDF + plain text in the output folder) plus the gate that triggers it (passing checks AND accept_if_ok). It does not say what happens on failure, whether existing output files are overwritten, or what permissions/paths are required, which are significant gaps for a write-capable tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with the validation purpose and with the consequential write behavior placed second where it matters. The parenthetical check list is long but each item earns its place by defining what 'passes' means.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema and no annotations, so the description should cover results too. It implies a pass/fail diagnostic but never says what the check returns on failure (error list? reasons?), nor what the output files are named or where exactly they land, leaving the agent unable to predict the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for all three parameters. It usefully clarifies accept_if_ok's role (write only happens when checks pass and this flag is set) and body is described in passing as the letter to check, but job_id is never explained and no formats or constraints are given for any parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource ('Check a cover letter body') and enumerates the checks performed, plus the secondary action (making the PDF and plain text files). It is clearly distinguishable from a generic submit tool, but it never names or contrasts with the sibling cover_letter_prepare, so sibling differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the tool is meant to run on a drafted body, and 'If it passes and accept_if_ok' explains the conditional write path. There is no explicit when-to-use/when-not or pointer to cover_letter_prepare for the drafting step, so the agent must infer the workflow position.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
doctorC
Check the installation and settings; each problem has a fix hint.
| Name | Required | Description | Default |
|---|---|---|---|
| check_sites | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that problems include fix hints, but says nothing about whether the check is read-only, what permissions are needed, or how results are structured beyond the hint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that avoids waste. It is efficient, though the second clause is somewhat vague and could be more specific about output.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations, no output schema, and an undocumented parameter, the description is too sparse. It omits when to use the tool, what the parameter does, and any behavioral details beyond the existence of fix hints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description does not mention the sole parameter 'check_sites' at all. With no explanation of what the boolean controls, the agent cannot infer its effect from the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Check') and resource ('installation and settings'), distinguishing it from the job/resume/config sibling tools. The added note that problems come with fix hints clarifies the diagnostic nature, though it does not explicitly differentiate from all siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides no guidance on when to use this tool versus alternatives. The mention of fix hints implies troubleshooting, but there is no explicit trigger condition, prerequisite, or alternative tool named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_jobsC
Search the job sites now (or check on a search already running).
| Name | Required | Description | Default |
|---|---|---|---|
| source | No | ||
| wait_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, yet it only hints that a search may still be running. It never states whether the call blocks, what it returns (new results vs. status), whether it writes data to the site, or rate-limit/auth constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tightly-worded sentence with the primary action front-loaded. It wastes no words but is under-specified rather than genuinely concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A two-parameter search tool with no annotations, no output schema, and undocumented parameters needs more than one parenthetical sentence to be callable correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters have 0% schema description coverage, so the description must compensate and does not: 'source' is never mentioned, and only the phrase 'check on a search already running' loosely gestures at the polling semantics of wait_seconds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search the job sites'), so an agent can tell it initiates a job search. It doesn't differentiate itself from siblings like list_jobs or job_details, which is where it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical '(or check on a search already running)' implies two usage modes — trigger a new search or poll an in-flight one — but names no alternatives or selection criteria against siblings such as list_jobs or job_details.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_resume_prepareA
Start a resume import from a Word (.docx) or PDF file (docx_path = path to either): returns the prompt to follow.
| Name | Required | Description | Default |
|---|---|---|---|
| docx_path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that the call returns 'the prompt to follow' rather than completing an import, but says nothing about whether it writes files, what permissions are needed, or whether it is safe to re-run.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the action first and the input clarification parenthetical immediately after. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with no output schema, the essentials are covered, but as the opening step of a prepare/submit pair the description omits the follow-up step and any indication of what the returned prompt expects. An agent can call it, but not confidently place it in the workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the parameter name 'docx_path' is misleading, so the description earns real credit by stating it is the path to either a .docx or PDF file. It still omits path format (absolute/relative) and validation behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Start a resume import from a Word (.docx) or PDF file') and clarifies the accepted input formats. It does not explicitly name the sibling it hands off to (import_resume_submit_tex), so sibling differentiation is only implied by the prepare/submit naming.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'Start' implies this is the first step of a flow, but the description never says when to use it versus import_resume_submit_tex or build_resume, nor what happens next. Usage must be inferred from the two-step naming convention.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_resume_submit_texC
Check a LaTeX version of the imported resume against the source Word or PDF file.
| Name | Required | Description | Default |
|---|---|---|---|
| tex | Yes | ||
| accept_if_ok | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it undersells the operation: 'Check' reads as a read-only comparison, yet the tool is named submit_tex and exposes an accept_if_ok flag that implies the check can commit or accept the imported resume. Nothing is said about side effects, what a mismatch does, or reversibility.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is appropriately short, though the brevity is achieved partly by omitting needed information rather than by tight writing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations, no output schema, 0% schema coverage, and an undocumented side-effecting flag, the description leaves an agent unable to call this correctly or predict its effects. It should at minimum explain what a successful check returns and what accept_if_ok does.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both parameters. The description loosely implies the 'tex' input is the LaTeX file under test, but it never explains the required tex string's format or the accept_if_ok flag at all, which is the one parameter with real behavioral consequence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete action (check/compare) on a specific resource: the LaTeX version of an imported resume against the source Word/PDF. This places it in the import_resume_* workflow and separates it from siblings like build_resume or import_resume_prepare, though it never names a sibling explicitly and the name's 'submit' verb is not reconciled with the description's 'check'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no stated prerequisites (presumably a prior import_resume_prepare call), and no indication of what to do if the check fails. The agent must infer the whole position of this step in the workflow from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
job_detailsC
Everything about one job, including the description and keyword match.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden and does not meet it. It never states that this is a read-only operation, what happens with an invalid or unknown job_id, or whether any authentication/configuration is required. It partly discloses returned content ('description and keyword match') but nothing about side effects or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with no filler, and the scope ('one job') is front-loaded before the content hint. It is efficiently sized, though brevity here edges into under-specification rather than crispness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter lookup with no annotations and no output schema, the description minimally suffices: it says what the tool returns in broad terms. But with no output schema to fall back on, it should have enumerated the returned fields more concretely and explained the input identifier, so gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single parameter (job_id, string) has no description. The tool description mentions 'one job' but never explains the identifier's format or where the agent should obtain it (presumably from find_jobs/list_jobs), so it does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The phrase 'Everything about one job' identifies the resource and its scope (a single job), implicitly distinguishing it from collection tools like find_jobs and list_jobs. However, it uses a vague catch-all ('everything') instead of a specific verb such as 'retrieve' or 'get', and it never names a sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this tool versus find_jobs, list_jobs, or mark_job, and no prerequisites (e.g. that a job_id must first come from find_jobs). The only usage signal is implicit: the singular resource suggests lookup after a search, but nothing in the text says so.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_jobsC
List saved jobs (best match first by default).
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | match | |
| limit | No | ||
| search | No | ||
| status | No | ||
| min_match | No | ||
| show_hidden | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, but it only discloses the default ordering ('best match first'). It says nothing about pagination, whether hidden jobs are excluded by default, required auth, or what fields come back — notable gaps for a 6-parameter read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler is structurally clean. However, the brevity comes at the cost of under-specification rather than efficiency, so it is only adequate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no annotations and no output schema, the description gives an agent almost nothing beyond the ordering default. Missing are the meanings of the filter/sort parameters, pagination behavior, and the distinction from find_jobs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 6 parameters, so the description must compensate and largely fails. 'Best match first by default' weakly hints at the sort parameter's default, but search, status, min_match, limit, and show_hidden are left entirely undefined in both the schema and the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') and resource ('saved jobs'), plus a scope hint that saved jobs are the domain. It does not differentiate from the sibling find_jobs, so an agent cannot tell from the description alone whether listing and finding are the same operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites, and no mention of alternatives such as find_jobs or job_details. The only implicit signal is the verb 'List' itself, which is the bare minimum.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_jobC
Set status: new, interested, applied, interview, rejected, offer, ignored.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | ||
| status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. 'Set status' implies a mutation, but it never states whether the change is idempotent, whether it can overwrite an existing status, what permissions are needed, or what happens on an invalid job_id — all material for a write tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single terse line with no filler, and the enumerable values are placed immediately after the verb. It is efficient, though it borders on under-specification rather than deliberate brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation tool with no annotations, no output schema, and no schema descriptions, the definition leaves too much unspecified: the effect of the operation, idempotency, and failure behavior are all missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It does add real value by enumerating the accepted status values, which the schema does not encode as an enum. However, job_id is left entirely unexplained, so coverage is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb (Set) and the resource being changed (a job's status), and the enumerated values make the intent unambiguous. It does not, however, distinguish itself from siblings like find_jobs or job_details beyond the implicit fact that it mutates rather than reads.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus the sibling tools, no preconditions, and no exclusions. The only guidance is the list of accepted status values, which is parameter information rather than usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_dashboardA
Start the dashboard in the background (if needed) and open it in the browser. Returns its address.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does reasonably well: it discloses a background server start, a browser-launch side effect, conditional execution ('if needed'), and the return value. It omits failure modes (port conflicts, browser launch failure) and whether the server persists, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, action first, return value last. Every clause earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description covers the trigger, the side effects, and the return format ('its address'), which is enough to call it correctly. Minor gaps around lifecycle and error behavior keep it just under complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and the schema is fully described, so there is no parameter nuance the description could add. Baseline 4 applies for a no-argument tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource pair (start the dashboard, open it in the browser) plus the returned artifact ('its address'). No sibling tool overlaps with dashboard launching, so there is no ambiguity to resolve.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase '(if needed)' implies the call is safe to make when a dashboard may already be running, which is light usage context. There is no explicit when-to-use/when-not-to-use guidance, but with no sibling alternative for this capability there is little to disambiguate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_config_filtersB
Change the job filters in config.yaml (only the fields you pass). Old file kept as config.yaml.bak.
| Name | Required | Description | Default |
|---|---|---|---|
| job_types | No | ||
| languages | No | ||
| locations | No | ||
| max_age_days | No | ||
| title_exclude | No | ||
| title_include | No | ||
| companies_exclude | No | ||
| companies_include | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses two behaviors beyond the schema: partial-update semantics (only passed fields change) and that the prior file is preserved as config.yaml.bak. However, it omits permissions required, whether relative or absolute path resolution, and whether filters affect already-recorded jobs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero padding, and the core action and file target are front-loaded. Every clause carries information, including the backup behavior in the second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter mutation tool with no annotations, no output schema, and 0% schema description coverage, this is too thin. Key details an agent needs — value formats, matching semantics for include/exclude lists, units for max_age_days, and the effect of changes — are absent from both the description and the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 8 parameters, so the description must compensate and does not: it never explains job_types, languages, locations, max_age_days, or the include/exclude list semantics. Nothing is added beyond the self-descriptive parameter names, and the numeric max_age_days unit and string-match rules are left undefined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Change the job filters in config.yaml'. It is unambiguous about what is being modified, though it does not differentiate itself from siblings (which are mostly job/resume tools) or note relationships to diagnostic tools like doctor.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives, no prerequisites, and no mention of when not to use it. The parenthetical '(only the fields you pass)' describes merge behavior rather than usage context, so an agent gets no routing help from this sentence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.5- Changed
build_resume1 field changed- added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Variant" +}
- Added
cover_letter_prepare - Added
cover_letter_submit - Added
open_dashboard
9 tool updates
v0.1.2- First observed
build_resume - First observed
doctor - First observed
find_jobs - First observed
import_resume_prepare - First observed
import_resume_submit_tex - First observed
job_details - First observed
list_jobs - First observed
mark_job - First observed
update_config_filters
TDQS
Scored across 12 tools
Each tool has a clearly distinct purpose: the two-phase workflows (cover_letter_prepare/submit, import_resume_prepare/submit_tex) are explicitly named as pairs, and search/list/detail/status tools target separate concerns. Even closely related tools like import_resume_submit_tex vs build_resume are differentiated by their descriptions (import validation vs tailored PDF generation).
All names are consistently snake_case, which makes the set readable and predictable. However, verb position varies (verb_noun like list_jobs/build_resume vs noun_verb like cover_letter_prepare/import_resume_submit_tex), and singleton names like 'doctor' and 'job_details' don't follow the verb_noun pattern.
Twelve tools is well-scoped for a job-application assistant covering search, tracking, cover letters, resume import/build, config, and diagnostics. Each tool earns its place with no redundant or filler entries.
The surface covers the full workflow: find/detail/list jobs, mark status, tune filters, prepare/submit cover letters, import and build resumes, plus dashboard and diagnostics. Minor gaps exist (no delete/remove job, no explicit export or application-submission tool), but agents can work around these.
Maintenance
Related MCP Connectors
Your career companion for ATS checks, resumes, cover letters, job tracking, websites, and more.
Analyze job listings against your resume, track applications, and generate cover letters.
The career management plugin for your own AI assistant: CVs, cover letters, interviews and more.
Search jobs, prepare resumes and cover letters, retrieve PDFs, and track your applications.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables 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.-
- FlicenseNot gradedqualityCmaintenanceEnables 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 gradedqualityBmaintenanceEnables 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-
- AlicenseNot gradedqualityBmaintenanceEnables Claude to read and update the local job-search tracker, adding postings from screenshots, pasted text or links, drafting application emails, syncing Gmail to log sent applications and replies, and answering questions about what's due or which jobs match a criteria. Every change is validated and appears live on the dashboard with a timeline entry.MIT