Skip to main content
Glama
kaidashova

Job Assistant MCP

by kaidashova

Job Assistant MCP

An MCP server that turns Claude into a job-search assistant. It pulls real postings from public job boards, scores them against your own stored profile (skills, experience, projects) and tracks your applications in SQLite.

"Find remote Python + AI jobs posted this week and tell me which three fit me best."

What it does

Tool

Purpose

set_profile / get_profile

Store your skills, years of experience, target roles, summary and projects (merged, so you can update one field at a time).

search_jobs

Query all boards concurrently, filter by keywords / remote / recency, dedupe, cache. If a profile exists every result gets a 0-100 fit score and the list is sorted best-first.

match_job_to_profile

Explainable breakdown for one posting: matched & missing skills, seniority fit, which of your projects to mention.

get_job

Full posting text + your application status.

save_job, update_status, list_applications

Application tracker (saved → applied → screening → interview → offer / rejected / withdrawn) with full status history and per-stage counts.

Also exposed: resources profile://me and jobs://pipeline, and prompts find_best_jobs and prepare_application (tailored cover letter + talking points).

Job sources

Source

Access

Notes

DOU

official public RSS

Ukrainian IT jobs

Djinni

official public RSS

Ukrainian / European IT jobs

The scope is intentionally limited to these two Ukrainian IT job boards. LinkedIn is not supported: it has no public job API and scraping it violates its Terms of Service. New sources are easy to add, see Adding a source.

A failing board never breaks a search; its error is reported in errors and the rest still return.

Related MCP server: job-search-mcp

Quick start

You need Docker and an MCP client such as Claude Code.

1. Start the server

git clone https://github.com/kaidashova/job-assistant-mcp.git && cd job-assistant-mcp
docker compose up -d --build

The MCP endpoint is now at http://localhost:8000/mcp. If port 8000 is taken, pick another one: HOST_PORT=8765 docker compose up -d --build (use the same port in step 2).

2. Connect your MCP client

claude mcp add --transport http job-assistant http://localhost:8000/mcp
claude mcp list        # job-assistant should show as connected

Then start claude and type /mcp to see the 8 tools. Any other MCP client that supports Streamable HTTP can use the same URL.

3. Day-to-day

docker compose logs -f     # watch the server
docker compose down        # stop (your data is kept)
docker compose down -v     # stop and delete all data (profile, applications)

The container restarts automatically with Docker. Your profile and applications live in the job-data Docker volume, so they survive restarts and rebuilds.

The port is bound to 127.0.0.1 only. There is no authentication, so don't expose it publicly without a reverse proxy in front.

Try it

  1. Tell Claude about yourself once:

    Save my profile: skills Python, FastAPI, PostgreSQL, Docker, LLM, RAG, MCP; 3 years of experience; I want Python Developer or AI Engineer roles. Projects: "Job Assistant MCP" (MCP server, tech: python, sqlite, mcp), "Docs Q&A bot" (tech: python, rag, postgresql).

  2. Use the find_best_jobs prompt, or just ask:

    Find remote Python + AI jobs posted this week and tell me which three fit me best.

  3. Save the first one and mark it as applied. → later: "What's in my pipeline?"

How scoring works

Deterministic and explainable, so Claude can reason over the parts instead of a black box:

score = 65 × skill coverage + 20 × role fit + 15 × seniority fit

  • Skill coverage: skills are extracted from the posting using a vocabulary of ~90 technologies with aliases (k8s → kubernetes, postgres → postgresql; ambiguous words like go only match as golang). Skills in the title/tags count double. Umbrella skills are implied (LLM/RAG ⇒ AI, PostgreSQL ⇒ SQL). Skills outside the vocabulary that you list in your profile are still searched for.

  • Role fit: word overlap between your target roles and the job title.

  • Seniority fit: level from the title (junior … lead) vs. your years of experience.

Architecture

Layered, with dependencies pointing downward only:

server/         MCP adapters: tools, resources, prompts (validate input -> call service -> typed output)
   ↓
services/       business logic: SearchService, TrackerService, ProfileService, MatchingService
   ↓
repositories/   SQLite access only: Database, JobRepository, ApplicationRepository, ProfileRepository
sources/        one module per job board, all behind the same JobSource protocol
matching/       pure scoring engine + skill extraction (no I/O)
utils/          small stateless helpers (HTML to text, date parsing)
schemas/        Pydantic models shared by every layer; tool results are typed, so the server
                publishes JSON output schemas for each tool
