Skip to main content
Glama
a7512cs

mcp-server-104

by a7512cs

mcp-server-104

台灣 104 人力銀行的非官方 MCP server。讓 Claude(或任何 MCP client)能直接搜尋 104 的即時職缺。

這個工具適合你嗎?

你的情境

最佳工具

偶爾自己找工作

直接開 104 網站

想寫個一次性爬蟲抓資料

Playwright / cycletls 腳本就好,不用 MCP

不想自己寫腳本,要讓 Claude 直接幫你分析/比對/彙整/自動化職缺

這個 MCP

Related MCP server: LinkedIn MCP Server

安裝

以下三種擇一,看你用什麼 client:

A:有快捷指令的 client —— 一行搞定,設定自動寫好:

claude mcp add job104 -- npx -y mcp-server-104   # Claude Code
codex mcp add job104 -- npx -y mcp-server-104    # OpenAI Codex CLI(新版才有;舊版走 B 的 TOML)

B:手動貼設定的 client —— 把設定貼進該 client 的 MCP 設定檔:

Claude Desktop / Cursor / Windsurf(JSON):

{
  "mcpServers": {
    "job104": { "command": "npx", "args": ["-y", "mcp-server-104"] }
  }
}

OpenAI Codex CLI 舊版(~/.codex/config.toml):

[mcp_servers.job104]
command = "npx"
args = ["-y", "mcp-server-104"]

A 和 B 做的是同一件事:告訴 client「用 npx 啟動這個 server」。核心到哪都是 npx -y mcp-server-104,差別只在各家 client 怎麼登記它。

⚠️ ChatGPT 網頁/桌面版接不上這種本機型(stdio)server —— 它只支援遠端 URL 型 MCP,它的雲端上沒有你的電腦可以跑 npx。

C:開發者,想改 code —— clone 這個 repo 後:

npm install && npm run build
claude mcp add job104 -- node /你的路徑/104-mcp-server/dist/index.js

日常指令與測試策略見下方「開發」。

用什麼方法取得資料

104 的搜尋 API 藏在 Cloudflare bot 防護後面。用 curl 或 Node fetch(即使帶 Referer / User-Agent)都會被擋 —— 回 403 或 Cloudflare 的 "Just a moment..." 挑戰頁。

關鍵不是 header,是 TLS 指紋。 Cloudflare 會檢查 TLS 握手的指紋(JA3);一般程式的指紋一看就不是瀏覽器,直接被攔。

本專案用 cycletls 偽裝成 Chrome 的 TLS 指紋,讓 Cloudflare 以為請求來自真瀏覽器 → 放行。這樣不用開瀏覽器(比 Playwright / Selenium 輕一個量級、快、好部署),純 HTTP 就能拿到真實 JSON。

cycletls 底層是一個 Go 寫的 TLS client 子程序,server 啟動時開一次、全程共用。

現在有什麼

Tool

狀態

說明

search_jobs

✅ 真實資料

依關鍵字 + 多種篩選搜尋職缺,支援分頁

find_company

✅ 真實資料

用公司名稱找公司,回名片(companyId、產業、員工數、在徵職缺數);同名多家回候選不猜

get_job_detail

✅ 真實資料

取得單筆職缺完整詳情:完整 JD、薪資、地點、學經歷要求、技能、語言能力、福利、產業別

get_company_jobs

✅ 真實資料

列出某公司所有在徵職缺(分頁)

get_apply_analysis

✅ 真實資料

單筆職缺的應徵者分析:兩週內不重複應徵人數(真實數字)+性別/學歷/年齡/年資/語言/科系/技能/證照分布。只在你明確要求時才會被呼叫

search_jobs 參數

參數

必填

說明

keyword

✅

職務關鍵字,例如 Rust 工程師

area

工作地區名稱,例如 台北市、新竹(自動解析成 104 官方地區代碼查詢)。同名多區(如「信義區」有台北/基隆兩個)不會直接搜,改回 ambiguousArea 候選清單讓模型跟你確認

salaryMin

月薪下限(新台幣),例如 60000。薪資明確低於此值的濾掉;面議預設保留

excludeNegotiable

設 true 排除「面議」職缺。預設 false

