career-agent-mcp
This server exposes deterministic career-agent tools over MCP: it scores job postings, tailors and validates resumes, and tracks applications without letting the model invent facts.
Analyse a job posting against the master profile, producing a deterministic 100-point score breakdown, APPLY/MAYBE/DO_NOT_APPLY/MANUAL_REVIEW decision, hard-reject reasons, and learnable vs critical gaps.
Tailor a resume for a specific job by selecting/reordering existing profile content only, then automatically running the validation gate; invalid resumes are returned with blocking issues.
Validate any resume independently against the master profile (skill provenance, employment integrity, project provenance, metric verification, no placeholders, no seniority inflation, required fields).
Track applications with deduplication on company + normalised role + canonical URL, returning existing entries instead of creating duplicates.
Update application status with an append-only history (e.g. DISCOVERED → SUBMITTED → INTERVIEW → OFFER), never rewriting past state.
Show the pipeline with every tracked application and status counts.
Summarise the profile, showing which skills are printable vs deliberately blocked as LEARNING or UNSUPPORTED.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@career-agent-mcpAnalyse this job posting, score my fit, and tailor my resume"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AI Career Agent
Deterministic job-analysis and resume-tailoring tools, exposed over the Model Context Protocol. An LLM client orchestrates them; it never produces the score and it never decides what is true about the candidate.
The problem this solves
Resume tailoring is the single task where an LLM will most reliably help you lie. Ask it to match a job description and "familiar with Docker" becomes "containerised production workloads", "did a course on Kubernetes" becomes "Kubernetes", and neither of you notices until an interviewer asks a follow-up question you cannot answer.
The fix is not a better prompt. It is a structural separation:
The model may decide what to emphasise. It may never decide what is true.
Everything printable about the candidate lives in one MasterProfile, and every
skill in it carries an evidence label. The tailoring engine may reorder,
select and re-word — it may not add. A validation gate then checks the
generated resume against the profile independently and blocks anything it
cannot trace back.
┌──────────────────────┐
job posting ────▶│ Scorer │──▶ score / decision / gaps
│ (deterministic) │ (learnable vs critical)
└──────────────────────┘
│
MasterProfile ─────────────▶│
(labelled claims) ▼
┌──────────────────────┐
│ ResumeTailor │──▶ tailored resume
│ select + reorder │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ ValidationGate │──▶ FINAL, or BLOCKED with reasons
│ independent check │
└──────────────────────┘Related MCP server: jobfinder-mcp
Standalone daily run (no LLM required)
career-agent daily runs on GitHub Actions every morning without Claude:
company ATS boards, remote-job boards, public Telegram channels and job blogs
→ gates → match score → Notion tracker; a tailored resume (DOCX + text) with
an ESTIMATED ATS score on every new match, marked READY only at ATS ≥ 90
with the validation gate passed; government IT jobs into a separate tracker;
link/post safety checks; and a digest with apply links in Notion and email.
It never submits applications. What is and is not independent, setup and
limits: docs/STANDALONE_RUNTIME.md.
Evidence labels
Every skill is recorded with how well it is actually supported:
Label | Meaning | Printable? |
| Demonstrable — shipped code, or core to a job held | yes |
| Real but narrower than the word implies | yes |
| Adjacent experience, honestly framed | yes |
| Being learned. Not a competency yet | no |
| Not held | no |
| Unconfirmed | no |
The interesting part is that LEARNING and UNSUPPORTED skills are stored
deliberately. The system needs to know they exist so it can refuse to print
them — and so that when a posting asks for one, it can tell you honestly
whether it is a gap of weeks or a gap of years.
$ career-agent profile
┌────────────────────┬──────────────────────────────────────────────────┐
│ LEARNING │ Kafka, LangChain, Vector databases │
│ UNSUPPORTED │ Kubernetes, Machine learning, React │
└────────────────────┴──────────────────────────────────────────────────┘
LEARNING and UNSUPPORTED skills are recorded deliberately - the validation
gate blocks them from ever being printed as competencies.Scoring
Deterministic, weighted, 100 points. Same input, same score — which is what makes it comparable across a hundred applications instead of drifting with whatever the model felt like that day.
Component | Max |
Technical fit (required weighted 4× preferred) | 25 |
Experience against stated requirement | 20 |
AI / GenAI relevance | 15 |
Backend relevance | 10 |
Seniority alignment | 10 |
Location | 5 |
Compensation signal | 5 |
Career growth signal | 5 |
Learnability of the gaps | 5 |
Hard rejects run first and short-circuit. A role requiring a PhD you do not have is not a low score, it is not a job — and pretending otherwise wastes the only genuinely scarce resource in a job search, which is the attention you can give each application.
$ career-agent analyse examples/jpmorgan_hyderabad.yaml
JPMorgan Chase - Software Engineer III - Java/Python - AIML
APPLY · score 87.5/100 (Strong) · ATS keyword coverage 88.9%
Learnable gaps: LangGraph$ career-agent analyse examples/senior_ml_riyadh.yaml
Example Analytics - Principal Machine Learning Engineer
DO_NOT_APPLY · score 21.8/100 (Low Priority)
Hard rejects
· Requires 10+ years; profile has 4.7 - a 5.3 year gap.
· Mandatory qualification not held: PhD in Machine Learning
· Title implies a seniority band above this profile.
· Three or more required skills are multi-year gaps, not learnable ones.
Critical gaps (do not claim): PyTorch, TensorFlow, MLOps, KubernetesGaps are split into learnable (weeks of deliberate work) and critical (years). Conflating the two is how people either give up on winnable roles or waste months on unwinnable ones.
The validation gate
Seven checks, each blocking:
Skill provenance — every printed skill exists in the profile at a printable label. A
LEARNINGskill named in the posting is still refused.Employment integrity — employer, title and dates must match a profile record exactly. Inflating a title at a real employer is caught.
Project provenance — no unknown projects; a public URL is refused unless the profile marks the project shipped, because a link that 404s in front of a recruiter is worse than no link.
Metric verification — any number presented as an achievement must appear in the profile as a whole token.
No placeholders — no
TBD, no[COMPANY], no unresolved templates.No seniority inflation — "principal", "architected the", "expert in" are blocked against a 4.7-year profile.
Required fields — no empty headline or summary.
A resume that fails is returned with is_final: false and every blocking
reason listed. There is no override flag. If the gate is wrong, the fix is to
correct the profile, not to bypass the check.
MCP server
career-agent-mcp # JSON-RPC 2.0 over stdioTool | Determinism |
| fully deterministic |
| selection + reordering, then gated |
| fully deterministic |
| deduplicated, append-only |
| append-only history |
| read |
| read |
The server's initialize instructions tell the client, in as many words, that
it may not decide what is true about the candidate and must report blocking
issues rather than working around them.
Tracker
Append-only JSONL. Two rules, both learned the expensive way:
Never overwrite history. Status changes append; the previous state stays readable. A tracker that silently rewrites itself cannot answer "when did this go quiet?", which is the only question that matters when a pipeline stalls.
Never create a duplicate. Deduplication on company + normalised role + canonical URL, so the same job on LinkedIn and on the company careers page is one row.
Senior AI Engineer IIandAI Engineerat the same company on the same URL are the same job;?utm_source=linkedinis not a different posting.
Quick start
pip install -e ".[dev]"
career-agent profile # what is and isn't claimable
career-agent analyse examples/jpmorgan_hyderabad.yaml # score a posting
career-agent tailor examples/jpmorgan_hyderabad.yaml # generate + validate
career-agent track examples/jpmorgan_hyderabad.yaml # add to the pipeline
career-agent pipeline --export applications.csv
pytest -q # 68 testsNo API key, no network, no cost. Nothing here calls a model — that is the client's job.
Tests found real bugs
Worth recording, because it is the argument for writing them:
Substring metric matching. An invented "47% latency reduction" passed the gate because
47appears inside the LinkedIn URL sluga94479167. Fixed with whole-token numeric extraction.Alias-blind skill promotion. A posting asking for
MCPfailed to promote the skill stored asModel Context Protocol, burying the most relevant item on the resume. Fixed by matching aliases.Punctuation surviving normalisation.
Sr. Java Developerleft a bare.token, so it would not deduplicate againstJava Developer.
Limitations
It does not find jobs. Ingestion is by URL, file or paste. LinkedIn prohibits unauthorised automated collection, and this project does not do it.
It never submits an application. Preparation is automated; submission is a human action.
The ATS score is an estimate of overlap between the profile and a posting's stated skills. It is not any employer's actual ATS score and is labelled as such everywhere it appears.
The master profile is never modified automatically. An agent that can silently edit its own source of truth has no source of truth.
Licence
Apache-2.0.
Available Tools
7 toolsanalyse_jobA
Score a job posting against the master profile using a deterministic weighted rubric (technical 25, experience 20, AI relevance 15, backend 10, seniority 10, location 5, compensation 5, growth 5, learnability 5). Returns the score breakdown, an APPLY / MAYBE / DO_NOT_APPLY / MANUAL_REVIEW decision, hard-reject reasons, and gaps split into learnable versus critical.
| Name | Required | Description | Default |
|---|---|---|---|
| job | Yes | JobPosting object. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and largely meets it: it discloses the deterministic weighted rubric with explicit weights, the decision taxonomy (APPLY/MAYBE/DO_NOT_APPLY/MANUAL_REVIEW), hard-reject reasons, and learnable-vs-critical gap classification. It does not address side effects, whether the master profile is fixed/implicit, or rate limits, but behavioral disclosure is unusually strong for a no-annotation tool.
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 dense sentences that front-load the method (weighted rubric) before the outputs. The weight enumeration is long but earns its place by disclosing the scoring model; no filler sentences.
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 exists, but the description compensates by enumerating return contents (breakdown, decision, hard-reject reasons, gap categories), which is what an agent needs to consume results. The nested JobPosting structure and the implicit master-profile dependency are the remaining gaps.
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 single 'job' parameter is documented in the schema as a JobPosting object; the description adds no format or structural detail beyond that. One noteworthy implicit dependency — that scoring happens against a 'master profile' not passed as a parameter — is mentioned but not clarified. 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 and resource ('Score a job posting against the master profile') and names the exact scoring mechanism, making it clearly distinct from siblings like tailor_resume or track_application. An agent immediately knows this is the evaluation/scoring tool.
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?
Usage is implied by the scoring semantics (use it to decide whether to apply), but there is no explicit when-to-use statement, no when-not conditions, and no named alternatives among the siblings. The context is reasonably inferable but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profile_summaryA
Return what the master profile can and cannot support: printable skills by label, and the skills deliberately recorded as LEARNING or UNSUPPORTED so they are never printed as competencies.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden, and it does disclose a real trait: LEARNING/UNSUPPORTED skills are deliberately never surfaced as competencies, so callers understand the filtering rule. However, it omits that this is a read-only operation, how results are ordered or structured, and whether anything is mutated.
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?
A single sentence front-loads the core purpose ('what the master profile can and cannot support') and uses the colon clause to enumerate the two result categories. No filler or repetition.
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, no annotations, and no parameters, the description is the sole carrier of meaning, and it does explain the two output categories and the exclusion rule. It stops short of describing the shape of the returned data (labels, grouping, counts), which is the remaining gap for a reporting tool.
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 document and the baseline of 4 applies. The schema being empty and closed ('additionalProperties: false') is consistent with the no-argument nature of the call.
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 concrete action and resource: return the master profile's supported/unsupported skills, breaking them into printable skills by label and items recorded as LEARNING or UNSUPPORTED. That is specific enough to distinguish it from siblings like tailor_resume or validate_resume, though it never explicitly contrasts itself with them.
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?
There is no statement of when to call this versus alternatives such as tailor_resume or validate_resume, nor any prerequisite or exclusion. The intended use (audit what the profile can back up) is only implied by the word 'support'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
show_pipelineB
Return every tracked application and a count by status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations and no output schema, the description carries the full disclosure burden. It does reveal the return content (all applications plus a status breakdown), which is genuinely useful, but it says nothing about authentication, pagination, ordering, or whether the set can be filtered or is unbounded.
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?
A single short sentence that front-loads the verb and resource with zero filler. Nothing could be removed without losing meaning.
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-parameter read tool this is close to sufficient, and the return content is sketched. However, no output schema exists, so the description should be doing more work on what the returned counts/records look like and when this view is preferable to the other pipeline tools.
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 schema has zero parameters, so there is nothing to document and no ambiguity for the agent to resolve. Baseline 4 applies since no parameter detail is required.
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 concrete action and resource: returning all tracked applications plus a per-status count. It is clear enough to distinguish from write-oriented siblings like track_application and update_application_status, though it never names a sibling or scope boundary explicitly.
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?
There is no when-to-use statement, no mention of alternatives such as profile_summary, and no trigger conditions (e.g., 'use to review your job search pipeline'). The agent must infer that this is the read/list counterpart to the other application tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tailor_resumeA
Generate a role-specific resume by reordering and selecting from the master profile, then run the factual-validation gate over the result. Never adds a skill, employer, metric or certification that is not already in the profile. A resume that fails validation is returned with is_final=false and the blocking issues listed.
| Name | Required | Description | Default |
|---|---|---|---|
| job | Yes | ||
| version | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the strong non-fabrication invariant ('never adds a skill, employer, metric or certification'), the validation gate, and the failure mode (is_final=false plus listed blocking issues). It omits permissions, whether the result is persisted, and the cost/behavior of the version parameter.
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 the core action and immediately followed by the key constraint and failure behavior. No filler or repetition.
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?
The generation semantics, invariant, and failure return are covered, which offsets the absence of an output schema. However, the nested 'job' object's expected fields and the meaning of 'version' are undocumented, leaving a real gap for an agent that must construct the call.
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 0% and two parameters exist, one of them a nested object ('job') with no documented shape. The description explains the purpose of neither 'job' nor 'version' (e.g., what the version increments or selects), so it fails to compensate for the coverage gap.
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 ('Generate a role-specific resume') and precisely defines the mechanism: reordering and selecting from the master profile plus a factual-validation gate. It is distinguishable from show_pipeline/track_application, but it never names the sibling validate_resume even though it performs validation, leaving a small ambiguity an agent must resolve itself.
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?
Usage is implied: this is the tool for producing a tailored resume for a given job. There is no explicit when-to-use vs. when-not, and no guidance on choosing between this and validate_resume or analyse_job even though their scopes overlap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
track_applicationB
Add a job to the application tracker, or return the existing entry. Deduplicates on company + normalised role + canonical URL, so the same posting seen on two boards is one row. Never overwrites history.
| Name | Required | Description | Default |
|---|---|---|---|
| job | Yes | ||
| score | No | ||
| decision | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose real behavior: dedup key (company + normalised role + canonical URL), idempotency, and the promise never to overwrite history. It omits write/auth implications and what happens to the score/decision values when an existing entry is returned instead of created.
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 tight sentences, with the core upsert behavior and dedup rule front-loaded. No filler, though the dedup clause is dense and slightly jargon-heavy ('normalised role', 'canonical URL') without definition.
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 mutation tool with no annotations, no output schema, and a fully undocumented nested 'job' object at 0% coverage, the description covers the key idempotency/integrity behavior but leaves the return shape, auth needs, and score/decision semantics unaddressed.
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 0%, so the description must compensate; it helpfully names the fields used for deduplication (company, role, canonical URL), which are inside the otherwise opaque nested 'job' object. It says nothing about the 'score' or 'decision' parameters, leaving their semantics entirely to the schema.
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+resource (add a job to the application tracker / return the existing entry) and clarifies the scope through its idempotent upsert semantics. It does not explicitly name a sibling like update_application_status or show_pipeline, so differentiation is inferred rather than stated.
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?
Usage is implied: the idempotent 'or return the existing entry' behavior tells the agent it need not pre-check for duplicates. However, there is no explicit when-to-use vs when-to-use-an-alternative guidance, and no mention of update_application_status for changing status on an existing row.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_application_statusB
Move an application to a new status. Appends to history; never rewrites it.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| status | Yes | ||
| application_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose a genuinely non-obvious trait — history is appended, never rewritten — which tells the agent this is a non-destructive, history-preserving mutation. However it says nothing about whether transitions are validated (can DISCOVERED jump to OFFER?), required permissions, or any side effects.
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 tight sentences with zero filler; the core action is front-loaded and the behavioral caveat follows immediately.
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 3-parameter mutation tool with no annotations and no output schema, the description covers the key history semantics but omits transition validity, permissions, and the meaning of the note parameter. Adequate, but there are clear gaps an agent would want filled.
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 0%, so the description must compensate and it largely does not. The 'status' enum is self-documenting in the schema, but neither the required application_id nor the optional 'note' field is explained anywhere, leaving the agent guessing at what note does.
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 ('Move an application to a new status') plus the scoping behavior. It is clear on its own, but it never names or contrasts with siblings like track_application or show_pipeline, so sibling differentiation is left to inference.
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?
There is no statement of when to reach for this tool versus track_application or show_pipeline, and no prerequisites or preconditions (e.g., whether the application must already exist). Usage is only implied by the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_resumeB
Run the factual-validation gate over a resume object independently. Use this to check a resume that was edited by hand or generated elsewhere.
| Name | Required | Description | Default |
|---|---|---|---|
| resume | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It usefully discloses that this is a standalone validation/gate operation (implying non-destructive, independently invoked), but says nothing about failure behavior, whether it blocks anything, or what a validated/failed result looks like.
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 short sentences, front-loaded with the core action followed by the routing condition. No filler or 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?
With no annotations, no output schema, and an opaque nested 'resume' object, an agent still lacks what the validation checks, what the resume object must contain, and what success/failure returns. It does not compensate for the missing structured data.
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?
One parameter with 0% schema description coverage and a nested object whose structure is entirely undocumented. The description only says the input is a 'resume object', adding no field-level meaning beyond the schema's bare type declaration.
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: it runs a 'factual-validation gate' over a 'resume object', which is a clearly identifiable operation distinct from tailor_resume (generation) and analyse_job. It does not explicitly name any sibling as the alternative, but the purpose is unambiguous.
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 an explicit when-to-use condition: invoke it for resumes 'edited by hand or generated elsewhere', and the word 'independently' signals it is not part of the normal pipeline. No when-not or named alternative, but the context is clear enough to route correctly.
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.
7 tool updates
v1.0.0- First observed
analyse_job - First observed
profile_summary - First observed
show_pipeline - First observed
tailor_resume - First observed
track_application - First observed
update_application_status - First observed
validate_resume
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: viewing pipeline data, tailoring a resume, validating a resume independently, tracking an application, updating status, summarizing profile capabilities, and analysing a job posting. Overlap between tailor_resume and validate_resume is explicitly clarified in the descriptions (one generates-and-validates, the other validates standalone).
Most tools follow a consistent verb_noun pattern (show_pipeline, tailor_resume, validate_resume, track_application, update_application_status, analyse_job). profile_summary is the lone exception, using a noun_noun form instead of a verb-led name.
Seven tools is well-scoped for a career-agent server, covering the key areas of application tracking, resume tailoring and validation, profile introspection, and job analysis without redundancy. Each tool appears to earn its place.
The surface covers core lifecycle operations: tracking applications, updating status, viewing the pipeline, summarizing profile support, analysing jobs, and tailoring/validating resumes. Minor gaps exist around deleting or archiving applications and editing the master profile, though these may be intentional given the explicit no-overwrite and read-only profile-summary design.
Maintenance
Related MCP Connectors
Generate tailored, ATS-optimized resume PDFs and cover letters from a job description, over MCP.
AI job search MCP — fact-checked jobs, application tracker, alerts. ChatGPT, Claude, Cursor.
A job-search companion: tailor your CV to a role, score fit, fix ATS issues. Also via MCP.
Job search and interview prep MCP. 15 tools, OAuth 2.1, cross-LLM. four-leaf.ai.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA local-first, open-source MCP server that analyzes jobs, matches your CV, tailors documents, and tracks applications — all on your machine with no data uploaded.AGPL 3.0
- FlicenseAqualityCmaintenanceEnables searching job listings, tracking applications, managing resumes, and tailoring resumes to job posts, all locally via MCP.620-
- AlicenseNot gradedqualityBmaintenanceEnables JD-aware resume matching through MCP tools, providing deterministic scoring, gap analysis, bullet rewrites, and tailored cover letter generation.308 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables AI clients to serve as a personal career analyst by searching, matching, and explaining job recommendations, managing job applications, and syncing public job boards through standardized MCP tools.MIT