A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API
jobctl is installed from its publisher's own source and answers where it runs, so this marketplace is not in the path of a single call. There is no address here to send one to, and a panel that pretended otherwise would be showing you an answer we made up. Install it and call it from your own client — the Installation tab has the entry for each one.
What it does
Job application tracker for developers - AI agents write over MCP, you review in a dashboard.
Quickstart
# 1 — add it to Claude Code
claude mcp add --scope user --transport http jobctl-mcp https://app.jobctl.app/mcp
# 2 — ask your agent for something these tools do
# add_application, list_applications, update_application and 8 more
jobctl costs nothing on mcprush: there is no plan to choose here, no cap to set and nothing mcprush can bill you for.
Collected from a public index. Nobody has claimed this account, so nothing here was written by its author — claim it if it is yours.
Where are you running it?
Every route below installs the same thing and ends at the same approval screen. Nothing here runs on your machine and nothing runs on ours: this server answers at its publisher’s own address, and what you install is the connection straight to it.
This is a public server: it answers at its publisher’s own address and this marketplace is not in the path. Claude Code registers it in one command; --scope user makes it available in every project. The transport below is http, as the publisher's own manifest declares it.
claude mcp add --scope user --transport http jobctl-mcp https://app.jobctl.app/mcpReconnect, or start a new session, and the tools appear in the model’s tool list.
One config entry pointing straight at the publisher’s own address — this marketplace is not in the path, and nothing from this listing executes on your machine.
11 tools, with what each one reads, writes and reaches shown before you agree — the same list on every route above. Read the tool surface.
Tool surface
What the model actually sees. Descriptions are diffed on every release — see version history.
Track a new job application. Pass either a single raw line — add_application({raw: "Bosch, Tech Lead, prio A, due friday, remote, via LinkedIn"}) — or structured fields (company and role required then). Returns the created application and possible-duplicate warnings; if duplicates are listed, tell the user instead of creating again.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| raw | string | no | Free-form line: "Company, Role, prio A|B|C, due <date>, remote|hybrid|onsite, via <source>, https://…, in <location>, applied <date>" |
| company | string | no | — |
| role | string | no | — |
| status | string | no | — |
| priority | string | no | A = top priority |
| remote | string | no | — |
| remote_note | string | no | e.g. "2 days office" |
| source | string | no | LinkedIn, referral, recruiter, Easy Apply… |
| url | string | no | Link to the job posting |
| location | string | no | — |
| salary_asked | integer | no | What the candidate asked for — yearly gross EUR as a plain number, e.g. 110000 |
| salary_range_min | integer | no | Posting salary range lower bound — yearly gross EUR, plain number |
| salary_range | integer | no | Posting salary range upper bound — yearly gross EUR, plain number |
| cv_variant | string | no | Which CV was sent: DE, EN, AI-focused… |
| match_notes | string | no | Markdown match assessment: why the candidate fits this role — strengths vs requirements, gaps, level/salary advice, process notes. Save your vacancy analysis here so it is not lost; shown as an expand |
| next_interview_at | string | no | ISO datetime, e.g. 2026-07-20T14:00:00+02:00 |
| next_action | string | no | e.g. "follow-up", "thank-you email" |
| next_action_due | string | no | ISO date YYYY-MM-DD |
| applied_at | string | no | ISO date YYYY-MM-DD |
List job applications. Filter by view (active = default working set, archive = rejected/withdrawn/no-response), status list, priority, or free-text search in company/role. Example: list_applications({view: "active"}), list_applications({q: "bosch"}).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| view | string | no | — |
| status | string | no | Comma-separated: started_apply, waiting_referral, applied, waiting, interview, offer, accepted, rejected, no_response, on_hold, withdrawn, archived |
| priority | string | no | — |
| q | string | no | Search in company/role |
| limit | integer | no | — |
Update fields of an application (get the id from list_applications). Status changes are logged to the timeline automatically. Example: update_application({id: "…", status: "interview", next_action: "prepare system design", next_action_due: "2026-07-20"}).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| company | string | no | — |
| role | string | no | — |
| status | string | no | — |
| priority | string | no | A = top priority |
| remote | string | no | — |
| remote_note | string | no | e.g. "2 days office" |
| source | string | no | LinkedIn, referral, recruiter, Easy Apply… |
| url | string | no | Link to the job posting |
| location | string | no | — |
| salary_asked | integer | no | What the candidate asked for — yearly gross EUR as a plain number, e.g. 110000 |
| salary_range_min | integer | no | Posting salary range lower bound — yearly gross EUR, plain number |
| salary_range | integer | no | Posting salary range upper bound — yearly gross EUR, plain number |
| cv_variant | string | no | Which CV was sent: DE, EN, AI-focused… |
| match_notes | string | no | Markdown match assessment: why the candidate fits this role — strengths vs requirements, gaps, level/salary advice, process notes. Save your vacancy analysis here so it is not lost; shown as an expand |
| next_interview_at | string | no | ISO datetime, e.g. 2026-07-20T14:00:00+02:00 |
| next_action | string | no | e.g. "follow-up", "thank-you email" |
| next_action_due | string | no | ISO date YYYY-MM-DD |
| applied_at | string | no | ISO date YYYY-MM-DD |
Append a free-text note to an application timeline — recruiter call summaries, interview instructions, pasted messages. Multiline markdown is fine. Example: add_note({application_id: "…", text: "Recruiter: team of 5, on-call rotation, offer range 85-95k"}).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| application_id | string | yes | — |
| text | string | yes | — |
Log an interview for an application (max 10 per application): when it takes place, its status (planned or done), who attends (each with an optional profile link), related links (prep materials the company sent, meeting URL), and a short recap of what was discussed. Also keeps the application's next-interview date in sync. Example: `log_interview({application_id: "…", scheduled_at: "2026-07-20T14:0
| Parameter | Type | Required | Notes |
|---|---|---|---|
| application_id | string | yes | — |
| scheduled_at | string | yes | ISO datetime with offset, e.g. 2026-07-20T14:00:00+02:00 |
| status | string | no | planned (default) or done |
| attendees | array | no | Who attends, each with an optional profile link |
| links | array | no | Related links: prep materials, meeting URL, docs |
| recap | string | no | Short recap of what was discussed |
What is burning today: applications with next_action_due today or overdue. Call this when the user asks "what should I do today?" about their job search.
No parameter schema on file.
What is actually SCHEDULED: interviews with their time, attendees and meeting links, plus the actions falling due, for today, tomorrow, or the next seven days. Use this whenever the user asks what is planned, what the day or week looks like, or before proposing a time to anyone — get_due only knows action deadlines and is blind to booked interviews. Example: get_planned({range: "tomorrow"}).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| range | string | no | today (default), tomorrow, or week (today plus the next 6 days) |
Attach a markdown company analysis (research you produced) to an application. Single document per application — a new call REPLACES the previous one. Max 100000 bytes (~100 KB) of utf-8. The user reads it in the dashboard, e.g. before an interview. Example: attach_analysis({application_id: "…", markdown: "# Bosch ## Culture…"}).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| application_id | string | yes | — |
| markdown | string | yes | The analysis as markdown |
Attach or replace a file on an application so the user sees it in the dashboard: a CV/resume (kind: 'cv') or a cover letter (kind: 'cover_letter'). Pass the file bytes as base64 in data_base64. One file per (application, kind) - a new call REPLACES the previous one. Max ~5 MB; pdf/doc/docx/txt/md (MIME is inferred from the filename if you omit it). Call this whenever you generate a tailored CV or
| Parameter | Type | Required | Notes |
|---|---|---|---|
| application_id | string | yes | — |
| kind | string | yes | — |
| filename | string | yes | — |
| data_base64 | string | yes | Base64-encoded file bytes |
| mime | string | no | Optional; inferred from the filename extension when omitted |
Attach prep material to a specific interview so the user sees it next to that round in the dashboard: the prep document you wrote, the job description, a deck, notes the company sent. Max 3 files per interview, 20000000 bytes (20 MB) each; pass the bytes as base64. Get interview ids from get_application. Example: `attach_interview_file({application_id: "…", interview_id: "…", filename: "prep-round
| Parameter | Type | Required | Notes |
|---|---|---|---|
| application_id | string | yes | — |
| interview_id | string | yes | — |
| filename | string | yes | — |
| data_base64 | string | yes | Base64-encoded file bytes |
| mime | string | no | Optional; inferred from the filename extension when omitted |
Full detail of one application: all fields, contacts, recent timeline events, and whether a company analysis is attached (fetch it via the dashboard or attach_analysis to replace).
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
- Every tool — any call limit is its publisher’s, not ours
- No card, and mcprush charges nothing for it
- Runs at its publisher’s own address — this marketplace is not in the path
- Nothing to cap, because mcprush bills nothing
What counts against your monthly calls
| Tool | Unit | Calls used | Out of the allowance |
|---|
Nothing here is billable: mcprush charges nothing to install jobctl or to call it, at any volume.
Two independent axes, because powerful and malicious are different questions. The grade is threat only. The capability level is blast radius, and it is never a penalty on the grade — it is priced as one subtract-only term in the score, where you can see it.
This listing is an address its publisher runs, and you connect to it directly — this marketplace is not in the path. The scanner reads packages and public source, and an address is neither. So there is no grade — not a withheld one, an unmeasured one.
Release history
This is an address its publisher runs: which release it serves is theirs to choose, so there is nothing here to pin. The history below is for reading; the current release on file is 0.5.1.
No release note was published with this version.
One review per account, from a signed-in account that does not publish this listing. Nothing else is asked — you can say what you think before you install it. Publishers can reply once per review, and a review can be edited or deleted by whoever wrote it.
Any signed-in account that does not publish jobctl can review it, once — before installing it or after. A review from an account that has installed it is marked as one.
Nobody has reviewed this listing. The rating on the card is the mean of the reviews written here and nothing else, so there is no rating until somebody writes the first — which takes a signed-in account that does not publish it, and nothing else.