excludeFeatured

設 true 排除 104 付費廣告職缺(featured=true 那些)。預設 false

jobCategory

職務類別名稱,例如 軟體工程師(自動解析成 104 官方職類代碼查詢)

remote

遠端:full 完全遠端 / partial 部分遠端 / any 皆可

jobType

工作性質:fulltime 全職 / parttime 兼職

experience

需求年資:under-1y / 1-3y / 3-5y / 5-10y / over-10y

sort

排序:newest 最新更新在前(掃新缺用,建議配 excludeFeatured=true)/ salary 待遇高→低。預設相關性

page

第幾頁(每頁 20 筆),預設 1。想看更多就往後翻

limit

一般職缺的回傳筆數上限,最多 20,預設 5。廣告位(featured=true)另計、不佔名額;要完整翻頁請用 20

篩選參數的實作眉角(都是觀察 104 官網 UI 實際請求 + metadata.total 實測得來的):

  1. salaryMin 要同時送 scmin + sctp=M + scstrict=1,缺了 scstrict 薪資篩選會被完全忽略。

  2. 「面議」薪資值是 0,104 預設保留(面議可能開很高)。excludeNegotiable 會排除它們。

  3. 薪資上限 9,999,999 是 104「不設上限」哨兵值,server 端已正規化成「N 元以上」。薪資前綴依原始 s10 類型標示(10=面議、30=時薪、40=日薪、50=月薪、60=年薪)—— 兼職多為時薪,別當月薪讀。

  4. remoteWork=1完全/2部分、ro=1全職/2兼職、jobexp=1/3/5/10/99(互斥年資級距)。

  5. 地區/職類用樹狀代碼表 + 剪枝:命中父節點(如「新竹縣市」)就用父代碼,不展開成一堆子代碼 —— 展開太多會讓 104 回 400。地區同名多處(如「信義區」)不聯集也不搜尋,回 ambiguousArea 請模型跟使用者確認(地理上不相干的地方聯集沒意義);職類多重命中則維持聯集(相關職類一起查通常是想要的)。

  6. 廣告偵測:104 會在結果最前面塞廣告(原始欄位 jobType=1),它會無視關鍵字(例如護理師搜尋跑出「COACH 精品銷售」)。每筆回傳 featured 旗標標記它,excludeFeatured=true 可整批濾掉。廣告是額外疊加在每頁 20 筆一般職缺之上(實測原始一頁可達 22 筆),limit 只數一般職缺、廣告不佔名額。jobType=2(付費優先位)仍符合關鍵字,視為有效結果不標記。搜尋列表刻意不含完整 JD(精簡、避免模型整理清單時把某筆網址對錯到別筆),完整內容用 get_job_detail。

  7. 掃新缺姿勢:sort=newest(order=16,實測)最新更新在前,但廣告位連排序都無視、照樣卡最前面 —— 配 excludeFeatured=true 才是乾淨的最新清單。另外 employeeCount=0 代表「未公開」(約半數公司不提供),不是 0 人。跨頁彙整請用 jobId 去重——最新排序是活水,新缺插入會使分頁窗口飄移,跨頁邊界可能重複。

  8. 公司名關鍵字不硬搜,翻譯暗號:關鍵字被 104 判定為公司名(如「聯發科」)時,回應是 data:[] + metadata.companyKeyword:true 且沒有 pagination。本專案把這個暗號翻譯成 companyKeyword 結構化提示(同 ambiguousArea 的「錯誤即資料」),引導模型走 find_company → get_company_jobs。刻意不用 searchJobs=1 硬搜:實測硬搜回 1080 筆全文模糊結果、第一筆是文曄集團(代理商)—— 靜默誤導比查無結果更糟。若 104 回了既無 pagination 也無 companyKeyword 的形狀,工具直接報錯(fail loud),不再靜默當成 0 筆。

  9. 應徵人數:列表只有區間,真實數字在另一支 API:搜尋 API 的 applyCnt 自 2026-09 起一律回 0(實測 44/44 筆),舊版 applyCount 因此恆為 0、看起來像「沒人應徵」—— 已改成 applyRange,由每筆的 analysisType 區間代碼對回職缺頁標籤(實測 1=05 人、2=610 人、3=11~30 人、4=30 人以上;沒驗證過的代碼回「未知區間(analysisType=N)」,不猜表)。要真實不重複人數與應徵者組成用 get_apply_analysis:它打「應徵分析」頁背後的 API,不登入也回完整資料(「登入解鎖完整分析」只是前端遮罩),104 每日統計一次。

