job-tracker
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| JOB_RESUMES_DIR | No | Directory for generated resumes and documents. Defaults to a Resumes folder next to the tracker file. | |
| JOB_TRACKER_FILE | No | Path to the Job_Tracking.xlsx file (tracker). Defaults to <home>\Documents\Job_Tracking.xlsx. | |
| JOB_DISCOVERY_FILE | No | Path to the Job_Search_Discovery.xlsx file (discovery). Defaults to Job_Search_Discovery.xlsx next to the tracker file. | |
| JOB_GMAIL_TOKEN_FILE | No | Path to the Gmail token file (gmail_token.json). Defaults to gmail_token.json in the project root. | |
| JOB_RESUME_MASTER_FILE | No | Path to resume_master.json, the stable resume facts file. Defaults to a sibling of the tracker file. | |
| JOB_INTERVIEW_PREP_FILE | No | Path to the Interview_Prep_QA.md file. Defaults to Interview_Prep_QA.md next to the tracker file. | |
| JOB_GMAIL_CREDENTIALS_FILE | No | Path to the Gmail OAuth client credentials.json file. Defaults to credentials.json in the project root. |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_jobsA | List all tracked job applications, with optional filters. Filter by status (case-insensitive exact match), company (case-insensitive substring), and/or a Date Applied range (inclusive, YYYY-MM-DD). |
| get_jobA | Return full details for a single application, matched by company (and position, if the company has more than one row). |
| add_jobA | Append a new job application row. Company and Position are required; all other fields are optional. Status defaults to "Awaiting Response" and Date Applied defaults to today if omitted. Use extra_fields to set any custom columns you've added. Backs the file up to .bak before writing. |
| update_job_statusA | Update the Status (and optionally the Notes) of an existing application, matched by company + position. Validates the row exists and backs the file up before writing. |
| delete_jobA | Permanently remove a job application row, matched by company + position, shifting the rows below it up (like Excel's Delete Row). Refuses to act on a missing or ambiguous match, backs the file up to .bak first, and returns the full deleted row so it can be re-added if needed. |
| update_jobA | Edit any field(s) of an existing application, matched by company + position. Only the fields you supply are changed; pass an empty string to clear a field. Rename with new_company / new_position. Set custom columns via extra_fields. Refuses missing or ambiguous matches, validates dates, and backs the file up before writing. |
| get_stale_jobsA | List applications still "Awaiting Response" or "Applied" whose Date Applied is more than N days ago (default 14), computed against today. |
| get_due_followupsA | List applications whose Next Follow-Up date is due — on or before today (or within the next |
| search_jobsA | Case-insensitive substring search across the Company, Position, and Notes columns. |
| draft_followup_messageA | Draft a short, professional follow-up email for a given application, referencing how long it has been since applying, the role, and the resume version used. Returns draft text only — it does not send anything. |
| add_columnA | Add a new custom column to the spreadsheet, appended after the last column. Optionally fill every existing job row with a default value. Refuses if a column with that name already exists. Backs the file up before writing. (Note: the built-in job tools only read/write the standard columns; custom columns are managed with these column tools.) |
| modify_columnA | Modify a custom column: rename it (new_name) and/or set the same value into every existing job row (fill_value; pass an empty string to clear the column). At least one of new_name / fill_value is required. Refuses on the built-in columns and on a missing column. Backs the file up first. |
| delete_columnA | Permanently remove a custom column and shift the columns to its right left by one (like Excel's Delete Column). Refuses on the built-in columns and on a missing column. Backs the file up to .bak first. |
| discovery_listA | List job leads from the discovery sheet (Job_Search_Discovery.xlsx). Optional filters: company (case-insensitive substring), status (case-insensitive exact), and query (substring across every column). |
| discovery_addA | Append a new lead to the discovery sheet. Company and Position are required; set any other columns via fields (e.g. Salary, Job Link, "Match Assessment"). Date Found defaults to today and Status to "Open" if not supplied. Backs the file up first. |
| discovery_updateA | Edit a discovery lead, matched by company + position. Rename via new_company / new_position; set any columns via fields (empty string clears a value). Refuses missing/ambiguous matches; backs up first. |
| discovery_deleteA | Permanently remove a discovery lead, matched by company + position, shifting rows below it up. Refuses missing/ambiguous matches, backs up first, and returns the deleted row so it can be re-added. |
| promote_to_trackerA | Turn a discovery lead into a tracked application: copies Company, Position, Job Link, and Location into the tracker with Status "Applied" and Date Applied = today (both overridable). Salary and Match Assessment are carried into Notes unless you supply your own. Optionally removes the lead from the discovery sheet. Backs up both files it writes. |
| read_interview_prepA | Read the interview-prep Q&A markdown file (Interview_Prep_QA.md) and return it as text. Pass an optional company to return just that company's section. Returns a friendly message (not an error) if the file doesn't exist yet or the company has no section. |
| append_interview_prepA | Append markdown to the interview-prep file under a company's section. Creates the file (with a top-level heading) and/or the company section if needed; otherwise adds to the existing section without duplicating its heading. Keep the file's style: 'Q: ...' / 'A: ...' pairs and optional 'Notes: ...' lines. Backs the file up before writing. |
| save_documentA | Save a generated document (docx or PDF) into the Resumes folder (created if missing).
PREFERRED: pass |
| print_documentA | Silently print a saved document to a printer. Give a file name in the Resumes folder (or a full path). PDFs print directly; .docx files are converted to PDF first (cached next to the docx). Uses the system default printer unless printer_name is given. Confirms the job was SENT to the printer, not that it physically finished. |
| list_documentsA | List the saved resumes / cover letters in the Resumes folder (name, size, and modified date). Optional |
| delete_documentA | Delete a saved document from the Resumes folder. Backs it up (to the rotating .backups folder) first so it can be restored, then removes it. Refuses a missing file or any path outside the Resumes folder. |
| read_documentA | Extract and return the plain text of a saved resume / cover letter (.pdf or .docx) from the Resumes folder, so it can be read and analyzed in conversation (e.g. "read my Acme Corp resume and check it against this posting"). Read-only. Give a file name in the Resumes folder. |
| generate_resumeA | Generate a tailored resume PDF (or docx) on the host and save it into the Resumes folder — no base64, works from Claude Desktop.
The STABLE facts (employers, titles, dates, education, skills) come from resume_master.json; YOU supply only the per-posting tailoring: a rewritten |
| get_resume_master_fieldA | Read one field from resume_master.json (the stable resume facts) by dot/bracket path, e.g. "skills", "projects[0].description", "experience[2].title". Scoped to that one file. Use list_resume_master_structure first if you're unsure of the path. |
| update_resume_master_fieldA | Update one existing field in resume_master.json by dot/bracket path (e.g. a corrected date, an added skill, a new project). Only edits fields that ALREADY exist — it will not create new keys (that's a deliberate schema change to make by hand). Backs the file up first and reports old → new. Scoped to resume_master.json only. |
| list_resume_master_structureA | Show the SHAPE of resume_master.json (keys, array lengths, scalar types — not the full field values) to help pick a path for get_resume_master_field / update_resume_master_field. Optional |
| read_text_fileA | Read any plain-text file (.md, .txt, .json, .csv, …) inside the Job Tracking folder tree — handoff notes, scratch files, etc. Give a filename or relative path (e.g. "HANDOFF_2026-08-02.md" or "notes/plan.txt"), resolved under the Job Tracking root. Read-only, and strictly scoped to that tree — paths that escape it are refused. For PDFs/docx in the Resumes folder use read_document instead. |
| search_gmail_for_jobA | Read-only search of the authorized Gmail account for messages related to a company (and optionally position/keywords) — recruiter replies, interview invites, rejections, etc. Does not modify anything. Requires Gmail to be authorized first (see GMAIL_SETUP.md / npm run gmail:auth). |
| read_gmail_messageA | Read the full body of ONE specific Gmail message — search_gmail_for_job and scan_job_updates only return a short snippet, so use this when you need the actual content (e.g. an interview link or instructions). Pass message_id (the |
| scan_job_updatesA | Cross-reference open applications in the tracker against Gmail: for each open job (or one company, if given), searches Gmail for recent related mail and flags simple keyword-based signals (interview, offer, rejection language). Read-only — it only SUGGESTS a status change via |
| draft_gmail_replyA | Create a real Gmail draft — visible in the Drafts folder — but does NOT send it; a human still has to open it and hit Send. Either replies within an existing thread (pass thread_id, e.g. from search_gmail_for_job or scan_job_updates) or starts a new message (pass to + subject). Requires Gmail to be authorized (see GMAIL_SETUP.md). |
| send_gmail_emailA | SENDS a real email immediately through the authorized Gmail account. This cannot be undone — there is no draft step. Only call this after showing the user the exact to/subject/body and getting explicit confirmation; the call must include confirm: true or it is refused. Either sends a reply within an existing thread (thread_id) or a new email (to + subject). Requires Gmail to be authorized (see GMAIL_SETUP.md). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DaleMagrath/mcp-job-tracker'
If you have feedback or need assistance with the MCP directory API, please join our Discord server