jobwatch
jobwatch MCP server watches company job boards, ranks new roles for you, and tracks your applications through hire — it finds and preps, but never applies for you.
Watchlist: find a company's board by name or job/careers link, then add or remove boards to watch.
New jobs: fetch every watched board for new postings, then get a filtered, best-first digest (optionally fit-scored against your resume, with people you know at each company).
Job details: pull one posting's full text, pay, fit score, must-have gaps, referral connections, missing skills, and what was sent.
Applying: queue roles worth applying to, mark statuses (applied, screening, interviewing, offer, rejected, withdrawn, skipped), add notes, next steps, follow-up dates, and pasted posting text.
Off-board jobs: add applications jobwatch didn't find (referrals, recruiters, LinkedIn links) so everything lives in one list.
Posting checks: verify queued jobs and open applications are still open, closed, or reopened.
Tracking: list applications with follow-ups due first, or list tracked jobs by status.
Packages: save and read back exactly what you submitted — resume, cover letter, form answers, and the posting as it read that day.
Interview prep: generate a printable prep sheet pairing each requirement with your closest resume line, plus gaps, questions to expect, and questions to ask.
Skills: see which skills your target jobs want that your resume lacks, ranked by demand, with courses and learning paths for your timeline.
Reads public Greenhouse job boards to discover and track new job postings at watched companies, including pay ranges and posting details.
jobwatch
Watch the job boards of the companies you care about and get a short, ranked digest of new roles that match you, optionally fit-scored against your resume. jobwatch finds and ranks. It never applies for you.