欄位命名跨工具一致(都對照 104 原始欄位語意,避免同名不同物):

概念

search_jobs

get_job_detail

get_company_jobs

職缺代碼(slug,可餵回 get_job_detail)

jobId

jobId

jobId

職缺網址

url

url

url

地區(區級)

area

area

area

完整地址(區+街道)

—

location

—

需求年資

—

experience

experience

擅長工具/語言(C++、Linux)

skills

skills

—

職務技能(職類層級,如「軟體工程系統開發」)

—

jobSkills

—

公司頁網址(餵給 get_company_jobs)

companyUrl

companyUrl

—

是否為廣告位(jobType=1)

featured

—

—

更新日期(頁面的「MM/DD更新」)

appearDate

appearDate

—

員工人數

employeeCount(數字,0=未公開)

employees(字串)

—

兩週內應徵人數區間(職缺頁的「0~5 人」)

applyRange(字串;精確人數用 get_apply_analysis)

—

—

jobId 一律是 slug(如 7uqyj),不是 104 內部數字 —— slug 才能餵回 get_job_detail。公司同理:find_company 回的 companyId 是公司 slug(104 三支 API 對它的稱呼各不相同:encodedCustNo/custNo/網址尾碼,對外一律統一叫 companyId)。skills 到哪都是「具體技術」。appearDate 統一為 YYYY/MM/DD。公司職缺刻意不回日期:公司 API 原始只有 8/20 這種無年份格式,久未更新的殭屍職缺看起來永遠像最近更新(實測有 2025 年的缺混在裡面),跨年靜默誤導 —— 想要某筆的日期,把它的 jobId 餵給 get_job_detail 拿完整的。

find_company 參數

參數

必填

說明

name

✅

公司名稱:全名、簡稱或英文名皆可(如 聯發科、MediaTek —— 英文別名找得到中文本尊)

回傳「公司名片」:companyId(slug,可直接餵 get_company_jobs)、全名、公司頁網址、產業、地區、員工數、資本額、在徵職缺數。 不猜:唯一命中或名稱完全相符才回單一 company;多家符合回 candidates(≤5 筆)+hint 請模型跟使用者確認 —— 名片上的產業/在徵職缺數就是分辨「聯發科技(在徵 461)」和「全家便利商店聯發科店(在徵 1)」的依據。total 是 104 模糊比對的總數(含「簡介提及」的公司,會偏大)。

get_job_detail 參數

參數

必填

說明

jobUrlOrId

✅

職缺網址或代碼,例如 https://www.104.com.tw/job/7uqyj 或 7uqyj(用 search_jobs 回傳的 url)

get_company_jobs 參數

參數

必填

說明

companyUrlOrId

✅

公司代碼或網址(find_company 的 companyId,或其他工具回傳的 companyUrl)

keyword

在這家公司內搜職缺,如 C++。比對職稱+JD 內文(含「其他條件」欄)——「某公司有沒有 C++」用它,別翻頁自己過濾職稱

page

第幾頁(窗口大小=limit 所在檔位 20/50/100),預設 1

limit

一般職缺的回傳筆數上限,最多 100,預設 10。想一次拿完(如公司內搜 C++ 實測 98 筆)用 100;要完整翻頁,limit 請用檔位值 20/50/100 本身且中途不換——其他值會截掉每個窗口的尾端、下一頁不補回。置頂職缺(pinned=true)另計不佔名額、只在第 1 頁回

公司內搜尋(keyword)的眉角(實測):比對範圍含 JD 內文——聯發科 C++ 98 筆中,職稱含 C++ 的是 0 筆,靠職稱過濾會全漏。多字詞是 OR 不是 AND。total 不含置頂(465 缺 → total 462);帶 keyword 時置頂會變 0~1 筆。

get_apply_analysis 參數

