Skip to main content
Glama
mozzan

job104-mcp

by mozzan

job104-mcp

An MCP server for searching 104 人力銀行 job listings with natural-language filters. Works with any MCP client — Claude, Cursor, Windsurf, Cline, Zed, VS Code, and others.

Disclaimer: This is an unofficial, educational/personal-use tool. It is not affiliated with, endorsed by, or sponsored by 104 Corporation. It calls 104's public web endpoints; please respect 104's Terms of Service and use it at a reasonable, low frequency. No scraped job data is distributed with this project.

How it works

104 sits behind Cloudflare bot protection — a plain HTTP request to its JSON API returns 403. This server uses curl_cffi with impersonate="chrome" to match a real browser's TLS fingerprint, so the same public endpoints return their normal JSON. The AI sees clean structured results; the 104 category/area codes are resolved from Chinese names automatically.

Related MCP server: JobSpy MCP Server

Prerequisite: install uv

Every install path runs the server through uv, so it must be installed first (uvx ships with uv):

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Install in any MCP client (Cursor, Windsurf, Cline, Zed, VS Code, …)

MCP is an open protocol, so any MCP-capable client works — not just Claude. Add this to the client's MCP config (e.g. Cursor's ~/.cursor/mcp.json); the command/args form is what most clients accept:

{
  "mcpServers": {
    "job104": { "command": "uvx", "args": ["job104-mcp@latest"] }
  }
}

Install in Claude Code (User scope)

claude mcp add job104 -s user -- uvx job104-mcp@latest

Or from a local clone (no PyPI required):

claude mcp add job104 -- uv run --project /absolute/path/to/job104-mcp -m job104_mcp

Install in Claude Desktop (.mcpb bundle)

The .mcpb bundle is a Claude-Desktop-only convenience (other clients use the JSON config above). Download job104-mcp-vX.Y.Z.mcpb from the Releases page and double-click it (or drag it into Claude Desktop → Settings → Extensions).

To build the bundle yourself:

npx @anthropic-ai/mcpb pack .   # produces job104-mcp.mcpb

Run manually (stdio)

uv run job104-mcp
# or
uv run python -m job104_mcp

Tools

  • search_jobs — search with keyword, area, job category, salary floor, remote, recency, experience, education, sort, paging. Use Chinese names for area/jobcat (e.g. ["台北市大安區"], ["軟體工程師"]); they resolve to 104 codes automatically. Each result carries a detail_id.

  • get_job_detail — full posting for a detail_id from search_jobs.

  • lookup_code — resolve a job-category or area name to its 104 code.

Refresh code tables

The bundled jobcat.json / area.json come from 104's public category tool. Regenerate:

uv run python scripts/fetch_codes.py

Tests

uv run pytest            # fast unit tests
uv run pytest -m live    # hits the real 104 site

Releasing (maintainer)

Releases are automated by .github/workflows/release.yml, triggered when the version in pyproject.toml changes on main. It publishes to PyPI, builds the .mcpb bundle, and attaches it to a GitHub Release.

One-time PyPI setup (uses Trusted Publishing, no API token stored): on https://pypi.org/manage/account/publishing/ add a pending publisher with project job104-mcp, owner mozzan, repo job104-mcp, workflow release.yml.

To cut a release: bump version in pyproject.toml, commit to main.

License

MIT — see LICENSE. Provided as-is, without warranty.

Available Tools

3 tools
get_job_detailA

取得單一職缺的完整內容(職務說明、條件、薪資、地點)。 detail_id 來自 search_jobs 結果的 detail_id 欄位。

ParametersJSON Schema
NameRequiredDescriptionDefault
detail_idYes

TDQS

A4.2/5.0
Behavior3/5

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 discloses the content returned (職務說明、條件、薪資、地點) but does not mention any behavioral traits like read-only nature, authentication requirements, rate limits, or potential errors. This is adequate for a read operation but could be more transparent.

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?

The description is two sentences: one clearly stating the tool's function and the second explaining the parameter source. Every word earns its place, with no redundancy or unnecessary detail, making it highly efficient and front-loaded.

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?

Given the tool's simplicity (1 parameter, no output schema) and sibling tools, the description is fairly complete. It explains what the tool does and where the input comes from. It could be more explicit about the return format, but listing the content areas (job description, conditions, etc.) provides sufficient context.

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 parameter 'detail_id' has 0% schema coverage, meaning the schema provides no description. The tool's description compensates by explaining that the ID comes from 'search_jobs' results, adding crucial semantic context beyond the raw schema. It does not specify format or constraints, but the origin is valuable.

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

Purpose5/5

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

The description clearly states it retrieves full content of a single job listing, specifying details like job description, conditions, salary, and location. It also distinguishes itself from the sibling tool 'search_jobs', which lists jobs, making the purpose unambiguous.

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

Usage Guidelines4/5

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

The description explicitly states that the 'detail_id' comes from 'search_jobs' results, providing clear context for when to use this tool (after a search). However, it does not explicitly mention when not to use it or suggest alternatives beyond the implied dependency.

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

lookup_codeB

查 104 職類/地區代碼。kind: 'jobcat' 或 'area'。回傳 [{name, code}]。

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description must carry full behavioral disclosure. It adds the allowed values for kind and the return format, but does not mention side effects, authorization, rate limits, or error scenarios. The behavior is partially disclosed but incomplete.

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?

The description is very concise at two sentences. It front-loads the core purpose and provides necessary details without waste. However, it could be slightly more structured (e.g., separate lines for each parameter).

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?