constants/      all module-level constants (skill vocabulary, scoring weights, feed URLs, SQL schema…)
config.py       Settings (pydantic BaseSettings, read from env / .env)
container.py    composition root: builds the repositories and services and wires them together
errors.py       JobAssistantError, surfaced to the model as a clean tool error
app/
  config.py  container.py  errors.py
  constants/      skills, matching, sources, search, database, server
  schemas/        job, application, profile, search, matching, source
  repositories/   database, jobs, applications, profile
  services/       search, tracker, profile, matching, filters
  matching/       scoring, skills
  sources/        base, rss, dou, djinni
  utils/          text (HTML cleanup, remote detection), dates
  server/         app, tools, resources, prompts
tests/            offline: mocked HTTP + fixtures, one test module per layer, plus end-to-end over MCP

Services never import MCP and the server never touches SQL, so each layer is testable on its own.

Development

make install   # local .venv with dev tools (uv)
make test      # offline tests, no network needed
make lint      # ruff + mypy

CI (GitHub Actions) runs lint + tests on Python 3.11-3.13 and builds the Docker image.

Adding a source

Create app/sources/mysource.py with a class that has a name and an async fetch(client, query) -> list[Job], then register it in sources/__init__.py. Filtering by keyword / remote / date is done centrally in services/filters.py, so a source only needs to fetch and map fields. Add a fixture and a test in tests/.

Configuration

Variable

Default

Meaning

JOB_ASSISTANT_DB

/data/jobs.db in Docker

SQLite file

MCP_TRANSPORT

streamable-http in docker-compose.yml

stdio or streamable-http

MCP_HOST / MCP_PORT

0.0.0.0 / 8000 in Docker

HTTP bind address inside the container

JOB_ASSISTANT_HTTP_TIMEOUT

20

Seconds before a job-board request times out

To change one, add it under environment: in docker-compose.yml and run docker compose up -d again.

Notes

  • Built on the official MCP Python SDK (v2, MCPServer).

  • Be a good citizen: only public feeds/APIs are used, with a descriptive User-Agent and one request per board per search.

  • Your profile and applications never leave your machine; only the search keywords go to the boards.

MIT licensed.

Available Tools

8 tools
get_jobA
Read-only

Full details (description, tags, application status) of a job from search results.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
urlYes
tagsNo
titleYes
remoteNo
salaryNo
sourceYes
companyNo
locationNo
posted_atNo
applicationNo
descriptionNo

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds the fields that come back, but that is largely duplicated by the output schema, and it says nothing about error behavior for invalid/expired job IDs or whether saved-job state is included.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single compact sentence with the resource and scope front-loaded; every clause carries information. The parenthetical field list is somewhat redundant with the output schema but is not wasteful enough to hurt.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with an output schema, the description covers what is returned and where the ID comes from. Missing pieces are minor: no mention of failure modes or that application status may be stale relative to update_status.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the schema itself gives no meaning for job_id. The description partially compensates by indicating the ID originates from search results, but it does not state the expected format or whether IDs expire, leaving a real gap for the single required parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (a job) and scope (full details: description, tags, application status), and the phrase 'from search results' distinguishes it from search_jobs. It does not, however, explicitly separate itself from match_job_to_profile or save_job, which also operate on a single job.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'From search results' implies the job_id comes from search_jobs, giving an implied usage context. There is no explicit when-to-use statement, no exclusion ('do not use to fetch multiple jobs'), and no mention of alternatives such as match_job_to_profile.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_profileA
Read-only

Return the stored profile (empty if none has been set yet).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
skillsNo
summaryNo
projectsNo
target_rolesNo
years_experienceNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds non-obvious behavioral context: the return is empty if no profile has been set, which tells the agent how to interpret a null/blank result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the main behavior front-loaded and the edge case parenthetically appended. Zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-shape explanation is not required, and the empty-state caveat covers the main ambiguity. The only shortfall is the absence of any relationship to sibling tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, which is the baseline-4 case. There is nothing for the description to disambiguate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Return) and resource (stored profile), so the operation is unambiguous. It does not explicitly differentiate itself from the sibling set_profile (the write counterpart), leaving the read-vs-write routing to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the verb 'Return' but there is no explicit when-to-use statement or named alternative (e.g., 'use set_profile to create one'). Adequate but with a clear gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_applicationsB
Read-only

Your tracked jobs (optionally filtered by status) plus counts per pipeline stage.

ParametersJSON Schema
NameRequiredDescriptionDefault
statusNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
countsYesNumber of applications per status
applicationsYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds that results include per-stage counts, which is useful context, but says nothing about pagination, ordering, or how the counts are scoped. With annotations doing the heavy lifting, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with zero padding. The core resource is front-loaded and the optional filter and supplementary counts are appended parenthetically, which is efficient and readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and annotations cover the safety profile. Still, for a list tool the description leaves the valid status vocabulary and any result-ordering behavior undocumented, which is a meaningful gap given the 0% schema coverage on the only parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single 'status' parameter is a bare string with no enum, so the schema tells the agent nothing about valid values. The description only repeats that filtering by status is optional ('optionally filtered by status') and does not enumerate the accepted status values, 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.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource ('Your tracked jobs') plus an aggregation ('counts per pipeline stage'), so an agent can tell this is a personal application-list tool rather than a search tool. It lacks an explicit verb and does not name a sibling, but the resource is distinctive enough to distinguish it from search_jobs or get_job.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Your tracked jobs' implies this is for the user's saved pipeline rather than the global job corpus, hinting at divergence from search_jobs. However, there is no explicit when-to-use statement and no exclusions or named alternatives, leaving routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