參數

必填

說明

jobUrlOrId

✅

職缺網址或代碼(跟 get_job_detail 相同),例如 https://www.104.com.tw/job/7bsyk 或 7bsyk

回傳:total(兩週內不重複應徵人數,真實數字)、updateTime(104 每日統計一次)、以及 sex / edu / age / exp / language(含 levels 程度)/ major / skill / cert 分布,每項 { name, count, percent },0 人的項目已濾掉、人數多的排前面。major / skill / cert 只有前 10 名,加總不等於 total。 使用規矩:這支只在你明確要求「這個職缺的應徵者/應徵人數/競爭狀況」時才會被呼叫 —— 搜尋、看詳情、列公司職缺時不會順便呼叫,也不會為了比較競爭度批次呼叫(規矩寫在工具說明裡給模型看)。

工具怎麼串:

  • 想找「某家公司」的職缺 → find_company 拿 companyId → get_company_jobs(可帶 keyword 在公司內搜,如 C++)。別把公司名丟進 search_jobs —— 它會回 companyKeyword 提示請你走這條路。

  • search_jobs / get_job_detail 每筆都回 url(職缺)和 companyUrl(公司)兩個網址。

  • 想看某筆職缺完整內容 → 把它的 url 餵給 get_job_detail。

  • 想看「這家公司還有哪些缺」→ 把 companyUrl 餵給 get_company_jobs。

  • 想知道某筆職缺的競爭狀況(真實應徵人數、應徵者背景)→ 把 url 或 jobId 餵給 get_apply_analysis —— 只在你明確開口要時。

find_company ─ companyId ──────────────┐
search_jobs ─ url ──────→ get_job_detail  │
      │                        │       ▼
      └─ companyUrl ───────────┴──→ get_company_jobs(keyword=公司內搜)

104 內部 API 參考

主要 endpoint:

GET https://www.104.com.tw/jobs/search/api/jobs

必要 header:Referer: https://www.104.com.tw/jobs/search/、Accept-Language: zh-TW

常用查詢參數(本專案目前只用到部分,其餘供未來擴充):

參數

意義

範例值

keyword

關鍵字

自由文字

kwop

關鍵字運算

7(全符合)

searchJobs

強制執行職缺搜尋(抑制公司名轉介暗號)

1;本專案刻意不帶,改為翻譯暗號(見眉角 8)

order

排序

15 相關性(預設) · 16 最新(實測) · 13 薪資

page / pagesize

分頁

pagesize 建議 20

area

地區碼(逗號分隔)

查 Area.json(見下)

jobcat

職類碼(逗號分隔)

查 JobCat.json

scmin + scstrict=1

最低薪資

整數

remoteWork

遠端

1 完全遠端 · 2 部分 · 1,2 皆可(實測)

ro

全/兼職

1 全職 · 2 兼職(實測;wt 部分值會 400,不用)

jobexp

年資

1/3/5/10/99 = 1年下/1-3/3-5/5-10/10年上(互斥級距,實測)

edu

學歷

4,5,6 大學以上 等

地區 / 職類代碼表(放 static.104.com.tw,沒有 Cloudflare 擋,一般 fetch 就能拿):

https://static.104.com.tw/category-tool/json/Area.json
https://static.104.com.tw/category-tool/json/JobCat.json

其他 endpoint:

  • 職缺詳情:GET https://www.104.com.tw/job/ajax/content/{slug}(Referer 指向 /job/{slug})

  • 公司職缺:GET https://www.104.com.tw/api/companies/{code}/jobs?page=1&pageSize=20(回 list.topJobs + list.normalJobs;pageSize 只吃 20/50/100;可加 keyword= 在公司內搜,比對職稱+JD 內文)

  • 公司搜尋:GET https://www.104.com.tw/company/ajax/list?keyword=…&mode=s&page=1&pageSize=10(Referer 指向 /company/search/;公司 slug 欄位叫 encodedCustNo;模糊比對含簡介全文)

  • 應徵分析:GET https://www.104.com.tw/jb/104i/applyAnalysisToJob/all?job_no={十進位 jobNo}(Referer 指向 /jobs/apply/analysis/{slug};jobNo = parseInt(slug, 36),網址上的 slug 是 base36;不登入也回完整資料;每個維度底下是「數字字串 key 的物件」不是陣列,旁邊混著 update_time / total;percent 字串/數字混用;language[].level 有時物件有時陣列)

