Skip to content

jobctl

by DmytroRybka · remote · no sign-in to list tools · v0.5.1 · published by GitHub user DmytroRybka

Job application tracker for developers - AI agents write over MCP, you review in a dashboard.

Deletes · 2Changes · 5

11 tools: 2 can delete or cancel things, 5 change things and 4 only read.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http jobctl https://app.jobctl.app/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "log_interview" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false}; The name "log_interview" says "log": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

11 tools

Deletes or cancels 2Claude Code: deny
  • attach_analysisAttach a markdown company analysis (research you produced) to an application.No findings

    Why it is in this group

    • The name "attach_analysis" says "attach": a word for a change.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    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\n\n## Culture…"})`.

    Annotations the server declares

    • title: Attach company analysis
    • readOnlyHint: false
    • destructiveHint: true
  • attach_fileAttach 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').No findings

    Why it is in this group

    • The name "attach_file" says "attach": a word for a change.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    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 cover letter for an application. Example: `attach_file({application_id: "…", kind: "cv", filename: "CV_Cursor.pdf", data_base64: "JVBERi0…"})`.

    Annotations the server declares

    • title: Attach CV or cover letter
    • readOnlyHint: false
    • destructiveHint: true
Changes things 5Claude Code: ask
  • add_applicationTrack a new job application.No findings

    Why it is in this group

    • The name "add_application" says "add": a word for a change.
    Description, as the server wrote it
    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.

    Annotations the server declares

    • title: Add application
    • readOnlyHint: false
    • destructiveHint: false
  • add_noteAppend a free-text note to an application timeline — recruiter call summaries, interview instructions, pasted messages.No findings

    Why it is in this group

    • The name "add_note" says "add": a word for a change.
    Description, as the server wrote it
    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"})`.

    Annotations the server declares

    • title: Add note
    • readOnlyHint: false
    • destructiveHint: false
  • attach_interview_fileAttach 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 se…No findings

    Why it is in this group

    • The name "attach_interview_file" says "attach": a word for a change.
    Description, as the server wrote it
    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-round2.md", data_base64: "IyBQcmVw…"})`.

    Annotations the server declares

    • title: Attach interview prep file
    • readOnlyHint: false
    • destructiveHint: false
  • log_interviewLog 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 (pr…1 finding

    Why it is in this group

    • The name "log_interview" says "log": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "log_interview" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false}; The name "log_interview" says "log": a word for reading.

      What this check looks for
    Description, as the server wrote it
    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:00:00+02:00", status: "planned", attendees: [{name: "Anna Weber (HR)", url: "https://linkedin.com/in/annaweber"}], links: [{label: "Prep materials", url: "https://company.com/interview-prep"}], recap: "System design round"})`.

    Annotations the server declares

    • title: Log interview
    • readOnlyHint: false
    • destructiveHint: false
  • update_applicationUpdate fields of an application (get the id from list_applications).No findings

    Why it is in this group

    • The name "update_application" says "update": a word for a change.
    Description, as the server wrote it
    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"})`.

    Annotations the server declares

    • title: Update application
    • readOnlyHint: false
    • destructiveHint: false
Only reads 4Claude Code: allow
  • get_applicationFull 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).No findings

    Why it is in this group

    • The name "get_application" says "get": a word for reading.
    Description, as the server wrote it
    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).

    Annotations the server declares

    • title: Get application
    • readOnlyHint: true
  • get_dueWhat is burning today: applications with next_action_due today or overdue.No findings

    Why it is in this group

    • The name "get_due" says "get": a word for reading.
    Description, as the server wrote it
    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.

    Annotations the server declares

    • title: Due actions
    • readOnlyHint: true
  • get_plannedWhat is actually SCHEDULED: interviews with their time, attendees and meeting links, plus the actions falling due, for today, tomorrow, or the next seven days.No findings

    Why it is in this group

    • The name "get_planned" says "get": a word for reading.
    Description, as the server wrote it
    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"})`.

    Annotations the server declares

    • title: Planned schedule
    • readOnlyHint: true
  • list_applicationsList job applications.No findings

    Why it is in this group

    • The name "list_applications" says "list": a word for reading.
    Description, as the server wrote it
    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"})`.

    Annotations the server declares

    • title: List applications
    • readOnlyHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.5.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http jobctl https://app.jobctl.app/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__jobctl__list_applications",
      "mcp__jobctl__get_due",
      "mcp__jobctl__get_planned",
      "mcp__jobctl__get_application"
    ],
    "ask": [
      "mcp__jobctl__add_application",
      "mcp__jobctl__update_application",
      "mcp__jobctl__add_note",
      "mcp__jobctl__log_interview",
      "mcp__jobctl__attach_interview_file"
    ],
    "deny": [
      "mcp__jobctl__attach_analysis",
      "mcp__jobctl__attach_file"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as jobctl. Review it before you use it.