match_job_to_profileB
Read-only

Compare a posting with the stored profile: score, matched/missing skills, seniority fit and which of your projects are most relevant to mention.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlNo
notesYes
scoreYes
titleYes
job_idYes
companyYes
verdictYes
breakdownYes
matched_skillsYes
missing_skillsYes
relevant_projectsYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds that the result is an analysis (scores, matched/missing skills, seniority fit), which is useful, but with an output schema present the return-content detail is largely redundant and no preconditions (e.g. stored profile requirement) are disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that leads with the action and then lists the outputs. Efficient, with no filler, though the enumerated outputs make it slightly list-heavy rather than prose-tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read-only tool with an output schema, the description is adequate about what is produced, but it omits how to source job_id and any precondition that a stored profile must exist — gaps that matter given 0% parameter documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single job_id parameter is undocumented in both schema and description. The phrase 'a posting' hints that an identifier is needed, but the description never explains what job_id is, its format, or where to obtain it (get_job/search_jobs), leaving the only parameter under-specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (compare) and both resources (posting, stored profile), then enumerates the analysis produced: score, matched/missing skills, seniority fit, relevant projects. This clearly separates it from siblings like get_job/get_profile, which merely fetch, though it does not name them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied — the agent can infer 'use this to evaluate fit' — but there is no explicit when-to-use guidance, no prerequisites (e.g. a profile must be set first), and no named alternatives among the siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_jobB
Idempotent

Add a job to your application tracker with status 'saved'.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
job_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
applicationYes
already_savedYes

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, so safety and repeat-call behavior are covered. The description adds one useful bit of context beyond them: the record is created with status 'saved'. It says nothing about duplicate job_ids, required fields, or what happens if the job is already tracked.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with zero filler, and the key effect (status 'saved') is placed up front. Nothing is padded or restated from the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. However, for a mutation tool with a required undocumented parameter and no usage routing, the description is thin; it covers the action and its state effect but not the inputs or alternatives an agent needs to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the required 'job_id' parameter is never mentioned in the description, leaving no guidance on its format or provenance (e.g. from search_jobs). The optional 'notes' parameter is likewise unexplained. This is a clear case where the description should compensate for the empty schema and does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a job') plus the resulting state ('status saved'), so an agent understands the effect without opening the schema. It does not, however, contrast itself with siblings like update_status or list_applications, which is where a 5 would come from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance. With siblings such as update_status, list_applications and get_job present, the description never says whether this is for first-time tracking versus status changes, leaving the agent to infer intent from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_jobsA

Search live job boards concurrently. If a profile is stored, each result carries a 0-100 fit score and results are sorted best-first; otherwise newest-first.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sourcesNoSubset of boards to query. Available: dou, djinni.
keywordsYesTerms to look for, e.g. ['python', 'AI'].
remote_onlyNoOnly remote positions.
match_all_keywordsNoRequire every keyword (AND) instead of any (OR).
posted_within_daysNoOnly postings from the last N days.

Output Schema

ParametersJSON Schema
NameRequiredDescription
jobsYes
errorsYesBoards that failed, with the reason
returnedYes
by_sourceYes
total_foundYes
scored_against_profileYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (destructiveHint=false, openWorldHint=true) and match the 'live job boards' framing, so the description is free to spend its words elsewhere, which it does: it discloses that boards are queried concurrently, that a stored profile adds a 0-100 fit score per result, and that ordering flips between best-first and newest-first. This is genuinely additive context. It does not explain the readOnlyHint=false flag, i.e. what the non-read-only side effect of a search actually is.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with the core action front-loaded and the conditional scoring/sorting behavior immediately after. Every clause carries information an agent would otherwise have to guess.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return shape need not be described, and the description covers the two behaviors that the schema cannot express: concurrency across boards and the profile-dependent scoring/ordering. Parameter-level filtering is left entirely to the schema, which is acceptable given 83% coverage but is the one remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 83%, so keywords, sources, remote_only, match_all_keywords and posted_within_days are already documented in the schema. The description adds nothing about any parameter (not even the fact that the remote/freshness defaults are applied), so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Search live job boards') plus a scope detail ('concurrently', i.e. multiple boards queried in parallel), which an agent can hold apart from get_job or save_job. It stops short of naming a sibling or ruling one out, so it is clear but not fully differentiated from the sibling set.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the reader infers 'call this when you want to find postings', and the mention that a stored profile changes scoring hints at why one might set a profile first. There is no explicit when-to-use/when-not statement and no alternative (e.g. match_job_to_profile) named for the scoring case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_profileB
Idempotent