檔案結構

src/
  index.ts            進入點:建 server、掛 tool、接 stdio、處理關閉
  config.ts           所有設定 / 魔術數字(JA3 指紋、endpoint、節流區間…)
  types.ts            乾淨型別 + normalizeJob / JobDetail / CompanyJob(防腐層)
  query.ts            純函式:組查詢網址、client 端過濾、enum 對照
  slug.ts             從 104 網址取出職缺 slug / 公司碼(types/query 共用)
  codes.ts            地區/職類「名稱→官方代碼」解析(樹狀比對+剪枝,快取代碼表)
  api/
    httpClient.ts     cycletls 單例(TLS 指紋偽裝)
    throttle.ts       禮貌性隨機節流 1.5~3.5s
    job104.ts         104 抓取層:組 URL → 打 API → 重試 → 正規化
  tools/
    searchJobs.ts     search_jobs
    getJobDetail.ts   get_job_detail
    getCompanyJobs.ts get_company_jobs
    findCompany.ts    find_company
    getApplyAnalysis.ts get_apply_analysis
scripts/
  smoke-test.mjs      手動發 JSON-RPC 驗證,不用開 Claude 也能測
test/
  types.test.mjs      normalize 邏輯(薪資格式、面議、哨兵值、applyRange…)
  query.test.mjs      組網址 / slug / 公司碼 / 過濾 / enum 對照
  codes.test.mjs      代碼表樹狀比對 + 剪枝
  merge.test.mjs      公司職缺置頂/一般合併(置頂不佔 limit 名額)
  apply-analysis.test.mjs  slug→jobNo、應徵分析網址、normalizeApplyAnalysis(形狀陷阱)
  evals-score.test.mjs     evals 純評分函式

開發

npm run build                 # 編譯 src → dist
npm test                      # 跑單元測試(先 build 再 node --test,零額外依賴)
node scripts/smoke-test.mjs   # 煙霧測試(連真實 104)
npm run inspect               # 開 MCP Inspector GUI 除錯

改完 code 要 npm run build,然後重啟 Claude Code(或用 /mcp reconnect)才會生效 —— client 只在 session 啟動時抓一次工具清單。

測試策略:純邏輯(normalize、組網址、過濾)都抽到 types.ts / query.ts,用 Node 內建 node --test 測,快又不用連網 —— 改壞馬上知道。碰網路的部分(job104.ts / httpClient.ts)用 smoke-test 對真實 104 驗證。

⚠️ 免責聲明

  • 104 沒有公開官方 API。本專案使用的是網頁前端的非官方內部 endpoint,隨時可能因 104 改版而失效。

  • 自動化存取可能違反 104 的服務條款。本專案僅供個人、低頻、學習用途。

  • 請勿拿去做高頻抓取、大量爬取,或架成公開服務 —— 容易被封鎖,也有法律風險。

  • 本專案已內建禮貌性節流(每次請求間隔隨機 1.5~3.5 秒),請勿移除或調低。

  • 使用本專案造成的任何後果,使用者自負。

Available Tools

4 tools
find_company用名稱找 104 公司A

用公司名稱找 104 上的公司,回傳公司名片:companyId(公司代碼,可直接餵給 get_company_jobs)、全名、公司頁網址、產業、地區、員工數、資本額、在徵職缺數。比對是模糊的:英文別名(如 MediaTek)也找得到中文本尊,但 total 含「簡介提及」的公司會偏大。唯一命中或名稱完全相符 → 回單一 company;多家符合 → 回 candidates 候選清單,此時請向使用者確認是哪一家(用產業/地區/在徵職缺數分辨),不要自行猜選。「某公司有沒有某類職缺」的標準流程:find_company 拿 companyId → get_company_jobs 帶 keyword。

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes公司名稱 —— 全名、常用簡稱或英文名皆可,如 '聯發科'、'台積電'、'MediaTek'

TDQS