The complexity is low, but with 0% schema coverage, the description should fully cover parameter behavior. It handles kind but not query. The output schema exists but the description already mentions the return format. Overall, it is adequate but not complete.

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%, so the description must compensate. It adds meaning for the 'kind' parameter (possible values) but does not explain the 'query' parameter at all. This is incomplete for a tool with two required parameters.

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

Purpose5/5

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

The description clearly states the tool's purpose: to look up 104 job category/area codes. It specifies the kind parameter values ('jobcat' or 'area') and the return format. This distinguishes it from sibling tools like get_job_detail and search_jobs.

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 description implies the tool is for code lookup when you need job category or area codes, but it does not explicitly state when to use it over siblings or provide exclusion criteria. The guidance is minimal but sufficient for a simple lookup.

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

search_jobsA

搜尋 104 職缺。area/jobcat 用中文名稱(如 ["台北市大安區"]、["軟體工程師"]), 內部自動轉成 104 代碼;若名稱不明確會回傳建議選項。每筆結果的 detail_id 可傳給 get_job_detail 取得完整內容。

sort: relevance|date|salary(不填時:有給 salary_min 就自動用 salary 排序, 否則 relevance)。

薪資門檻提醒:104 沒有可靠的伺服器端薪資篩選,所以給 salary_min 時是「用薪資 排序把高薪職缺排到前面」,不是硬篩。薪資會標月薪/年薪(年薪職缺數字較大)。標 「待遇面議」的職缺薪資未公開——若職稱/公司看起來可能達標,呼叫 get_job_detail 通常能拿到真實薪資(detail 常有列表沒有的數字)。

ParametersJSON Schema
NameRequiredDescriptionDefault
eduNo
areaNo
pageNo
sortNo
is_newNo
jobcatNo
remoteNo
keywordNo
job_typeNo
exp_yearsNo
page_sizeNo
salary_minNo

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It explains that area/jobcat are converted from Chinese names, ambiguous inputs return suggestions, salary_min sorts rather than filters, and '待遇面議' jobs may have actual salary in detail. However, it does not cover behavior for other parameters like 'remote', 'is_new', etc., leaving gaps.

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?

The description is well-structured with clear sections: purpose, area/jobcat handling, sort behavior, and salary notes. It front-loads the main purpose. While not extremely concise, every sentence adds value.

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?

Given 12 parameters, no output schema, and no annotations, the description is incomplete. It does not explain the output format (only mentions detail_id) and omits many parameters. The salary note, though helpful, does not fully compensate for missing behavioral details.

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 description must compensate. It adds meaning for area, jobcat, sort, and salary_min (explaining conversion, suggestions, and sorting behavior). However, 8 of 12 parameters (e.g., keyword, job_type, exp_years) are not described, so the compensation is partial.

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

Purpose5/5

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

The description clearly states '搜尋 104 職缺' (search 104 job openings), specifying the verb and resource. It differentiates from sibling tools by noting that the 'detail_id' from results can be used with 'get_job_detail', and 'lookup_code' is a separate tool for code lookup.

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

Usage Guidelines4/5

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

The description provides context on when to use this tool (searching jobs) and references 'get_job_detail' for detailed info. It explains sorting behavior and salary filter limitations. However, it does not explicitly mention when not to use this tool or alternatives for other parameters.

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. Dates show when Glama detected each change.

  1. 1 tool updatev0.1.7
    • Changedsearch_jobs3 fields changed
      • addedInput schema / properties / sort / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / sort / default
        Previous value: -"relevance"New value: +null
      • removedInput schema / properties / sort / type
        Removed value: -"string"
  2. 3 tool updatesv0.1.1
    • First observedget_job_detail
    • First observedlookup_code
    • First observedsearch_jobs

TDQS

A3.9/5.0
Disambiguation5/5

Each tool has a distinct purpose: search_jobs for querying listings, get_job_detail for retrieving full details of a specific job, and lookup_code for resolving category and area codes. There is no functional overlap, and the descriptions clearly differentiate them.

Naming Consistency5/5

All tools follow a consistent verb_noun snake_case pattern: search_jobs, get_job_detail, lookup_code. While 'lookup' is a compound verb, the naming is predictable and clear, aiding agent comprehension.

Tool Count4/5

With only 3 tools, the server is minimal yet sufficient for its purpose of job searching. It covers the essential operations (search, detail retrieval, code lookup) without excess. While a few additional tools (e.g., listing filters) could be added, the current count is reasonable.

Completeness5/5

The tool surface offers a complete workflow for job discovery: lookup codes to build search parameters, search for jobs, and retrieve full details. The search tool handles ambiguous inputs by providing suggestions, and the detail tool can uncover hidden salary data. No obvious gaps exist for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that exposes job search data from multiple boards, enabling clients to query and manage job listings via natural language.
    7
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables job search and scraping across multiple job boards (LinkedIn, Indeed, Glassdoor, etc.) with advanced filtering, directly from Claude Desktop or other MCP clients.
    5
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables job search on LinkedIn through MCP tools, including keyword and location search, filtering by remote, easy apply, experience level, job type, and date, and retrieving job details.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables searching real job listings from multiple job boards (Indeed, LinkedIn, Glassdoor, Google Jobs, etc.) through a single MCP tool, designed for use as a custom connector in Claude Cowork.
    -

Latest Blog Posts

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/mozzan/job104-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server