Watch it with sound (1½ minutes, made from made-up data).
$ jobwatch run
Checked 48 board(s): 9,412 open roles, 37 new.
# jobwatch digest
6 matching job(s). Filtered out: 22 by location, 4 by pay, 5 by title.
### [Staff AI Engineer](https://jobs.ashbyhq.com/initech/c1)
Initech · Denver, CO, United States; Remote · $230K–$300K · posted today
**Fit 81/100**, must-haves 6/7. Gaps: 3+ years with Kubernetes in production
Keywords: Python, RAG, agents
`ashby:initech:c1`
...Why company boards
Most tech companies post jobs through Greenhouse, Lever, Ashby or Workable, and most large employers through Workday (some through Eightfold or a Jibe careers site), and many small companies through Rippling. Each publishes open roles as public JSON so anyone can build a careers page, with no API key or scraping. jobwatch reads those feeds for the companies on your watchlist:
Complete and fresh: a role appears as soon as the company posts it, not when an aggregator picks it up.
Pay ranges: read from the board's structured fields where they exist (Lever, Ashby), otherwise from the posting text.
Polite: one request per company per run on Greenhouse, Lever, Ashby and Workable (a Jibe site: one per 100 roles). A Workday or Eightfold board can list thousands of roles, most of them nothing like yours, so jobwatch searches it for your
filters.titleswords and reads a posting in full only when its title passes your title filters, once: after that, a run costs a few searches per company. Titles written as regexes can't be searched for, so keep a plain word or two ("engineer", "forward deployed") among them. A board that answers "too many requests" (HTTP 429) is asked again after a pause; a posting it still won't serve is kept without its text and read on the next run. Eightfold boards are read one request at a time.Within the rules: it reads public APIs meant for this. It doesn't scrape LinkedIn or Indeed, which forbid it.
Related MCP server: mcp-autopilot-jobhunt
Install
pip install jobwatch # discovery, filters, digest
pip install 'jobwatch[score]' # + fit scores with shortlist-ai (Claude API)
pip install 'jobwatch[local]' # + fit scores on-device (Apple Silicon, MLX)
pip install 'jobwatch[mcp]' # + MCP server for Claude and other assistantsQuick start
In your browser
pipx install jobwatch # or: pip install jobwatch
jobwatch uiA page opens on your computer. Add the companies you want to watch (type a name or paste a link to one of their jobs), say what you're looking for, and press Check for new jobs. From there:
Today: new matching jobs, with pay, how long ago they were posted, keywords, and who you know there. Queue the ones worth applying to, Skip the rest.
Queue: your short list. Apply on the company's site, then press I applied.
Long lists come in pages (12, 24, 48 or 96 at a time, kept per browser).
Applications: every job you applied to and where it stands (applied, screening, interviewing, offer, rejected, withdrawn), with the next step and a follow-up day. Those due come first. Filter by status with the chips over the list (or click the pipeline bar), and switch between Cards and a sortable Table. Add an application covers jobs you found elsewhere, such as a referral or a recruiter.
Settings: companies, filters, keywords, your resume (for fit scores), your LinkedIn connections, and the page's theme (system, light or dark) and width (standard, wide or full, for a big monitor).
Ask jobwatch: a chat on Today (about all of today's jobs and your applications) and beside each job's details (about that posting). See Chat.
The page only talks to jobwatch on your own machine. The one exception is a model you choose: with
scoring.backend: claude, fit scores and chat send the posting and your resume to Anthropic. It's the same
watchlist file and history as the command line, so you can switch between the two.
To have the page always there, even after a restart, on a Mac:
jobwatch service install # starts jobwatch ui when you log in, and again if it stops
jobwatch service status # running? where's the log?
jobwatch service uninstallA login item doesn't see variables set in your shell profile, so with scoring.backend: claude the page's
chat and scores need ANTHROPIC_API_KEY given to launchd (launchctl setenv ANTHROPIC_API_KEY ...), or
run jobwatch ui from a terminal instead. The local backend needs nothing.
On the command line
jobwatch init # writes an example jobwatch.yaml
jobwatch find "Anthropic" "Scale AI" # find each company's board
jobwatch find https://jobs.lever.co/spotify/4f1c2a9e-... # or paste any job linkfind prints a line like Anthropic: greenhouse:anthropic (627 open roles). For a Workday company it tries
the usual site names; if that finds nothing, paste a job link from their careers site (it has
myworkdayjobs.com in it) and find reads the board from it: workday:nvidia.wd5/NVIDIAExternalCareerSite.
A company's own careers page works too (jobwatch find https://careers.acme.com/jobs): find reads it for
links to a board, which is how a board under a name nobody would guess turns up. Add those
entries under companies:, adjust the filters, then:
jobwatch run # fetch every board, then show the digestRun it daily, for example from cron: 0 8 * * * jobwatch run -o ~/jobs-today.md.
The watchlist
companies:
- greenhouse:anthropic
- lever:spotify
- {source: ashby, board: openai, name: OpenAI}
- workable:acme # apply.workable.com/acme
- {source: workday, board: nvidia.wd5/NVIDIAExternalCareerSite, name: NVIDIA} # tenant.wdN/site
- {source: eightfold, board: acme, name: Acme} # tenant (or tenant/domain), from a link
- {source: jibe, board: careers.acme.com, name: Acme} # a Jibe site's host (job links: /careers-home/jobs/...)
- rippling:acme # ats.rippling.com/acme/jobs
filters:
titles: ["engineer", "architect"] # regexes; the title must match one
exclude_titles: ["intern", "manager"]
exclude_departments: ["sales"]
locations: ["remote", "Denver", "Boulder, CO"]
remote_country: US # remote roles must be open in the US ("any" to allow all)
min_salary: 200000 # the top of a listed range must reach this
require_salary: false # true: drop postings without pay
max_age_days: 30
flags: # not filters: a warning on queued jobs whose posting says this
"active (TS|top secret)": clearance
"on-?site 5 days": on-site
keywords: # relevance: title hits count double
LLM: 3
RAG: 3
Python: 2
"re:agent(s|ic)?": 2 # "re:" prefix = regex
resume: ~/Documents/resume.pdf # for fit scores
connections: ~/Downloads/linkedin.zip # who you know at each company (see below)
scoring:
backend: claude # or local
top: 5 # score the 5 most relevant new jobs per digest
auto: true # the page scores every new match in the background
display: # the browser page
theme: system # system, light or dark
width: standard # standard, wide or fullRelative paths are resolved from the watchlist's folder. State (which jobs you've seen, applied to or
skipped, and their scores) lives in one SQLite file, by default ~/.local/share/jobwatch/state.db.
How locations match
A posting can list several places (London, UK; Remote-Friendly, United States; Austin, TX), and each one
is checked:
remotematches a place that says remote and is inremote_country, or says only "Remote". It also matches a posting whose own remote flag is set and that lists a US location.Any other entry matches as text, so
DenvermatchesDenver, CO, United States.
Fit scores
Keyword relevance is fast and explainable, but it can't tell "uses Kubernetes" from "5+ years running
Kubernetes in production". With resume: set and scoring.top (or --score N), the most relevant new
jobs are scored with shortlist-ai:
It turns the posting into must-have and nice-to-have requirements.
It judges each requirement against your resume, with quotes it checks against the resume text.
It lists the must-haves the resume doesn't show.
Scores are stored per resume file content, so each job is scored once, and again only after you edit your
resume. The local backend takes a minute or two per job, so keep top small.
While jobwatch ui runs, it scores every matching job in the background, most relevant first and one at a
time: when the page starts, after each "Check for new jobs", and after you add a new resume. Today shows
how many are left, and a button brings in the new scores when you're ready (the cards don't move on their
own). A chat reply or a "Score fit" click goes first; background scoring waits for it. It's on by default
with scoring.backend: local. With claude every score is a paid API call, so turn it on with
scoring.auto: true. jobwatch score [--limit N] does the same in the terminal.
Chat
Ask questions in plain words: "which three should I apply to first?", "what follow-ups are due?", "how well do I fit this one, honestly?", "what will they ask in interviews?". The chat uses the model you set for fit scores:
scoring.backend: local: the same on-device model as scoring (pip install 'jobwatch[local]'). Nothing leaves your computer. The first answer waits for the model to load.scoring.backend: claude: Claude Sonnet via Anthropic's API (ANTHROPIC_API_KEY). Your question, your resume and the jobs it's about are sent to Anthropic.
It reads today's matching jobs and your applications, or one posting with its fit score and what you sent, plus your resume (the one you sent for that job, when it's kept). It's told to use only your resume for facts about you and to treat posting text as data, not instructions. It has no tools, so it can't change, apply for or send anything.
Under each reply are a copy button and what it took: seconds (and any wait for a background fit score to finish), tokens in and out, and on this computer tokens per second and peak memory. While a reply is on its way, a timer shows how long it's been against how long recent replies took. The download button in the chat's header saves the conversation as Markdown. The same thing works from the terminal:
jobwatch ask "What follow-ups are due this week?"
jobwatch ask --job c1 "What should my resume lead with for this one?"Skills to build
Which skills do the jobs you're going after ask for that your resume doesn't show, and where can you learn them in the time you have?
jobwatch skills # gaps across today's matches and your applications
jobwatch skills --timeline month # week, month, quarter (default) or any
jobwatch skills --all # also the skills your resume already showsThe Skills tab in jobwatch ui shows the same, with a timeline switch, and each job's details link to it
from the gaps it lists.
Skills are ranked by demand: how many of your matching jobs mention one, with a must-have that a fit score found missing counting three times. Each comes with:
curated courses and certifications from the official pages (AWS, Linux Foundation, DeepLearning.AI, Hugging Face, OWASP...), each with a rough time and marked if it's longer than your timeline;
searches on LinkedIn Learning, Coursera, edX and, for AI skills, DeepLearning.AI;
with a timeline of a quarter or more, certificate programs at colleges near you.
Fit-score gaps no course closes (a clearance, citizenship, a degree, travel) are listed apart, and so are must-haves asking for years of something: a course gives you something concrete to point to, not the years.
learning:
timeline: quarter # week, month, quarter or any
near: Denver # for colleges nearby; default: the first city in filters.locationsThe chat knows the top gaps too ("what should I learn this month?"), and a job's details list the skills that posting asks for that your resume doesn't show.
The apply queue
Pick the roles worth a tailored application from the digest and queue them. Work through the queue when you have time:
jobwatch queue c1 aaaa-1111 --note "ask for a referral first" # add (the posting id is enough)
jobwatch queue # what to apply to next, oldest first
jobwatch show aaaa-1111 # full posting text: for tailoring a resume
jobwatch mark applied aaaa-1111 --note "referred by a friend" # after you submit
jobwatch mark skipped greenhouse:acme:102
jobwatch list --status appliedQueued jobs leave the digest. The queue flags any posting that has since closed, and what to check before
applying: pay below min_salary, a place your filters don't want (a job queued by hand never passed them),
and anything your filters.flags patterns find in the posting. Every fetch notices a watched board's
postings closing; jobwatch check also checks queued jobs and open applications from boards you don't
watch, and from LinkedIn links:
jobwatch check # closed (or back) since the last check; --all lists the open ones tooJobs you found somewhere else
A job from LinkedIn, a job-alert email or a friend goes in the queue with its link. When the link is to a posting on Greenhouse, Lever, Ashby, Workable, Workday or Rippling, jobwatch reads the posting from there, so it can be fit-scored and prepped for like any other, even if you don't watch that company. A LinkedIn job link is read from LinkedIn's public posting page (one page, the one you gave; jobwatch doesn't search LinkedIn), then the same job is looked for on the company's own board: found, that's what is tracked, since it's where the application goes; not found, the LinkedIn posting is. For anything else (a company's own site), give the company and title and paste the posting's text:
jobwatch add https://apply.workable.com/acme/j/A1B2C3D4E5/ --status queued
jobwatch add "Umbrella" "Staff Engineer" --url https://www.linkedin.com/jobs/view/... --text posting.txt --status queued
pbpaste | jobwatch add "Umbrella" "Staff Engineer" --text - --status queued # the posting from the clipboardIn the browser, press Add a job on the Queue page. Many job sites (LinkedIn's "Apply on company website", job-alert emails) link through to the company's own board: that link is the one to use.
Tracking applications
An application moves through stages: applied, screening, interviewing, offer, and then rejected
or withdrawn. Each can have a next step and a day to follow up. Jobs you found somewhere jobwatch doesn't
watch (a referral, a recruiter, LinkedIn) go in with add, so every application is in one list:
jobwatch add "Umbrella" "Principal Engineer" --url https://... --on 2026-09-14 --note "via a recruiter"
jobwatch add https://job-boards.greenhouse.io/acme/jobs/101 --on 2026-09-20 # read from the link
jobwatch mark screening c1 --next "technical round" --follow-up +7 # or a date: 2026-10-05
jobwatch mark rejected principal-engineer
jobwatch mark umbrella interviewing # the company is enough when you applied there once
jobwatch mark withdrawn c1 --add-note "recruiter says onsite only" # adds a dated line; --note replaces
jobwatch mark c1 --add-note "interview Friday 10:30" --follow-up 2026-10-08 # no stage: it stays as it is
jobwatch mark principal-engineer --text posting.txt # its posting, found later, for scoring and prep
jobwatch applications # every application, follow-ups due first (alias: apps)
jobwatch applications --due # only the ones to act on todayThe day you applied is kept as an application moves through the stages. --next "" or --follow-up ""
clears a field. An application added by hand with only a company and a title can get its posting's text
later with --text (a copy from a job board, or - to paste it), so it can be scored and jobwatch prep
has something to work from; the posting kept with the application is replaced with it.
Every company on Workday has its own careers site with its own sign-in, so after a few applications it's hard
to remember where each one lives. For a Workday application, jobwatch show, jobwatch applications and
the job's Details link that company's candidate page (.../userHome), where you sign in to see its
status. jobwatch keeps only the link, never a login or password: your password manager saves each company's
login under that company's own address. For one you added by hand whose posting has since come down, give
it the company's careers site (jobwatch mark <key> --url https://acme.wd1.myworkdayjobs.com/Careers)
and the page link follows.
What you sent
Each application keeps what you submitted, as copies:
the resume and cover letter exactly as uploaded;
the answers you gave on the form (salary expectation, why this company, notice period...);
the posting as it read the day you applied.
Tailored resumes get rebuilt and postings change or come down. When a recruiter calls three weeks later, this is what they're looking at. The chat reads it too, so "prep me for the recruiter call" works from what you actually told them.
In the browser, open an application's Details and drop files into What you sent. From the command line:
jobwatch mark applied c1 --attach ~/Downloads/Resume_Initech.pdf
jobwatch attach c1 cover-letter.pdf --answers answers.yaml # answers.yaml: "Why Initech?: ..." pairs
jobwatch package c1 # show itPackages live in packages/<job>/ next to the state file. Removing a file moves it to .removed/ there
rather than deleting it.
Prep sheets
Before a recruiter call or an interview, open the application's Details and press Prep sheet (or run
jobwatch prep c1). One page, ready to print, with:
the stage, next step and your notes;
each requirement and responsibility in the posting, next to the line on your resume closest to it (the resume you sent, if you kept it), or a plain "nothing close" so you can prepare a story or an honest answer;
skills they ask for that your resume doesn't show, with the fit score's missing must-haves;
what you sent;
questions to expect and questions to ask, for a screen or for interviews.
Nothing on it is written for you: it quotes the posting and your resume. For an application you added by hand,
jobwatch looks for the posting on your watched boards by the requisition id in its title (R0123456,
REQ-4711, Job 20769), so a Workday posting fetched later fills in the sheet.
Who you know there
A referral gets read before an application does. Download your LinkedIn data (Settings → Data privacy →
Get a copy of your data) and upload the archive in jobwatch ui, or point connections: at the .zip or
at its Connections.csv. Each digest and queue entry then lists your connections who work there:
You know: Ana Li (Staff Engineer) [messaged 14×, last 2025-03-02]; Bo Chen (Recruiter)With the full archive, people you actually talk to come first. jobwatch counts the messages you exchanged, recommendations and endorsements, so a close colleague ranks above someone who only accepted a connection request. Only those counts are kept, never your messages. When you know nobody at a company, the page links to a LinkedIn search of your 2nd-degree network there, to find someone who can introduce you.
Companies are matched by name, ignoring suffixes like "Inc." and "Corporation". Your LinkedIn data is only read on your machine.
A digest lists each job once. Use digest --all to include jobs already shown, or --peek to look without
marking them shown. Roles that disappear from a board are marked closed.
MCP server
jobwatch-mcp offers these tools to Claude Code or any MCP client:
Watchlist:
find_board,list_boards,add_board,remove_boardNew jobs:
fetch_jobs,get_digest,get_job,list_jobs,list_skill_gapsApplying:
mark_job,list_queued_jobs,check_postings,add_application,list_applicationsWhat was sent:
save_application_package,get_application_package,get_interview_prep
(0.3.0 renamed them to verb_noun: digest is now get_digest, job_details is get_job, apply_queue is
list_queued_jobs, applications is list_applications, application_package is get_application_package,
interview_prep is get_interview_prep and skill_gaps is list_skill_gaps.) The watchlist comes from
JOBWATCH_CONFIG:
claude mcp add jobwatch -s user -e JOBWATCH_CONFIG=~/jobwatch.yaml -- jobwatch-mcpjobwatch mcp runs the same server. Without installing anything first,
uv can fetch and run it:
claude mcp add jobwatch -s user -e JOBWATCH_CONFIG=~/jobwatch.yaml -- uvx --with 'mcp>=2.2' jobwatch mcpIt's listed in the MCP Registry as io.github.vinayvobbili/jobwatch.
With a resume tool alongside it (for example resume-kit, whose
resume draft starts a tailored version from a posting), an assistant can work through your queue: read
the posting, tailor the resume from facts you've confirmed, check for a referral, and fill in the
application for you to review. You still press Submit.
Why it doesn't auto-apply
Tools that auto-apply to hundreds of jobs make the process worse for everyone and rarely work for the person using them:
Recruiters recognize mass applications.
Some companies cap how many roles one person can apply to.
Application forms ask legal questions (work authorization, export control, signatures) that you answer yourself.
jobwatch's job is to make sure you never miss a role worth applying to, and to spend your time on those.
Development
python -m venv .venv && .venv/bin/pip install -e '.[dev,mcp]'
.venv/bin/ruff check . && .venv/bin/python -m pytest -qCI tests on Python 3.10 and 3.13. scripts/check runs the same checks on both locally (it needs
uv, which fetches each Python). git config core.hooksPath .githooks runs it before
every push.
Tests use canned board responses and never touch the network, except the check that every curated course
link still resolves: JOBWATCH_LINK_TESTS=1 pytest tests/test_learn.py. To see how jobwatch ui looks after a change,
scripts/screenshots.py captures every tab in light and dark, at wide, desktop and phone widths, plus the
chat with a canned reply (it needs
pip install playwright && python -m playwright install chromium).
scripts/demo/make-video rebuilds the demo video from made-up data: see
scripts/demo/README.md.
Releases publish to PyPI through Trusted Publishing when a v* tag is pushed, and then to the MCP Registry
from server.json (keep its two versions in step with the package; a test checks).
scripts/release.py 0.2.3 -m "what's in it" does the whole release: it bumps all three versions, runs
scripts/check, commits, tags, pushes, and waits until PyPI and the registry show the new version
(--dry-run shows the bump first).
MIT licensed.
Available Tools
17 toolsadd_applicationA
Add a job jobwatch didn't find (a referral, a recruiter, LinkedIn...), so everything is in one place: an application (only after the person has applied themselves), or status queued for one they're considering. A url to one job on Greenhouse, Lever, Ashby, Workable, Workday or Rippling is read in full (company and title may be left out); so is a LinkedIn job link, which is tracked on the company's own board when the same job is found there. Otherwise give company and title, and text (the posting, pasted) so it can be scored. For a job jobwatch already tracks (it came from get_digest or get_job), use mark_job instead.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling or LinkedIn are read in full; any other link is just kept. | |
| note | No | A note: who referred them, how they found it... | |
| text | No | The posting's text, pasted, when the link can't be read, so it can be scored and prepped. | |
| title | No | The job title; may be left out when url is a job link it can read. | |
| status | No | applied (the default; only once the person has applied themselves), queued for one they're considering, or a later stage such as interviewing. | applied |
| company | No | The company; may be left out when url is a job link it can read. | |
| follow_up | No | A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it. | |
| next_step | No | What happens next ("hiring manager call Friday"). | |
| applied_on | No | The day applied (YYYY-MM-DD), if not today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, openWorldHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral detail beyond that: which domains are read in full, that a LinkedIn link is re-tracked on the company's own board, that status 'applied' is only valid once the person has applied, and that pasted text enables scoring. It stops short of auth/rate-limit context, so not 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?
Purpose is front-loaded in the first clause, followed by the url-vs-manual branch and then the sibling alternative. Dense but every sentence carries a decision the caller must make; minor tightening of the parenthetical examples is possible.
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 9-parameter tool with no required fields, an output schema, and full annotation coverage, the description supplies exactly the missing decision context: which input mode to pick, what status values mean, and the mark_job fallback for dedup. Return values and the timing parameters are covered by the output schema and 100%-described input 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 coverage is 100%, so the baseline is 3, but the description adds cross-parameter conditional logic the schema does not: company and title 'may be left out' when url is a readable job link, and text substitutes when a link can't be read. It also clarifies the meaning of the default status value ('applied' only after the person applied), which is more than a restatement.
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 (add) and resource (an application/job jobwatch didn't find), and scopes it precisely as jobs the tracker missed (referrals, recruiters, LinkedIn). It also names the sibling it is not — mark_job — for jobs already tracked, so an agent can route correctly without opening schemas.
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?
Explicit when-to-use ('a job jobwatch didn't find'), when-not ('for a job jobwatch already tracks ... use mark_job instead'), and the conditional split between supplying a readable url versus company+title+text. Alternatives and preconditions are named rather than implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_boardAIdempotent
Add a company's board to the watchlist, so fetch_jobs checks it from now on. Find the entry with find_board first and check its sample titles: a guessed board name can belong to another company. Adding one that's already there only updates its name. Creates the watchlist when there is none yet. The watchlist is rewritten (a copy of the old one is kept as .bak; comments in a hand-written file are not kept).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | The company's name as it should show, when the board's own name isn't it (e.g. a Workday tenant id). | |
| entry | Yes | The board as source:board, the way find_board and list_boards give it (e.g. greenhouse:stripe). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Extraordinarily candid about side effects beyond the annotations: adding an existing entry only updates its name, the watchlist file is created if absent, the file is rewritten with a .bak copy kept, and hand-written comments are lost. The idempotentHint=true and destructiveHint=false annotations are consistent with these statements.
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?
The primary action and downstream consequence are front-loaded, and every sentence carries distinct information (prerequisite, idempotency, file creation, rewrite caveat). The prerequisite sentence is slightly dense but not wasteful.
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 output schema needed for a file-mutation tool, the description still covers the mutation's side effects, idempotency, prerequisites, and data-loss caveat. An agent has everything needed to call this correctly and safely.
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 100%, so both 'name' and 'entry' are already documented with format examples in the schema. The description references the source:board format via find_board/list_boards but adds no syntax detail beyond the schema, so the baseline of 3 applies.
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 ('Add a company's board to the watchlist') and immediately names the downstream effect (fetch_jobs checks it from now on), which distinguishes it from siblings like find_board and list_boards that only read boards.
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 explicit prerequisites and workflow routing: find the entry with find_board first and verify sample titles, plus the warning that a guessed board name may belong to another company. It doesn't name when-not-to-use, but the sequencing guidance is concrete and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_postingsAIdempotent
Check that the postings of queued jobs and open applications still take applications, and record the ones that closed or came back. result is open, closed, reopened, or unknown (check it yourself). Run it before working through list_queued_jobs, so time isn't spent on closed postings.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, and openWorldHint=true; the description is consistent, explaining that state changes to postings are recorded (the write behavior implied by readOnlyHint=false). It adds the useful caveat that 'result' may be 'unknown' and must be re-checked manually, though it says nothing about permissions, rate limits, or how many postings are checked.
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, front-loaded with the action and ending with the operational rationale for running it first. The first sentence is dense ('postings of queued jobs and open applications still take applications, and record the ones that closed or came back'), slightly re-read worthy but not padded.
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 no-parameter, idempotent write tool with an output schema present, the description covers purpose, timing, and the meaning of the result field. Since an output schema exists it needn't enumerate return values further, though a note on whether it only inspects tracked postings would make it airtight.
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, so there is nothing for the description to disambiguate. The mention of 'result' values is closer to output semantics than parameter semantics, but does not hurt.
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 states a specific verb (check) and resource (postings), scopes it to queued jobs and open applications, and notes the side effect of recording closed/reopened postings. It also distinguishes itself from list_queued_jobs by positioning itself as a prerequisite step, so an agent can route correctly without reading any schema.
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?
Explicitly states when to run it ('before working through list_queued_jobs') and why (so time isn't spent on closed postings), naming the sibling tool it relates to. There is a clear ordering constraint rather than implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_jobsAIdempotent
Check every board in the watchlist and record new roles. Returns counts, and each board that failed to load (skipped; the rest are still recorded). Run it before get_digest, which lists the new roles themselves.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true, openWorldHint=true), so the description's job is to add beyond that. It does: it discloses that failures on individual boards are skipped while the rest are still recorded, which is non-obvious partial-failure semantics an agent needs. It does not restate idempotency or say what 'counts' comprise, but the added failure behavior is genuinely useful.
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, both front-loaded: the action first, then the failure behavior and the sequencing instruction. No filler, no restatement of the name.
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?
An output schema exists, so the description needn't enumerate return values; mentioning that it returns counts is a helpful hint rather than a gap. Combined with the partial-failure note and the ordering against get_digest, an agent has everything required to call it 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?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline is 4. The description correctly avoids inventing inputs and instead explains 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 ('Check every board in the watchlist and record new roles'), scoping the action to the whole watchlist. It also names the complementary sibling get_digest, so an agent can distinguish it from the listing tools without opening a schema.
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?
Explicitly tells the agent to run this before get_digest and explains the division of labor (this records; get_digest lists the roles). This is a clear sequencing rule, though it gives no explicit 'when not to use' condition or alternative for already-fetched data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_boardARead-onlyIdempotent
Find a company's job board by name or by a job/careers link. Returns entries for the watchlist. A guessed board name can belong to another company: check the sample titles before adding one. Use it before add_board; to track one job from its link, use add_application instead.
| Name | Required | Description | Default |
|---|---|---|---|
| company | Yes | A company name ("Stripe"), or a link to one of its job postings or its careers page. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld/non-destructive, so safety is covered. The description adds a genuine behavioral caveat not in the structured fields: a guessed name may match the wrong company, so sample titles should be checked first. That is useful domain insight, though auth/rate-limit context is absent.
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?
Four short sentences, front-loaded with the core action and scope, then the caveat, then routing. Every sentence 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?
An output schema exists so return format needn't be explained, annotations carry the safety profile, and the description supplies the pitfall caveat plus sibling routing. Nothing an agent needs to call this correctly is 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 100% and the single 'company' param is fully documented in the schema, so the description needn't carry parameter detail. It restates 'by name or by a job/careers link' but adds no syntax or format guidance beyond the schema. Baseline 3 applies.
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: 'Find a company's job board by name or by a job/careers link.' It also names the resulting scope ('entries for the watchlist'), distinguishing it from siblings like list_boards and add_board without the agent needing to open any schema.
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?
Explicitly routes: 'Use it before add_board; to track one job from its link, use add_application instead.' This gives both the when (before adding) and named alternatives for adjacent intents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_application_packageARead-onlyIdempotent
What was sent with an application: files kept (with their folder), form answers, note, and the day the posting was saved as it read then (posting.md in the folder). Use it to check exactly what was sent; for a full prep sheet use get_interview_prep, and for the posting and fit use get_job.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds genuine behavioral context beyond that: the returned posting is a frozen snapshot ('as it read then'), which tells the agent this is not live data and that a file artifact (posting.md) exists. It does not describe the multi-match error path, though the schema does.
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, front-loaded with the payload contents followed by the routing guidance, with no filler. The first sentence is a dense list, but every element is load-bearing.
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 one well-documented parameter, no output schema, and full annotation coverage, the description supplies precisely what is missing: the shape of the return payload and the frozen-snapshot semantics. Nothing an agent needs to call it correctly is absent.
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 100% and the single 'key' parameter is documented in detail there (formats, fallback to company name, multi-match behavior). The description adds no parameter-level meaning, so the baseline 3 is appropriate.
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 enumerates exactly what the tool returns (files with their folder, form answers, note, the frozen posting.md) and frames it as the application package snapshot. It explicitly differentiates itself from get_interview_prep and get_job, so an agent can pick it without opening any schema.
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?
'Use it to check exactly what was sent' states the positive trigger, and the two named alternatives each come with their own condition ('full prep sheet' -> get_interview_prep, 'posting and fit' -> get_job). This is explicit when/when-not/alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_digestA
New jobs that pass the watchlist's filters, best first (fit score when scored, then keyword relevance), with people the user knows at each company. Call fetch_jobs first to pick up today's postings. This is for finding jobs to consider; for jobs already queued use list_queued_jobs, and for applications use list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | The most jobs to return, best first. | |
| score_top | No | How many of the most relevant unscored jobs to fit-score against the resume with shortlist-ai first. 0 (the default) skips scoring; each job takes minutes on the local backend, so keep it small. | |
| mark_shown | No | Mark the returned jobs as shown, so the next digest leaves them out. False to peek without changing anything. | |
| include_seen | No | Also include jobs already shown in an earlier digest, not just new ones. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnlyHint=false, destructive=false, idempotent=false), and the description correctly implies mutation rather than contradicting it. It adds genuinely useful behavior beyond the annotations: the ranking logic and the stateful prerequisite that fetch_jobs must run first. It stops short of warning that the default call consumes/suppresses jobs (mark_shown=true) — that disclosure lives only in the parameter schema.
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?
Three tight sentences, front-loaded with what the tool returns and its ordering, then the prerequisite, then the sibling routing. No filler and nothing buried.
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, so the description could say more about the shape of a digest entry (beyond 'people the user knows at each company'), and the default mark_shown=true side effect is not surfaced in prose. Still, prerequisite, ordering, and alternatives are all covered, which is most of what an agent needs.
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 100%, so the baseline is 3, but the description adds meaning the schema lacks: it explains why results come back 'best first' and ties fit score to the scoring pass that score_top controls. This makes the limit/score_top interaction legible without reading parameter docs.
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 with scope: 'New jobs that pass the watchlist's filters, best first'. It also names the ordering rule (fit score, then keyword relevance), and explicitly distinguishes itself from list_queued_jobs and list_applications, so an agent can place it among siblings without opening the schema.
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 an explicit prerequisite ('Call fetch_jobs first to pick up today's postings') plus a when-not/what-else routing: 'for jobs already queued use list_queued_jobs, and for applications use list_applications.' Both the trigger and the alternatives are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_interview_prepARead-onlyIdempotent
A prep sheet for a recruiter call or interview: stage and next step, each requirement and responsibility in the posting next to the closest resume line (quoted, never written), gaps to be honest about, what was sent, questions to expect and to ask, and the posting. For an application added by hand, the posting is found on a watched board by its requisition id. markdown is the sheet ready to read. Use it before a call; get_job and get_application_package give the raw pieces.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive, so safety is covered. The description adds genuine context beyond that: resume lines are "quoted, never written" (no fabrication), the sheet output is markdown ready to read, and for hand-added applications the posting is resolved on a watched board by requisition id.
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?
The purpose is front-loaded, but the middle is a dense, comma-spliced run-on ("what was sent, questions to expect and to ask, and the posting") and "markdown is the sheet ready to read" is awkwardly phrased. Every idea earns its place, but the packing hurts readability.
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 output schema, the description carries the return-value burden and does so by enumerating the sheet's sections and stating the markdown format. Key resolution and sibling alternatives are covered; only minor gaps remain (e.g., no indication of failure when no posting is found).
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?
There is one parameter with 100% schema coverage, and the schema already documents the key format, the bare-posting-id fallback, company-name matching, and the multi-match error behavior. The description only adds that a hand-added application resolves via requisition id on a watched board, which is marginal over the schema. Baseline 3 applies.
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 concrete artifact (a prep sheet for a recruiter call or interview) and enumerates its contents: stage/next step, requirement-to-resume-line mapping, gaps, what was sent, questions, and the posting. It explicitly differentiates from siblings by stating that get_job and get_application_package give the raw pieces, so an agent can pick the right tool without opening schemas.
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?
"Use it before a call" gives a clear trigger, and the closing sentence routes the agent to get_job and get_application_package when raw data is wanted instead. There is no explicit statement of when not to use it (e.g., no application yet), but the alternative routing is strong enough for a 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_jobARead-onlyIdempotent
Everything about one job, by key or posting id: the full posting text, pay, tracking (status, note, next step, follow-up), its fit score against the resume (score, must-haves met, gaps), people the user knows there plus a LinkedIn search for a referral, skills it asks for that the resume doesn't show, what was sent with the application, and candidate_home: the company's page where the person signs in to see the application's status (Workday only; each company has its own account). Use it to tailor a resume or decide whether to apply; for only what was sent use get_application_package, and for a call or interview use get_interview_prep.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds real context beyond that: the candidate_home concept (the company's own sign-in page, Workday only, per-company account) and the breadth of returned data, plus the schema documents multi-match error behavior. It stops short of describing output format or size, so it earns 4 rather than 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?
Front-loaded with purpose, then the return inventory, then the routing sentence. The long middle enumeration is dense but each item is a distinct fact an agent needs to judge relevance; only minor trimming is possible.
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 output schema, the description carries the full burden of telling the agent what comes back, and it does so comprehensively — including the non-obvious candidate_home field. Combined with annotations covering the safety profile, nothing needed to call this correctly is 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?
There is a single parameter and the schema description already covers it at 100% (composite key, bare posting id, or company name, with multi-match error behavior). The description only restates 'by key or posting id', adding no syntax beyond the schema. Baseline 3 applies.
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 retrieval verb and resource ('Everything about one job, by key or posting id') and then enumerates the payload: posting text, pay, tracking, fit score, referral people, skill gaps, application package, candidate_home. It is immediately distinguishable from get_application_package and get_interview_prep, which it names.
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?
Explicitly gives the use case ('tailor a resume or decide whether to apply') and routes to the right siblings with conditions ('for only what was sent use get_application_package, and for a call or interview use get_interview_prep'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_applicationsARead-onlyIdempotent
Every application (applied or a later stage) and where it stands, follow-ups due soonest first; candidate_home is the company's page for checking its status, when it has one (Workday). Use it to see what needs a follow-up; for jobs not applied to yet use list_queued_jobs, and for any status use list_jobs.
| Name | Required | Description | Default |
|---|---|---|---|
| due_only | No | Only those whose follow-up day has come. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description's job is to add context beyond that. It does: result ordering, the applied-or-later scope, and the meaning of a non-obvious field (candidate_home is the company's own status page, only present for some systems like Workday). That last point is genuine added value, though no pagination or volume behavior is disclosed.
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?
Three dense clauses with no filler; the purpose and ordering lead, routing to siblings follows. The candidate_home clause is slightly tangential but earns its place by defining an otherwise opaque field.
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 single-parameter read-only list tool with an output schema and full annotation coverage, this covers purpose, routing, ordering and one field's semantics. Little is missing; only the due_only behavior and result-size expectations go unaddressed, and the output schema absorbs most of that burden.
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 100% and the single parameter due_only is fully described there, so the schema does the heavy lifting. The description hints at follow-up timing but does not explain what due_only actually narrows the result to. Baseline 3 is appropriate.
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 resource ('every application ... and where it stands') with scope (applied or a later stage) and ordering (follow-ups due soonest first). It even disambiguates against the two nearest siblings, so an agent can distinguish it from list_queued_jobs and list_jobs without opening any schema.
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?
Explicitly gives the trigger ('Use it to see what needs a follow-up') and names both alternatives with the condition that selects each: list_queued_jobs for not-yet-applied roles, list_jobs for any status. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_boardsARead-onlyIdempotent
The boards on the watchlist (entry, display name, careers page) and where the watchlist file is. Use it to see what fetch_jobs checks; add_board and remove_board change it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and closed-world, so safety is covered. The description adds genuine behavioral context beyond that: what the listing contains and that the same watchlist is mutated by add_board/remove_board. It does not cover permissions or freshness of the watchlist file, so it stops 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 sentences with no filler, and the resource being listed is front-loaded. The second sentence compresses three separate ideas (usage, alternative reads, mutating siblings) and the first is a verbless fragment, which costs it a point on polish but not on economy.
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 parameters, no output schema, and annotations already carrying the safety profile, the remaining burden is explaining what comes back and how it relates to siblings — which the description does. Minor omissions (whether the file path is user-specific, whether the list can be empty) keep it from a 5.
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, so per the baseline there is nothing for the description to disambiguate. The description correctly does not invent parameter talk, though it also gives no hint about whether output ordering or scoping can be controlled.
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 the specific resource (boards on the watchlist) and enumerates the returned fields (entry, display name, careers page) plus the watchlist file location. It explicitly distinguishes itself from siblings add_board/remove_board/fetch_jobs, so an agent can identify it without opening the schema.
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?
It states when to use it ('see what fetch_jobs checks') and names the alternatives that mutate the same data ('add_board and remove_board change it'). The when-to-use condition and the sibling routing are both explicit rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_jobsARead-onlyIdempotent
Tracked jobs with their tracking fields, newest first, including closed postings. A plain list by status (e.g. every skipped job); for ranked new jobs use get_digest, for the next to apply to list_queued_jobs, and for follow-ups list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Only jobs with this status; omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered; the description adds genuine behavioral context with 'newest first' ordering and the fact that closed postings are included, which is non-obvious for a job list. Pagination/limits are not addressed, but an output schema exists to carry return-shape details.
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, zero filler; the core behavior (untracked plain listing) is front-loaded before the disambiguation list. Every clause earns its place.
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 annotations covering safety, a 100%-covered single enum parameter, an output schema handling return values, and clear sibling routing, nothing an agent needs to call this correctly is 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 100% and the sole status parameter is fully described with its enum in the schema, so the baseline is 3. The description adds meaning by illustrating the filter's intent ('a plain list by status, e.g. every skipped job'), clarifying that it is an unranked equality filter rather than a relevance query.
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 ('tracked jobs'), plus scope qualifiers: newest-first ordering, inclusion of closed postings, and 'tracking fields'. It actively distinguishes itself from sibling list tools rather than restating the name.
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?
Explicitly names three alternatives (get_digest, list_queued_jobs, list_applications) with the condition that selects each, and adds a plain-list use case ('every skipped job'). An agent can route without opening any schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_queued_jobsARead-onlyIdempotent
Jobs queued to apply to, oldest first, with fit scores, notes, people the user knows there (ask them for a referral before applying) and warnings to check first (pay, place, flagged text). Use it to pick the next application; jobs get here through mark_job with status queued. For applications already sent use list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so safety is covered. The description adds the sort order (oldest first) and actionable workflow context (ask contacts for a referral before applying, check warnings for pay/place/flagged text), which goes beyond the annotations. It stops short of describing volume limits or pagination.
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?
Front-loaded with the core purpose and ordering, then routing guidance. The parenthetical enumerations of fields and the referral aside add useful detail but make the single sentence dense; still, every clause earns its place.
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-argument list tool with an output schema, the description covers what an agent needs: what comes back, the sort order, how entries get here, and which sibling to use for other cases. Return-value detail is rightly left to the output 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?
The tool takes no parameters, so per the rubric the baseline is 4. The description appropriately spends no space on argument syntax and instead documents what the (parameterless) result contains.
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 (queued jobs to apply to) and the ordering (oldest first), plus what each entry carries (fit scores, notes, contacts, warnings). It explicitly distinguishes itself from list_applications and marks mark_job as the source of these entries.
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 an explicit use case ('Use it to pick the next application'), how items arrive here ('through mark_job with status queued'), and names the alternative for the other case ('For applications already sent use list_applications'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_skill_gapsARead-onlyIdempotent
Skills today's matching jobs and the person's applications ask for, most in demand first, each with on_resume, how many jobs mention it, how many scored jobs list it as a missing must-have, and ways to learn it: curated courses and certifications (official pages, each with a rough time and whether it fits the timeline) and searches on Coursera, LinkedIn Learning, edX and nearby colleges. Also fit-score gaps no course closes (clearance, citizenship, degree, travel). Recommend only from these links; never suggest claiming a skill the resume doesn't show. For one job's gaps use get_job; to prepare for a call use get_interview_prep.
| Name | Required | Description | Default |
|---|---|---|---|
| timeline | No | How soon the person wants to close a gap: week, month, quarter or any. Omit for the watchlist's learning.timeline. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, so the bar is lower, and the description adds real value: it discloses the return shape (counts, on_resume flags, missing must-haves, fit-score gaps no course closes) and an agent-facing behavioral rule about not recommending unsupported skills. It does not cover pagination or result-size limits, 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?
The opening is well front-loaded with what the tool returns, but the middle is a sprawling run-on with nested parentheticals enumerating output fields and every learning platform (Coursera, LinkedIn Learning, edX, nearby colleges). The detail is defensible given there is no output schema, but the structure is dense enough that an agent must parse several clauses to find the routing guidance.
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 output schema, the description correctly carries the burden of describing the return payload and does so thoroughly, and read-only annotations cover the safety profile. What remains thin is the timeline parameter's behavior when omitted (it defers to the watchlist's learning.timeline without explaining the effect).
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?
There is a single optional parameter whose enum and default are fully documented in the schema (100% coverage), so the schema does the heavy lifting. The description only indirectly references it ('whether it fits the timeline') without adding format or defaulting behavior beyond what the schema already states; baseline 3 applies.
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 precise verb+resource (list skill gaps across the person's matching jobs and applications) and immediately specifies the ordering ('most in demand first') and the per-skill payload (on_resume, job counts, missing must-haves, learning links). It explicitly separates itself from get_job and get_interview_prep, so an agent can route correctly without opening any schema.
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?
It states the scope (all matching jobs and applications, aggregated) and names two concrete alternatives with the condition that selects each: 'For one job's gaps use get_job; to prepare for a call use get_interview_prep.' It also states a hard usage constraint ('Recommend only from these links; never suggest claiming a skill the resume doesn't show').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_jobADestructiveIdempotent
Record a job's status: new, shown, queued (to apply to next), applied, screening, interviewing, offer, rejected, withdrawn or skipped (omit status to keep it and only update the rest). key is the job's key, its posting id, or its company's name when that names one job (the one queued or applied to there); when it names several, nothing changes and the error lists them. Use applied only after the person has submitted the application themselves. add_note adds a dated line to the note, keeping what's there: prefer it for news ("recruiter replied: onsite only"); note replaces the whole note. next_step says what happens next ("recruiter screen Tuesday"); follow_up is the day to act (YYYY-MM-DD or +N days); applied_on is the day applied, if not today. url sets the link of a job added by hand (its posting, or the company's careers site once the posting is gone), and text its posting's text, pasted (found later, or from a copy once the posting is gone), so it can be scored and prepped. An empty string clears a field. For a job jobwatch doesn't track yet, use add_application.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| url | No | The link of a job added by hand: its posting, or the company's careers site once the posting is gone. | |
| note | No | Replaces the whole note. Prefer add_note for news. | |
| text | No | The posting's text, pasted (found later, or a copy once the posting is gone), so it can be scored and prepped. | |
| status | No | The new status; omit to keep it and only update the rest. applied only after the person has submitted the application themselves. | |
| add_note | No | A line to add to the note, dated today, keeping what's there ("recruiter replied: onsite only"). | |
| follow_up | No | A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it. | |
| next_step | No | What happens next ("recruiter screen Tuesday"). An empty string clears it. | |
| applied_on | No | The day applied (YYYY-MM-DD), if not today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile (destructive, idempotent, non-read-only), and the description adds operational behavior well beyond them: ambiguous key matches change nothing and return the offending keys in the error, empty strings clear fields, note replaces while add_note appends, and url/text are only for hand-added jobs. This is substantive disclosure of side effects and 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?
Purpose and status list are front-loaded, and each subsequent clause maps to a distinct parameter or edge case, so little is wasted. It is dense and long, with mild redundancy against the schema's own field descriptions, which keeps it from a 5.
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?
An output schema exists so return values need not be restated, and the description fills the remaining gaps: ambiguity handling, clearing semantics, append vs replace, and the boundary with add_application. An agent has everything needed to call this mutation 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?
Schema coverage is 100%, so the schema already documents all nine parameters; the description largely mirrors those per-parameter blurbs. It still adds cross-parameter meaning the schema does not, notably the status-omission rule, the note vs add_note distinction, and queued meaning 'to apply to next'.
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 opens with a specific verb+resource ('Record a job's status') and enumerates the full status vocabulary, making the operation unambiguous. It also explicitly contrasts itself with the sibling add_application for jobs not yet tracked, so an agent can distinguish the two without opening either schema.
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?
It gives explicit when-to-use rules for the trickiest cases: 'applied only after the person has submitted the application themselves', 'omit status to keep it and only update the rest', 'prefer add_note for news', and 'For a job jobwatch doesn't track yet, use add_application'. Both the alternative tool and the selecting condition are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_boardADestructiveIdempotent
Take a board off the watchlist, so fetch_jobs stops checking it. Jobs and applications already recorded from it are kept. The watchlist is rewritten, with a copy of the old one kept as .bak.
| Name | Required | Description | Default |
|---|---|---|---|
| entry | Yes | The board as source:board, the way find_board and list_boards give it (e.g. greenhouse:stripe). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds genuinely non-derivable behavior: previously recorded jobs/applications survive, the watchlist file is rewritten, and the old copy is preserved as .bak. That .bak detail is exactly the reassurance an agent needs before a destructive call. It lacks auth/prerequisite notes and error behavior, keeping it out of 5 territory.
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?
Three short sentences, front-loaded with the action and its effect, then the retention and backup guarantees. No filler and nothing repeated from the schema.
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 single-param destructive mutation with no output schema, the description covers what changes, what is preserved, and what is backed up. The remaining gap is only the return/confirmation behavior and failure modes, which are minor here.
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 100% and the single `entry` parameter is fully documented in the schema with format and example ('greenhouse:stripe'). The description adds no further parameter detail, so the baseline 3 applies.
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?
Specific verb+resource ('Take a board off the watchlist') with the downstream effect named ('so fetch_jobs stops checking it'). It is clearly the inverse of the sibling add_board, so an agent can distinguish them at a glance.
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 effect statement ('fetch_jobs stops checking it') implies when to reach for it versus add_board/fetch_jobs, and it clarifies the data-retention condition. It stops short of an explicit when-not (e.g., what to do if the entry is absent) or naming an alternative, but the context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_application_packageADestructive
Keep what was sent with an application, as copies: files (local paths to the resume PDF, cover letter... exactly as uploaded), answers (the form's questions and the answers given, [{question, answer}]; replaces any saved before) and note (a cover letter or message pasted into the form). Call it once the person has submitted, with what they actually sent; get_application_package reads it back.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| note | No | A cover letter or message pasted into the form. | |
| files | No | Local paths to the files exactly as uploaded (resume PDF, cover letter...). Copies are kept. | |
| answers | No | The form's questions and the answers given, as [{"question": ..., "answer": ...}]. Replaces any saved before. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and readOnlyHint=false. The description adds useful context beyond them: files are kept 'as copies' (not moved), and answers 'replace any saved before', clarifying partial-overwrite semantics. It does not cover auth or error behavior, but the added nuance is real.
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?
It is a single dense sentence with parenthetical glosses for each parameter, front-loading the purpose before the usage instruction. The nested parentheses make it slightly awkward, but every clause carries information.
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 destructive save tool with no output schema, the description covers what is stored, when to call it, and how to read it back. It omits what the call returns (e.g. a confirmation or the saved key), which would round it out, but nothing critical is 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 description coverage is 100%, so the schema already documents all four parameters well. The description largely restates the same parameter meanings ('exactly as uploaded', 'replaces any saved before'), adding little beyond what the schema already provides.
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 states a specific verb and resource: keeping copies of what was sent with an application (files, answers, note). It explicitly contrasts with the read counterpart, get_application_package, so an agent can distinguish it from its closest sibling without opening either schema.
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?
It gives a clear timing condition ('Call it once the person has submitted, with what they actually sent') and names the read alternative ('get_application_package reads it back'). It does not spell out when not to call it (e.g. before submission is complete), but the context is strong.
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.
17 tool updates
v0.3.0- Added
add_board - Removed
application_package - Removed
applications - Removed
apply_queue - Removed
digest - Added
get_application_package - Added
get_digest - Added
get_interview_prep - Added
get_job - Removed
interview_prep - Removed
job_details - Added
list_applications - Added
list_boards - Added
list_queued_jobs - Added
list_skill_gaps - Added
remove_board - Removed
skill_gaps
11 tool updates
v0.2.3- Changed
add_application9 fields changed- added
Input schema / properties / applied_on / descriptionAdded value: +"The day applied (YYYY-MM-DD), if not today." - added
Input schema / properties / company / descriptionAdded value: +"The company; may be left out when url is a job link it can read." - added
Input schema / properties / follow_up / descriptionAdded value: +"A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it." - added
Input schema / properties / next_step / descriptionAdded value: +"What happens next (\"hiring manager call Friday\")." - added
Input schema / properties / note / descriptionAdded value: +"A note: who referred them, how they found it..." - added
Input schema / properties / status / descriptionAdded value: +"applied (the default; only once the person has applied themselves), queued for one they're considering, or a later stage such as interviewing." - added
Input schema / properties / text / descriptionAdded value: +"The posting's text, pasted, when the link can't be read, so it can be scored and prepped." - added
Input schema / properties / title / descriptionAdded value: +"The job title; may be left out when url is a job link it can read." - added
Input schema / properties / url / descriptionAdded value: +"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling or LinkedIn are read in full; any other link is just kept."
- Changed
application_package1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
applications1 field changed- added
Input schema / properties / due_only / descriptionAdded value: +"Only those whose follow-up day has come."
- Changed
digest6 fields changed- added
Input schema / properties / include_seen / descriptionAdded value: +"Also include jobs already shown in an earlier digest, not just new ones." - added
Input schema / properties / limit / descriptionAdded value: +"The most jobs to return, best first." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / mark_shown / descriptionAdded value: +"Mark the returned jobs as shown, so the next digest leaves them out. False to peek without changing anything." - added
Input schema / properties / score_top / descriptionAdded value: +"How many of the most relevant unscored jobs to fit-score against the resume with shortlist-ai first. 0 (the default) skips scoring; each job takes minutes on the local backend, so keep it small." - added
Input schema / properties / score_top / minimumAdded value: +0
- Changed
find_board1 field changed- added
Input schema / properties / company / descriptionAdded value: +"A company name (\"Stripe\"), or a link to one of its job postings or its careers page."
- Changed
interview_prep1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
job_details1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
list_jobs2 fields changed- changed
Input schema / properties / status / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "new", + "shown", + "queued", + "applied", + "screening", + "interviewing", + "offer", + "rejected", + "withdrawn", + "skipped" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / status / descriptionAdded value: +"Only jobs with this status; omit for all."
- Changed
mark_job10 fields changed- added
Input schema / properties / add_note / descriptionAdded value: +"A line to add to the note, dated today, keeping what's there (\"recruiter replied: onsite only\")." - added
Input schema / properties / applied_on / descriptionAdded value: +"The day applied (YYYY-MM-DD), if not today." - added
Input schema / properties / follow_up / descriptionAdded value: +"A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it." - added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys." - added
Input schema / properties / next_step / descriptionAdded value: +"What happens next (\"recruiter screen Tuesday\"). An empty string clears it." - added
Input schema / properties / note / descriptionAdded value: +"Replaces the whole note. Prefer add_note for news." - changed
Input schema / properties / status / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "new", + "shown", + "queued", + "applied", + "screening", + "interviewing", + "offer", + "rejected", + "withdrawn", + "skipped" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / status / descriptionAdded value: +"The new status; omit to keep it and only update the rest. applied only after the person has submitted the application themselves." - added
Input schema / properties / text / descriptionAdded value: +"The posting's text, pasted (found later, or a copy once the posting is gone), so it can be scored and prepped." - added
Input schema / properties / url / descriptionAdded value: +"The link of a job added by hand: its posting, or the company's careers site once the posting is gone."
- Changed
save_application_package4 fields changed- added
Input schema / properties / answers / descriptionAdded value: +"The form's questions and the answers given, as [{\"question\": ..., \"answer\": ...}]. Replaces any saved before." - added
Input schema / properties / files / descriptionAdded value: +"Local paths to the files exactly as uploaded (resume PDF, cover letter...). Copies are kept." - added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys." - added
Input schema / properties / note / descriptionAdded value: +"A cover letter or message pasted into the form."
- Changed
skill_gaps2 fields changed- changed
Input schema / properties / timeline / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "week", + "month", + "quarter", + "any" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / timeline / descriptionAdded value: +"How soon the person wants to close a gap: week, month, quarter or any. Omit for the watchlist's learning.timeline."
14 tool updates
v0.1.0- First observed
add_application - First observed
application_package - First observed
applications - First observed
apply_queue - First observed
check_postings - First observed
digest - First observed
fetch_jobs - First observed
find_board - First observed
interview_prep - First observed
job_details - First observed
list_jobs - First observed
mark_job - First observed
save_application_package - First observed
skill_gaps
TDQS
Scored across 17 tools
Each tool has a clearly distinct purpose: boards, jobs, applications, and prep are cleanly separated. Descriptions explicitly cross-reference sibling tools and state when to use which (e.g., 'for jobs already queued use list_queued_jobs'), leaving no ambiguity.
Strong verb_noun pattern (add_board, fetch_jobs, get_digest, list_applications, mark_job), with only minor deviations like check_postings (noun-first) and get_interview_prep being slightly longer. The convention is predictable overall.
17 tools is on the high side for a job-tracking server; the domain is broad (boards, jobs, applications, interview prep, skill gaps), so most tools are justified, but it borders on heavy and some lifecycle operations could be consolidated.
Covers the full lifecycle: discover boards, fetch jobs, queue/apply, track status, save application packages, prep for interviews, and analyze skill gaps. Minor gaps exist (e.g., no explicit delete of applications or bulk import), but core workflows are well covered.
Maintenance
Related MCP Connectors
Analyze job listings against your resume, track applications, and generate cover letters.
Your personal career coach. Scanning jobs for you, daily.
HireHeat Jobs: search jobs on 12,000+ company career sites (Greenhouse, Ashby, Workable…).
HireHeat Jobs: search jobs on 12,000+ company career sites (Greenhouse, Ashby, Workable…).
Related MCP Servers
- AlicenseBqualityCmaintenanceProvides tools to search & auto-apply to jobs directly on company websites, generate custom resumes, get contacts of recruiters and referrals and track applications easily3568 npm25MIT
- AlicenseAqualityAmaintenanceScans 130+ company careers pages and scores every role against your resume with an LLM (0–100), surfacing top matches. Drafts tailored cover letters and resume bullets for any job on demand, and exports scan results to CSV.366 PyPI213MIT
- FlicenseAqualityDmaintenanceAutomates job outreach by finding companies, discovering contacts, generating personalized emails with AI, and tracking campaigns.9-
- AlicenseNot gradedqualityAmaintenanceEnables users to discover applicant tracking system job boards from company domains, list open roles, detect hiring changes over time, and generate hiring summaries across multiple ATS platforms.MIT