A4.4/5.0
Behavior4/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 fuzzy matching, the total count caveat for introduction mentions, and the single-vs-candidates decision rule. It does not state what happens when no company matches, which is a minor but relevant gap.

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 front-loaded with the core action and output, then moves through matching behavior, user-confirmation guidance, and the downstream workflow in a logical order. Every sentence carries operational value with no redundant filler.

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 tool with no output schema and no annotations, it covers the input contract, output fields, ambiguous-result handling, and integration with get_company_jobs. The only notable omission is the no-match return behavior; otherwise an agent has enough to call it correctly.

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 single name parameter is already fully described in the schema with full-name/abbreviation/English examples, so schema coverage is 100%. The description adds extra meaning by explaining alias matching and fuzziness, which helps the agent understand acceptable inputs and edge cases.

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 states the tool finds companies on 104 by name and enumerates the returned 'company card' fields, including the companyId that feeds get_company_jobs. This clearly defines the verb+resource and distinguishes it from job-search siblings.

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?

It explicitly prescribes the standard flow for checking whether a company has certain job types (find_company → get_company_jobs with keyword) and tells the agent to confirm with the user rather than guess when multiple candidates appear. It does not explicitly contrast with search_jobs or get_job_detail, but the intended use case is clear.

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

get_company_jobs列出某公司所有職缺A

列出「某一家指定公司」在 104 上在徵的職缺(職稱、地區、薪資、學經歷要求、網址),可分頁。公司用 find_company 回傳的 companyId,或 search_jobs / get_job_detail 回傳的 companyUrl。帶 keyword 可在這家公司內搜職缺(比對職稱與 JD 內文,含「其他條件」欄 —— 「某公司有沒有 C++」這種問題用它,別自己翻頁過濾職稱)。⚠️ keyword 多字詞是 OR 不是 AND,要同時符合請分次搜再交集。要完整翻頁,limit 請直接用檔位值本身(20、50 或 100)且全程不變 —— 非檔位值的 limit 會截掉每個窗口的尾端且下一頁不補回。置頂職缺(pinned=true)只在第 1 頁回、不佔 limit 名額;total 不含置頂。

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo第幾頁(窗口大小=limit 所在檔位 20/50/100),預設 1。完整翻頁時 limit 請用檔位值且中途不換
limitNo一般職缺的回傳筆數上限,最多 100,預設 10。想一次拿完(如公司內搜 C++)用 100;要完整翻頁請用檔位值 20/50/100 本身(其他值會截掉窗口尾端);置頂職缺另計、不佔名額
keywordNo在這家公司內搜職缺的關鍵字(比對職稱與 JD 內文)。例如 'C++'。多字詞是 OR,要 AND 請分次搜再交集
companyUrlOrIdYes公司代碼或網址:find_company 回傳的 companyId,或 search_jobs / get_job_detail 回傳的 companyUrl。例如 '12noppgo' 或 'https://www.104.com.tw/company/1a2x6blghh'

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations provided, the description carries the full disclosure burden, and it covers the critical non-obvious behaviors: complete pagination requires gear-value limits (20/50/100) held constant, non-gear limits silently truncate window tails with no backfill, pinned=true jobs only appear on page 1 without consuming limit quota, and total excludes pinned jobs. These are exactly the traps an agent cannot infer from schema.

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?

Purpose is front-loaded in the first sentence, followed by parameter sourcing, keyword usage, then pagination and pinned-job caveats. The text is dense but every clause earns its place — the ⚠️ warnings cover behaviors that would otherwise cause silent data loss or truncated results.

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

Completeness5/5

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

For a 4-param tool with no annotations and no output schema, the description covers the returned fields, pagination semantics, keyword matching operators, pinned-job behavior, and parameter provenance from each sibling tool. Nothing an agent needs in order to invoke it correctly or interpret results is missing.

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?

Schema coverage is 100%, so every parameter is already documented. The description adds value beyond the schema: the gear-value pagination rule, keyword matching scope (JD 內文含其他條件欄), the OR-not-AND semantics, and the provenance of companyUrlOrId from sibling tool outputs. Only slightly held back by the schema already carrying most parameter details.

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 opens with a precise verb+resource statement: listing a specific company's job openings on 104, with the returned fields enumerated (職稱、地區、薪資、學經歷要求、網址) and pagination noted. It also differentiates from the search_jobs sibling by positioning itself as the company-scoped tool for questions like 'does this company have C++'.

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

