# Job Tracker (mcpb · job-tracker-0.3.3.mcpb)

Local job-search tracker: roles, a status machine with evidence, rules, interviews, daily reports.

- Trust score: 35/100 (low)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-10-24

## Components

- mcpb · `job-tracker-0.3.3.mcpb`: 35/100 (this document), [markdown](https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker.md), [page](https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker)

## Channel facts

- Registry: `mcpb`
- Package: `https://github.com/adamwardecki/job-hunt-mcp/releases/download/v0.3.3/job-tracker-0.3.3.mcpb`
- Version: `0.3.3`
- Transport: `stdio`
- SHA-256: `d1cf80fdbd48e4a5a15d07792aa450ad4ae1e925367dd4ec1f5cad56ea45bcb9`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-10-24.

- **Supply Chain Security**: 13/100
  - No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.
  - Known CVEs could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).
  - No install/post-install scripts declared.
  - Dependency health could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).
- **Provenance & Transparency**: 19/100
  - Repository check failed: the declared repository URL redirects; it must resolve directly.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 3 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 68/100
  - AI-judged instruction clarity (good).
  - Tool/resource definitions use about 2681 tokens (~83/item across 32 items; 32 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "check_pay" implies "pay" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 33 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 60/100
  - Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the Job Tracker MCP server?

Job Tracker ships as an MCPB bundle, a single file you download and open in an MCP host that supports MCPB bundles, such as Claude Desktop. The host reads the launch command from the bundle's own manifest, so there is no command to copy. Before opening it, check the file's SHA-256 matches the one the MCP registry declares for it, d1cf80fdbd48e4a5a15d07792aa450ad4ae1e925367dd4ec1f5cad56ea45bcb9; the commands to do that are on this page. If it does not match, do not open it.

- Download bundle: `https://github.com/adamwardecki/job-hunt-mcp/releases/download/v0.3.3/job-tracker-0.3.3.mcpb`
- SHA-256: `d1cf80fdbd48e4a5a15d07792aa450ad4ae1e925367dd4ec1f5cad56ea45bcb9`

### Verify on macOS / Linux

```bash
echo "d1cf80fdbd48e4a5a15d07792aa450ad4ae1e925367dd4ec1f5cad56ea45bcb9  job-tracker-0.3.3.mcpb" | shasum -a 256 -c
```

### Verify on Windows (PowerShell)

```powershell
(Get-FileHash -Algorithm SHA256 .\job-tracker-0.3.3.mcpb).Hash -eq "d1cf80fdbd48e4a5a15d07792aa450ad4ae1e925367dd4ec1f5cad56ea45bcb9"
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-21 (score 35)

First indexed and scored.

## MCP tools (32)

### `setup_status` (~26 tokens)

Checklist of what is configured, missing or degraded. Call at the start of every run.

### `record_setup_decision` (~59 tokens)

Record the user decision for an amber setup item (e.g. "no browser, accepted"), so setup can complete.

Input parameters:

- `decision` (string, required): The user's decision, in their words
- `key` (string, required): setup_status item key

### `start_run` (~84 tokens)

Start a run and record detected capabilities (connectors, browser, local folder). Returns run_id.

Input parameters:

- `capabilities` (object, required): {connectors: {gmail, calendar, linkedin}, browser: "claude-in-chrome" | "built-in" | null, local_folder: bool}
- `kind` (string, required): sweep | apply | triage | setup | calibration

### `finish_run` (~38 tokens)

Close a run with a one-paragraph summary.

Input parameters:

- `run_id` (integer, required): From start_run
- `summary` (string): What happened

### `get_profile` (~28 tokens)

All config sections: filters, prefs, writing, accounts, autonomy, schedule, sources, capabilities.

### `save_config` (~72 tokens)

Validate and save one config section. Unknown fields are rejected. Field names and types are in templates/settings.example.yaml; an invalid call returns the section's expected fields.

Input parameters:

- `data` (object, required): Section contents
- `section` (string, required): filters | prefs | writing | accounts | autonomy | schedule | sources | capabilities

### `get_document` (~42 tokens)

Read a user document: profile (CV distilled), stories, reusable-answers, voice.

Input parameters:

- `name` (string, required): profile | stories | reusable-answers | voice

### `save_document` (~39 tokens)

Save a user document (markdown).

Input parameters:

- `content` (string, required): Markdown
- `name` (string, required): profile | stories | reusable-answers | voice

### `find_company` (~73 tokens)

Dedupe check. Fuzzy match on name, aliases, domain and ATS slug. verdict: new | seen | skip (live application, same posting, or no_cold_apply).

Input parameters:

- `domain` (string): Website domain
- `name` (string): Company name
- `url` (string): Posting URL

### `set_no_cold_apply` (~64 tokens)

Mark a company as no_cold_apply (an intro or recruiter process is open), or clear it.

Input parameters:

- `company_id` (integer, required): Company id
- `on` (boolean): true to set, false to clear
- `reason` (string): Why

### `add_alias` (~46 tokens)

Add an alias to a company (brand, former name, parent) so dedupe catches it.

Input parameters:

- `alias` (string, required): Alias
- `company_id` (integer, required): Company id

### `upsert_role` (~286 tokens)

Create or update a role (creates the company if needed). New roles start as found. Returns the dedupe result for new roles.

Input parameters:

- `ats` (string): ashby | greenhouse | lever | workable | teamtailor | personio | join | workday | other
- `comp_currency` (string): ISO currency code
- `comp_max` (number): Band maximum
- `comp_min` (number): Band minimum
- `comp_period` (string): year | month | day | hour
- `company` (string): Company name as the employer writes it
- `company_aliases` (array): Other names, e.g. a brand vs the legal entity
- `company_domain` (string): Employer website domain
- `equity` (string): Equity as stated
- `id` (integer): Existing role id to update
- `industry` (string): Industry of the business line the role sits in
- `location_line` (string): Verbatim location line from the employer ATS
- `location_type` (string): remote | hybrid | onsite | unknown
- `posted_at` (string): Posting date if shown
- `source` (string): Where the lead came from
- `stack` (string): Stack as stated
- `title` (string, required): Role title, verbatim
- `url` (string): Posting URL (employer ATS preferred)

### `get_role` (~31 tokens)

Role with its company, full event history, artifacts and interviews.

Input parameters:

- `role_id` (integer, required): Role id

### `transition` (~313 tokens)

Move a role through found → verified → scored → queued → applied → interviewing → offer (dropped from found/verified/scored/queued; closed from queued/applied/interviewing/offer). Rejects illegal moves. verified needs evidence (URL + verbatim location line), location_line and location_type. dropped needs evidence (quote or rule:<id>). applied needs the confirmation text. closed needs outcome.

Input parameters:

- `blocked_by` (string): For queued: browser | user | login | captcha | other
- `category` (string): For drops: location | pay | industry | role_shape | stack | culture | duplicate | gated | other
- `evidence` (string): Verbatim quote with URL, rule:<id>, or confirmation text
- `location_line` (string): verified only: verbatim from the ATS
- `location_type` (string): verified only: remote | hybrid | onsite | unknown
- `outcome` (string): rejected | withdrawn | role_closed (closed only)
- `question` (string): For queued: the single blocking question for the user
- `reason` (string, required): Why, one sentence
- `role_id` (integer, required): Role id
- `run_id` (integer): Current run id
- `score` (number): scored only: 0 to 10
- `score_notes` (string): scored only: short notes, including gaps kept internal
- `to` (string, required): found | verified | scored | queued | applied | interviewing | offer | dropped | closed

### `record` (~181 tokens)

Append a validated event without the state-machine check: outcomes from outside (rejection, invite, user decision) or a note (omit status).

Input parameters:

- `actor` (string, required): user | employer | pipeline
- `blocked_by` (string): browser | user | login | captcha | other
- `category` (string): Drop category
- `evidence` (string): Verbatim quote, feedback, or URL
- `outcome` (string): rejected | withdrawn | role_closed
- `question` (string): Blocking question for the user (shown under Needs you until a later event)
- `reason` (string, required): Why
- `role_id` (integer, required): Role id
- `run_id` (integer): Current run id
- `status` (string): found | verified | scored | queued | applied | interviewing | offer | dropped | closed (omit for a note)

### `check_pay` (~127 tokens)

Deterministic pay-floor check. Drops only if the band maximum is below the floor; straddling bands are kept and flagged. Pass fx_rate when the currency differs from the floor (look it up, never guess).

Input parameters:

- `comp_max` (number): Band maximum
- `comp_min` (number): Band minimum
- `currency` (string, required): ISO code
- `equity` (string): Equity, if any
- `fx_rate` (number): Floor-currency units per 1 unit of currency
- `period` (string): year | month | week | day | hour

### `gate_check` (~42 tokens)

Pre-submit check: role verified, dedupe clean, not no_cold_apply, no live application at the company.

Input parameters:

- `role_id` (integer, required): Role id

### `add_artifact` (~110 tokens)

Save a cover note, PDF, Gmail draft id, form answers, confirmation or note. Prose is linted. gmail_draft stays unverified until verify_artifact.

Input parameters:

- `content` (string): Text content
- `kind` (string, required): cover_note | cover_letter_pdf | gmail_draft | form_answers | confirmation | note
- `ref` (string): Path, URL or Gmail draft id
- `role_id` (integer): Role id (omit for drafts not tied to a role)

### `list_artifacts` (~91 tokens)

Artifacts for a run, a local day or a role, with lint results and read-back state. The auditor uses this.

Input parameters:

- `date` (string): YYYY-MM-DD, a day in filters.timezone (ignored when run_id is given)
- `kind` (string): Artifact kind
- `role_id` (integer): Role id
- `run_id` (integer): Artifacts from this run

### `verify_artifact` (~61 tokens)

Mark an artifact verified after reading it back. For gmail_draft, readback must be the get_draft/list_drafts output containing the draft id.

Input parameters:

- `artifact_id` (integer, required): Artifact id
- `readback` (string, required): Read-back output

### `lint_prose` (~56 tokens)

Lint outbound prose: em/en dashes, "not X but Y", fake-candid openers, volunteered gaps, length.

Input parameters:

- `max_words` (integer): Word limit
- `text` (string, required): Text to lint

### `open_items` (~47 tokens)

Queue (fresh and stale), unverified drafts, interviews to book, upcoming interviews.

Input parameters:

- `stale_after_days` (integer): Queue items untouched this long are listed as stale (default 14)

### `pipeline_summary` (~36 tokens)

Counts by status, live processes, rejections, queue (fresh and stale).

Input parameters:

- `stale_after_days` (integer): Default 14

### `add_rule` (~69 tokens)

Add a user preference or correction as a rule, with reason and example.

Input parameters:

- `added_by` (string): user | pipeline
- `example` (string): Concrete example
- `reason` (string, required): Why (the incident or the user words)
- `text` (string, required): The rule, imperative

### `list_rules` (~26 tokens)

Active rules with provenance.

Input parameters:

- `include_inactive` (boolean): Include deactivated rules

### `deactivate_rule` (~22 tokens)

Deactivate a rule.

Input parameters:

- `id` (integer, required): Rule id

### `source_health` (~17 tokens)

Per-source status, consecutive failures, yield.

### `set_source_status` (~75 tokens)

Record a source result for this run. Three consecutive failures mark it degraded.

Input parameters:

- `applied` (integer): Applications from it
- `error` (string): Error text
- `found` (integer): Leads found
- `name` (string, required): Source name
- `status` (string, required): ok | degraded | failed | disabled

### `add_interview` (~115 tokens)

Record an interview (or a booking link still to book: omit starts_at). Moves the role to interviewing.

Input parameters:

- `booked_by` (string): user | employer
- `link` (string): Booking or meeting link
- `notes` (string): Notes
- `people` (string): Interviewers
- `role_id` (integer, required): Role id
- `stage` (string, required): Stage name
- `starts_at` (string): ISO datetime, omit if not booked yet
- `tz` (string): IANA timezone

### `render_report` (~97 tokens)

Markdown daily report. With run_id it covers that run; otherwise the local day. Lead with the outcome via headline. Only read-back drafts and confirmed submissions are claimed.

Input parameters:

- `date` (string, required): YYYY-MM-DD, a day in filters.timezone (report title; ignored for scope when run_id is given)
- `headline` (string): One or two sentences: the outcome
- `run_id` (integer): Run id (preferred)

### `audit` (~86 tokens)

Post-run rule check for a run (preferred) or a local day: excluded industries, drops without evidence, applied without confirmation, prose lint, drafts not read back, no_cold_apply. Pass run_id or date.

Input parameters:

- `date` (string): YYYY-MM-DD, a day in filters.timezone (ignored when run_id is given)
- `run_id` (integer): Run id

### `import_legacy` (~113 tokens)

One-off import of the manual pipeline: applied-log.md, outreach-preferences.md, queue/*.md, and user documents. Pass the contents, or path to a local pipeline/ folder.

Input parameters:

- `applied_log` (string): applied-log.md contents
- `documents` (object): {profile, stories, "reusable-answers"} markdown
- `path` (string): Local path to the pipeline/ folder
- `preferences` (string): outreach-preferences.md contents
- `queue` (array): Queue notes

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker#diagnostics

## Score history

- 2026-10-24: 35
- 2026-10-23: 35
- 2026-10-22: 35
- 2026-10-21: 35

## Common questions

### What is the Job Tracker MCP server?

Job Tracker is an MCP server listed in the public MCP registry as io.github.adamwardecki/job-tracker. Local job-search tracker: roles, a status machine with evidence, rules, interviews, daily reports. This page covers its MCPB bundle (https://github.com/adamwardecki/job-hunt-mcp/releases/download/v0.3.3/job-tracker-0.3.3.mcpb).

### Is the Job Tracker MCP server safe to use?

Job Tracker scores 35 out of 100 on VerifyMCP. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Job Tracker MCP server expose?

Job Tracker exposes 32 tools: setup_status, record_setup_decision, start_run, finish_run, get_profile, and 27 more. Their descriptions and schemas cost roughly 2,572 tokens of context every time the server is loaded.

### What licence is the Job Tracker MCP server under?

Job Tracker declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- Website: https://jobtrackermcp.com/
- Changelog RSS feed: https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker.xml
- Changelog JSON feed: https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker.json
- HTML version of this page: https://verifymcp.io/servers/adamwardecki-job-tracker/job-tracker
