mcp-server-104
mcp-server-104
대만 104 인력은행(104人力銀行)의 MCP 서버입니다. Claude(또는 모든 MCP 클라이언트)가 104의 실시간 채용공고를 직접 검색할 수 있게 해줍니다.
이 도구가 당신에게 적합한가요?
상황 | 최적의 도구 |
가끔 직접 구직할 때 | 그냥 104 웹사이트 접속 |
일회성 크롤러를 작성하고 싶을 때 | Playwright / cycletls 스크립트면 충분, MCP 불필요 |
Claude에게 채용공고 분석/비교/정리/자동화를 시키고 싶을 때 | 이 MCP |
Related MCP server: LinkedIn MCP Server
설치
아래 세 가지 중 하나를 선택하세요. 사용 중인 클라이언트에 따라 고르면 됩니다:
A: 바로가기 명령어가 있는 클라이언트 — 한 줄이면 설정이 자동으로 완료됩니다:
claude mcp add job104 -- npx -y mcp-server-104 # Claude Codecodex mcp add job104 -- npx -y mcp-server-104 # OpenAI Codex CLI(新版才有;舊版走 B 的 TOML)B: 설정을 수동으로 붙여넣는 클라이언트 — 해당 클라이언트의 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는 같은 작업을 합니다: 클라이언트에게 "npx로 이 서버를 실행하라"고 알려주는 것입니다. 핵심은 어디서나
npx -y mcp-server-104이며, 차이는 각 클라이언트가 이를 등록하는 방식뿐입니다.⚠️ ChatGPT 웹/데스크톱 버전은 이런 로컬(stdio) 서버에 연결할 수 없습니다 — 원격 URL형 MCP만 지원하며, 클라우드상에는
npx를 실행할 수 있는 사용자의 컴퓨터가 없기 때문입니다.
C: 개발자, 코드를 수정하고 싶은 경우 — 이 repo를 clone한 후:
npm install && npm run build
claude mcp add job104 -- node /你的路徑/104-mcp-server/dist/index.js일상적인 명령어와 테스트 전략은 아래 '개발' 섹션을 참조하세요.
데이터를 가져오는 방법
104의 검색 API는 Cloudflare 봇 방어 뒤에 숨어 있습니다. curl이나 Node fetch(Referer / User-Agent를 포함하더라도)로 접근하면 차단됩니다 — 403 또는 Cloudflare의 "Just a moment..." 챌린지 페이지가 반환됩니다.
핵심은 헤더가 아니라 TLS 지문입니다. Cloudflare는 TLS 핸드셰이크의 지문(JA3)을 검사합니다. 일반 프로그램의 지문은 브라우저가 아니므로 바로 차단됩니다.
이 프로젝트는 cycletls 를 사용해 Chrome의 TLS 지문을 위장하여 Cloudflare가 실제 브라우저에서 온 요청으로 착각하도록 합니다 → 통과. 이렇게 하면 브라우저를 실행할 필요 없이(Playwright / Selenium보다 가볍고, 빠르며, 배포가 쉬움) 순수 HTTP만으로 실제 JSON을 얻을 수 있습니다.
cycletls는 내부적으로 Go로 작성된 TLS 클라이언트 하위 프로세스로, 서버 시작 시 한 번 실행되고 전체 기간 동안 공유됩니다.
현재 제공되는 기능
Tool | 상태 | 설명 |
| ✅ 실제 데이터 | 키워드 + 다양한 필터로 채용공고 검색, 페이지네이션 지원 |
| ✅ 실제 데이터 | 단일 채용공고의 전체 상세 정보: 전체 JD, 급여, 위치, 학력/경력 요구사항, 기술, 어학능력, 복리후생, 업종 |
| ✅ 실제 데이터 | 특정 회사의 모든 채용공고 목록(페이지네이션) |
search_jobs 매개변수
매개변수 | 필수 | 설명 |
| ✅ | 직무 키워드, 예: |
| 근무 지역명, 예: | |
| 최소 월급(대만 달러), 예: | |
|
| |
|
| |
| 직무 카테고리명, 예: | |
| 원격: | |
| 근무 형태: | |
| 요구 경력: | |
| 페이지 번호(페이지당 20건), 기본값 1. 더 보려면 계속 넘김 | |
| 이 페이지의 최대 반환 건수, 최대 20, 기본값 5 |
필터 매개변수 구현 세부사항(104 공식 웹사이트 UI의 실제 요청 +
metadata.total실측으로 얻은 결과):
salaryMin은scmin+sctp=M+scstrict=1을 함께 보내야 합니다.scstrict가 없으면 급여 필터가 완전히 무시됩니다.'면접 시 협의' 급여 값은
0이며, 104는 기본적으로 유지합니다(면접 시 협의가 매우 높을 수 있음).excludeNegotiable이 이를 제외합니다.최대 급여
9,999,999는 104의 '상한 없음' 센티널 값으로, 서버에서 'N원 이상'으로 정규화됩니다. 급여 접두사는 원본s10유형으로 표시됩니다(10=면접 시 협의, 30=시급, 40=일급, 50=월급, 60=연봉) — 파트타임은 대부분 시급이므로 월급으로 오해하지 마세요.
remoteWork=1 완전/2 부분,ro=1 정규/2 파트,jobexp=1/3/5/10/99(상호 배타적 경력 구간).지역/직무는 트리 코드 테이블 + 가지치기 사용: 상위 노드(예: '신주현시')가 일치하면 상위 코드를 사용하고 하위 코드로 확장하지 않음 — 너무 많이 확장하면 104가
400을 반환합니다. 지역이 같은 이름으로 여러 곳(예: '信義區')이면 합집합도 검색도 하지 않고ambiguousArea를 반환하여 모델이 사용자와 확인하도록 함(지리적으로 무관한 곳의 합집합은 의미 없음). 직무 카테고리가 여러 개 일치하면 합집합 유지(관련 직무를 함께 조회하는 것이 보통 원하는 결과).광고 감지: 104는 결과 맨 앞에 광고를 넣습니다(원본 필드
jobType=1). 이는 키워드를 무시합니다(예: 간호사 검색에 'COACH 명품 판매'가 나타남). 각 항목에featured플래그를 표시하며,excludeFeatured=true로 일괄 필터링할 수 있습니다.jobType=2(유료 우선 노출)는 여전히 키워드와 일치하므로 유효한 결과로 간주하여 표시하지 않습니다. 검색 목록에는 의도적으로 전체 JD를 포함하지 않습니다(간결성 + 모델이 목록을 정리할 때 특정 URL을 다른 항목에 잘못 매칭하는 것을 방지). 전체 내용은get_job_detail을 사용하세요.
세 도구 간 필드 이름 일관성(모두 104 원본 필드 의미를 따르며, 동음이의어 방지):
개념
search_jobs
get_job_detail
get_company_jobs
채용공고 코드(slug,
get_job_detail에 다시 전달 가능)
jobId
jobId
jobId채용공고 URL
url
url
url지역(구 단위)
area
area
area전체 주소(구+도로)
—
location—
요구 경력
—
experience
experience보유 기술/언어(C++, Linux)
skills
skills—
직무 스킬(직무 계층, 예: '소프트웨어 엔지니어링 시스템 개발')
—
jobSkills—
회사 페이지 URL(
get_company_jobs에 전달)
companyUrl
companyUrl—
광고 여부(
jobType=1)
featured—
—
업데이트 날짜(페이지의 'MM/DD 업데이트')
appearDate
appearDate—
jobId는 항상 slug(예:7uqyj)이며 104 내부 숫자가 아닙니다 — slug여야get_job_detail에 다시 전달할 수 있습니다.skills는 어디서나 '구체적인 기술'입니다.appearDate는 항상YYYY/MM/DD형식입니다. 회사 채용공고에는 의도적으로 날짜를 반환하지 않습니다: 회사 API의 원본에는8/20과 같은 연도 없는 형식만 있어서, 오래된 좀비 채용공고가 항상 최근에 업데이트된 것처럼 보입니다(실측 결과 2025년 공고가 섞여 있음). 연도가 지나면 조용히 오해를 불러일으킵니다 — 특정 항목의 날짜가 필요하면 해당jobId를get_job_detail에 전달하여 전체 정보를 얻으세요.
get_job_detail 매개변수
매개변수 | 필수 | 설명 |
| ✅ | 채용공고 URL 또는 코드, 예: |
get_company_jobs 매개변수
매개변수 | 필수 | 설명 |
| ✅ | 회사 URL 또는 코드, 예: |
| 페이지 번호(페이지당 20건), 기본값 1 | |
| 이 페이지의 최대 반환 건수, 최대 20, 기본값 10 |
세 도구를 연결하는 방법:
search_jobs/get_job_detail은 각 항목에url(채용공고)과companyUrl(회사) 두 개의 URL을 반환합니다.특정 채용공고의 전체 내용을 보려면 → 해당
url을get_job_detail에 전달.'이 회사의 다른 공고'를 보려면 →
companyUrl을get_company_jobs에 전달(이것은 지정된 회사의 채용공고 목록이지 키워드 검색이 아닙니다).
search_jobs ─ url ──────→ get_job_detail
│ │
└─ companyUrl ───────────┴──→ get_company_jobs104 내부 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
일반적인 쿼리 매개변수(이 프로젝트는 일부만 사용하며, 나머지는 향후 확장용):
매개변수 | 의미 | 예시 값 |
| 키워드 | 자유 텍스트 |
| 키워드 연산 |
|
| 정렬 |
|
| 페이지네이션 |
|
| 지역 코드(쉼표 구분) |
|
| 직무 코드(쉼표 구분) |
|
| 최소 급여 | 정수 |
| 원격 |
|
| 정규/파트 |
|
| 경력 |
|
| 학력 |
|
지역/직무 코드 테이블(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반환)
파일 구조
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
scripts/
smoke-test.mjs 手動發 JSON-RPC 驗證,不用開 Claude 也能測
test/
types.test.mjs normalize 邏輯(薪資格式、面議、哨兵值…)
query.test.mjs 組網址 / slug / 公司碼 / 過濾 / enum 對照
codes.test.mjs 代碼表樹狀比對 + 剪枝개발
npm run build # 編譯 src → dist
npm test # 跑單元測試(先 build 再 node --test,零額外依賴)
node scripts/smoke-test.mjs # 煙霧測試(連真實 104)
npm run inspect # 開 MCP Inspector GUI 除錯코드를 수정한 후에는 npm run build를 실행한 다음 Claude Code를 재시작(또는 /mcp로 reconnect)해야 적용됩니다 — 클라이언트는 세션 시작 시에만 도구 목록을 한 번 가져옵니다.
테스트 전략: 순수 로직(normalize, URL 구성, 필터링)은 모두 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 toolsfind_company用名稱找 104 公司A
用公司名稱找 104 上的公司,回傳公司名片:companyId(公司代碼,可直接餵給 get_company_jobs)、全名、公司頁網址、產業、地區、員工數、資本額、在徵職缺數。比對是模糊的:英文別名(如 MediaTek)也找得到中文本尊,但 total 含「簡介提及」的公司會偏大。唯一命中或名稱完全相符 → 回單一 company;多家符合 → 回 candidates 候選清單,此時請向使用者確認是哪一家(用產業/地區/在徵職缺數分辨),不要自行猜選。「某公司有沒有某類職缺」的標準流程:find_company 拿 companyId → get_company_jobs 帶 keyword。
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | 公司名稱 —— 全名、常用簡稱或英文名皆可,如 '聯發科'、'台積電'、'MediaTek' |
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 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.
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.
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.
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.
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.
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 不含置頂。
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 第幾頁(窗口大小=limit 所在檔位 20/50/100),預設 1。完整翻頁時 limit 請用檔位值且中途不換 | |
| limit | No | 一般職缺的回傳筆數上限,最多 100,預設 10。想一次拿完(如公司內搜 C++)用 100;要完整翻頁請用檔位值 20/50/100 本身(其他值會截掉窗口尾端);置頂職缺另計、不佔名額 | |
| keyword | No | 在這家公司內搜職缺的關鍵字(比對職稱與 JD 內文)。例如 'C++'。多字詞是 OR,要 AND 請分次搜再交集 | |
| companyUrlOrId | Yes | 公司代碼或網址:find_company 回傳的 companyId,或 search_jobs / get_job_detail 回傳的 companyUrl。例如 '12noppgo' 或 'https://www.104.com.tw/company/1a2x6blghh' |
TDQS
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.
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.
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.
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.
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.
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 欄位)。
| Name | Required | Description | Default |
|---|---|---|---|
| jobUrlOrId | Yes | 職缺網址或代碼,例如 'https://www.104.com.tw/job/7uqyj' 或 '7uqyj'(用 search_jobs 回傳的 url) |
TDQS
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.
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.
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.
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.
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.
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 取得該公司職缺。
| Name | Required | Description | Default |
|---|---|---|---|
| area | No | 工作地區名稱,例如 '台北市'、'新竹'(會解析成 104 官方地區代碼查詢) | |
| page | No | 第幾頁(每頁 20 筆),預設 1。想看更多職缺就往後翻頁 | |
| sort | No | 排序:newest 最新更新在前(找新開職缺/掃描擴編用,建議搭配 excludeFeatured=true,否則廣告位仍會無視排序卡在最前面)/ salary 待遇由高到低。不給則用 104 預設的相關性排序 | |
| limit | No | 一般職缺的回傳筆數上限,最多 20,預設 5。廣告位(featured=true)另計、不佔名額;要完整翻頁請用 20 | |
| remote | No | 遠端工作:full 完全遠端 / partial 部分遠端 / any 兩者皆可 | |
| jobType | No | 工作性質:fulltime 全職 / parttime 兼職 | |
| keyword | Yes | 職務關鍵字,例如 'Rust 工程師' | |
| salaryMin | No | 月薪下限(新台幣),例如 60000。薪資明確低於此值的濾掉;面議預設保留 | |
| experience | No | 需求年資級距:under-1y(1年以下)/1-3y/3-5y/5-10y/over-10y(10年以上) | |
| jobCategory | No | 職務類別名稱,例如 '軟體工程師'、'行銷企劃'(會解析成 104 官方職類代碼查詢) | |
| excludeFeatured | No | 排除 104 付費推廣/廣告職缺(結果中 featured=true 的),預設 false。這些會被 104 硬塞在最前面、常不符合搜尋條件;想只看自然結果時設 true | |
| excludeNegotiable | No | 排除「面議」(沒寫薪資)的職缺,預設 false。想只看有明確薪資時設 true |
TDQS
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.
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.
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.
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.
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.
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.
4 tool updates
v0.2.0- First observed
find_company - First observed
get_company_jobs - First observed
get_job_detail - First observed
search_jobs
TDQS
Scored across 4 tools
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.
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.
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.
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
Related MCP Connectors
Search live startup jobs from Claude, Cursor, or ChatGPT via MCP. Free, no account needed.
JobsPipe — data pipeline of every job posting on the web. Search live, normalized job postings from 30+ ATS feeds and job boards for AI agents via MCP.
Job search for Switzerland. Searches current listings on funkyjobs.ch by keyword, place with radius, workload, category and publishing date, and fetches a single listing with employer, location, workload and salary where stated. Read-only, no account needed. Docs: https://www.funkyjobs.ch/mcp-connector
Public MCP server for discovering open jobs. Search, filter, and get application links.
Related MCP Servers
- AlicenseAqualityBmaintenanceSearches 104 job listings with natural-language filters and retrieves full postings via MCP tools.327 PyPI27MIT
- FlicenseNot gradedqualityDmaintenanceEnables 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.-
- FlicenseNot gradedqualityBmaintenanceEnables 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.-
- FlicenseAqualityBmaintenanceThis 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.33-