Create/update your profile. Only the fields you pass are changed.

ParametersJSON Schema
NameRequiredDescriptionDefault
skillsNo
summaryNo
projectsNo
target_rolesNo
years_experienceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
skillsNo
summaryNo
projectsNo
target_rolesNo
years_experienceNo

TDQS

B3.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds genuine value with merge semantics ('Only the fields you pass are changed'), clarifying partial-update behavior that annotations do not express. It says nothing about permissions or overwrite edge cases.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two brief sentences, tightly front-loaded with the action and immediately followed by the key semantic. No filler; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, but the definition leaves 5 undocumented parameters ambiguous (e.g. what 'projects' objects expect, null vs omitted) and offers no usage context for a mutation tool. It is under-specified for a five-parameter profile upsert.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 5 parameters (skills, summary, projects, target_roles, years_experience) have 0% schema description coverage, so the description carries the full burden — yet it names no parameter and gives no format or type guidance. The only relevant clue is the generic note that unpassed fields are unchanged.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Create/update your profile') with clear upsert semantics that distinguish it from get_profile. It does not explicitly name or contrast with siblings like get_profile or match_job_to_profile, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance, and no mention of alternatives such as get_profile for reads. The only usage signal is implicit in 'Create/update'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_statusB
Idempotent

Move a job through the pipeline; every change is kept in its history.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
job_idYes
statusYessaved | applied | screening | interview | offer | rejected | withdrawn

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
notesNo
titleYes
job_idYes
statusYes
companyYes
historyNo
saved_atYes
updated_atYes

TDQS

B3.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds a genuinely new behavioral fact not derivable from any structured field: every change is retained in the job's history, telling the agent that status moves are auditable and recoverable. It still omits any permission or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the core action is stated before the behavioral footnote. Nothing is wasted or buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and annotations cover the mutation safety profile. Still, for a write tool with two undocumented parameters, the description is thin — it omits transition validity, notes semantics, and failure behavior, leaving the agent to guess at invocation details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (only 'status' carries an inline description listing the pipeline values); job_id and notes are undocumented. The description adds no meaning to any parameter — it does not say what notes are for or whether job_id must reference an existing application — 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.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The verb+resource are clear: 'Move a job through the pipeline' identifies this as a job-status transition tool, which is distinct from read-oriented siblings like get_job or search_jobs. It does not, however, explicitly name or contrast itself with save_job or list_applications, 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.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use this tool versus alternatives such as save_job, nor any precondition (e.g., job must already exist, allowed transitions). Usage is only implied by the phrase 'move a job through the pipeline'.

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.

  1. 8 tool updatesv0.1.0
    • First observedget_job
    • First observedget_profile
    • First observedlist_applications
    • First observedmatch_job_to_profile
    • First observedsave_job
    • First observedsearch_jobs
    • First observedset_profile
    • First observedupdate_status

TDQS

A3.7/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct resource and action: profile (get/set), jobs (search/get/save/match), and applications (update_status/list_applications). The fit-scoring overlap between search_jobs and match_job_to_profile is intentional and clearly separated by scope. An agent can reliably pick the right tool for any task.

Naming Consistency5/5

All tools use a consistent snake_case verb_noun pattern (get_profile, search_jobs, save_job, list_applications, set_profile, update_status). Naming is predictable and self-describing throughout.

Tool Count5/5

8 tools is well-scoped for a job-assistant domain covering profile management, job discovery, matching, and application tracking. No redundant or filler tools; each earns its place.

Completeness4/5

Covers the core lifecycle: profile get/set, job search/get/match/save, and application tracking with status updates and counts. Minor gaps exist (no way to remove/unsave a job or delete a profile), but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Transforms Claude into an AI job-hunting assistant that searches remote job boards, scores roles against your CV, generates tailored cover letters, and logs everything to a Notion tracker.
    11
    -
  • F
    license
    B
    quality
    D
    maintenance
    Enables searching justjoin.it for job listings and tracking applications locally with status updates, all via natural language in Claude.
    4
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to parse CVs, search job boards (Remotive, Arbeitnow, Adzuna, Greenhouse/Lever), tailor resumes and cover letters, and prepare application packages with direct apply links—without ever auto-submitting. It runs 100% locally and free, storing jobs and applications as JSON files.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude Desktop to manage a job search end-to-end: find and score job listings, tailor resumes, generate application messages, and track application history, while leaving final external actions to the user.
    -