Usage Guidelines5/5

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

Explicit when-to-use guidance is present: '某公司有沒有 C++' 這種問題用它, 別自己翻頁過濾職稱. It also instructs where to source companyUrlOrId from (find_company, search_jobs, get_job_detail) and warns about keyword OR semantics with the workaround (要 AND 請分次搜再交集). Alternatives and exclusions are stated rather than implied.

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

get_job_detail取得 104 職缺詳情A

取得單筆 104 職缺的完整詳情:完整職務說明、薪資、地點、學經歷要求、需求技能、語言能力、福利、產業別。傳入 search_jobs 結果中的職缺網址(url 欄位)。

ParametersJSON Schema
NameRequiredDescriptionDefault
jobUrlOrIdYes職缺網址或代碼,例如 'https://www.104.com.tw/job/7uqyj' 或 '7uqyj'(用 search_jobs 回傳的 url)

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description must carry the behavioral burden itself. It clearly signals a read-only fetch by saying 取得, and it sets expectations about what content will be returned. It does not describe error behavior or not-found cases, which is a minor gap for such a simple fetch tool.

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 only two sentences with no filler. It front-loads the core purpose, lists the content categories, and then gives the input binding instruction. Every sentence contributes value, and structure is clean and scannable.

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 single-parameter read tool with no output schema, the description adequately covers the purpose, the sort of data the agent will receive, and how to construct the input. A small residual gap is the lack of clarification around missing/invalid job URLs, but overall the instruction is complete enough for correct invocation.

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?

The input schema already provides full parameter documentation at 100% coverage, including format and example and the search_jobs context. The description repeats the instruction to use the url field from search_jobs but does not add substantial new semantic meaning beyond the schema.

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 states a specific action and resource: retrieving complete details for a single 104 job, and enumerates the content fields (薪資、地點、學經歷要求、技能、福利 etc.). It references search_jobs for the input URL, which helps distinguish it from the sibling search and company-level tools.

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 gives explicit workflow guidance: pass the jobUrl from search_jobs results. It tacitly says to use this tool when a single job's complete details are needed rather than the search tool's results, though it does not explicitly exclude alternatives like find_company.

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

search_jobs搜尋 104 職缺A

依關鍵字與篩選條件搜尋台灣 104 人力銀行的即時職缺,回傳職稱、公司、地區、薪資、需求技能與職缺網址。支援地區、薪資下限、職類、遠端、全/兼職、年資篩選,以及分頁。若 area 同名多處(如「信義區」有台北市與基隆市兩個),不會直接搜尋,改回傳 ambiguousArea 候選清單 —— 此時請向使用者確認是哪一個,再用完整名稱(如「台北市信義區」)重新搜尋。limit 只數一般職缺:廣告位(featured=true)另計、不佔名額。要完整翻頁請用 limit=20(上游每頁固定 20 筆一般職缺);跨頁彙整時用 jobId 去重(最新排序下新缺插入會使分頁窗口飄移)。keyword 適合職務/技能詞;輸入公司名稱時 104 不執行搜尋,本工具會回 companyKeyword 提示 —— 此時請改用 find_company 找到公司,再用 get_company_jobs 取得該公司職缺。

ParametersJSON Schema
NameRequiredDescriptionDefault
areaNo工作地區名稱,例如 '台北市'、'新竹'(會解析成 104 官方地區代碼查詢)
pageNo第幾頁(每頁 20 筆),預設 1。想看更多職缺就往後翻頁
sortNo排序:newest 最新更新在前(找新開職缺/掃描擴編用,建議搭配 excludeFeatured=true,否則廣告位仍會無視排序卡在最前面)/ salary 待遇由高到低。不給則用 104 預設的相關性排序
limitNo一般職缺的回傳筆數上限,最多 20,預設 5。廣告位(featured=true)另計、不佔名額;要完整翻頁請用 20
remoteNo遠端工作:full 完全遠端 / partial 部分遠端 / any 兩者皆可
jobTypeNo工作性質:fulltime 全職 / parttime 兼職
keywordYes職務關鍵字,例如 'Rust 工程師'
salaryMinNo月薪下限(新台幣),例如 60000。薪資明確低於此值的濾掉;面議預設保留
experienceNo需求年資級距:under-1y(1年以下)/1-3y/3-5y/5-10y/over-10y(10年以上)
jobCategoryNo職務類別名稱,例如 '軟體工程師'、'行銷企劃'(會解析成 104 官方職類代碼查詢)
excludeFeaturedNo排除 104 付費推廣/廣告職缺(結果中 featured=true 的),預設 false。這些會被 104 硬塞在最前面、常不符合搜尋條件;想只看自然結果時設 true
excludeNegotiableNo排除「面議」(沒寫薪資)的職缺,預設 false。想只看有明確薪資時設 true

TDQS

A5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden and fully delivers. It discloses non-obvious behaviors: featured ads are excluded from limit and ignore sort order, ambiguous area returns an ambiguousArea candidate list instead of searching, company keywords produce a companyKeyword hint, and newest-sort pagination windows drift and require jobId dedup. This goes well beyond the minimum.

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 long but every sentence earns its place for a 12-parameter tool with no annotations. It is front-loaded with the core purpose, then progressively covers edge cases, pagination, and sibling tool routing. The structure is logical and dense without redundancy.

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

Completeness5/5

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

Given the tool's complexity — 12 parameters, no output schema, no annotations — the description is remarkably complete. It covers return contents, filter semantics, ambiguous routing, ad behavior, pagination and dedup, and company-name fallbacks. An agent has enough information to invoke this tool correctly in nearly all scenarios.

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

Parameters5/5

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

Schema coverage is 100%, which sets a baseline of 3, but the description adds substantial meaning beyond the schema: limit only counts regular jobs while featured ads are separate, salaryMin preserves '面議' by default, sort=newest is best paired with excludeFeatured=true, and keyword is for job titles/skills only — not company names. Each parameter's real-world behavior is clarified.

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 opens with a specific verb + resource: search real-time 104 job bank openings by keyword and filters, and lists the returned fields (title, company, region, salary, skills, URL). It also distinguishes itself from siblings by explicitly routing company-name queries to find_company and get_company_jobs.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: use find_company then get_company_jobs when the keyword is a company name, and instructs the agent to ask the user for clarification when area is ambiguous. It also provides pagination strategy (limit=20 for full pages, jobId for de-duplication) and suggests excludeFeatured=true for newest sort.

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. 4 tool updatesv0.2.0
    • First observedfind_company
    • First observedget_company_jobs
    • First observedget_job_detail
    • First observedsearch_jobs

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct retrieval scope: global job search, fuzzy company lookup, single-job details, and per-company job listings. Even though search_jobs and get_company_jobs both return job lists, the descriptions clearly separate global vs. company-scoped search and include cross-references to guide selection.

Naming Consistency5/5

All tool names follow a lowercase snake_case verb_noun pattern: search_jobs, find_company, get_job_detail, get_company_jobs. The slight verb variation between search/find/get maps sensibly to different retrieval actions, and there is no mixing of styles or unpredictable naming.

Tool Count5/5

Four tools is a well-scoped size for a focused job-board client. Each tool covers a necessary step in the core workflows—searching jobs, inspecting a job listing, finding a company, and listing a company's jobs—without redundancy or obvious bloat.

Completeness5/5

The tool surface covers the main job-seeker flows end to end: global filtered search with pagination, detailed job lookup, company resolution by name, and targeted search inside a specific company. The described handling of ambiguous areas, company-name searches, and pagination edge cases closes the important gaps, leaving no dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Searches 104 job listings with natural-language filters and retrieves full postings via MCP tools.
    3
    27 PyPI
    27
    MIT
  • F
    license
    Not graded
    quality
    D
    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.
    -
  • F
    license
    A
    quality
    B
    maintenance
    This MCP server lets AI assistants search job listings on Taiwan's 104 Job Bank, read full job details, and prepare applications with human-in-the-loop confirmation before final submission.
    3
    3
    -