Skip to main content
Glama
a7512cs

mcp-server-104

by a7512cs

mcp-server-104

대만 104 인력은행(104人力銀行)의 MCP 서버입니다. Claude(또는 모든 MCP 클라이언트)가 104의 실시간 채용공고를 직접 검색할 수 있게 해줍니다.

이 도구가 당신에게 적합한가요?

상황

최적의 도구

가끔 직접 구직할 때

그냥 104 웹사이트 접속

일회성 크롤러를 작성하고 싶을 때

Playwright / cycletls 스크립트면 충분, MCP 불필요

Claude에게 채용공고 분석/비교/정리/자동화를 시키고 싶을 때

이 MCP

Related MCP server: job-source-mcp

설치

아래 세 가지 중 하나를 선택하세요. 사용 중인 클라이언트에 따라 고르면 됩니다:

A: 바로가기 명령어가 있는 클라이언트 — 한 줄이면 설정이 자동으로 완료됩니다:

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: 설정을 수동으로 붙여넣는 클라이언트 — 해당 클라이언트의 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

상태

설명

search_jobs

✅ 실제 데이터

키워드 + 다양한 필터로 채용공고 검색, 페이지네이션 지원

get_job_detail

✅ 실제 데이터

단일 채용공고의 전체 상세 정보: 전체 JD, 급여, 위치, 학력/경력 요구사항, 기술, 어학능력, 복리후생, 업종

get_company_jobs

✅ 실제 데이터

특정 회사의 모든 채용공고 목록(페이지네이션)

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

page

페이지 번호(페이지당 20건), 기본값 1. 더 보려면 계속 넘김

limit

이 페이지의 최대 반환 건수, 최대 20, 기본값 5

필터 매개변수 구현 세부사항(104 공식 웹사이트 UI의 실제 요청 + metadata.total 실측으로 얻은 결과):

  1. salaryMinscmin + sctp=M + scstrict=1을 함께 보내야 합니다. scstrict가 없으면 급여 필터가 완전히 무시됩니다.

  2. '면접 시 협의' 급여 값은 0이며, 104는 기본적으로 유지합니다(면접 시 협의가 매우 높을 수 있음). excludeNegotiable이 이를 제외합니다.

  3. 최대 급여 9,999,999는 104의 '상한 없음' 센티널 값으로, 서버에서 '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로 일괄 필터링할 수 있습니다. 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년 공고가 섞여 있음). 연도가 지나면 조용히 오해를 불러일으킵니다 — 특정 항목의 날짜가 필요하면 해당 jobIdget_job_detail에 전달하여 전체 정보를 얻으세요.

get_job_detail 매개변수

매개변수

필수

설명

jobUrlOrId

채용공고 URL 또는 코드, 예: https://www.104.com.tw/job/7uqyj 또는 7uqyj(search_jobs가 반환한 url 사용)

get_company_jobs 매개변수

매개변수

필수

설명

companyUrlOrId

회사 URL 또는 코드, 예: https://www.104.com.tw/company/1a2x6blghh 또는 1a2x6blghh

page

페이지 번호(페이지당 20건), 기본값 1

limit

이 페이지의 최대 반환 건수, 최대 20, 기본값 10

세 도구를 연결하는 방법:

  • search_jobs / get_job_detail은 각 항목에 url(채용공고)과 companyUrl(회사) 두 개의 URL을 반환합니다.

  • 특정 채용공고의 전체 내용을 보려면 → 해당 urlget_job_detail에 전달.

  • '이 회사의 다른 공고'를 보려면 → companyUrlget_company_jobs에 전달(이것은 지정된 회사의 채용공고 목록이지 키워드 검색이 아닙니다).

search_jobs ─ url ──────→ get_job_detail
      │                        │
      └─ companyUrl ───────────┴──→ get_company_jobs

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(모두 일치)

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 반환)

파일 구조

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초 랜덤 대기)이 내장되어 있습니다. 제거하거나 낮추지 마십시오.

  • 이 프로젝트 사용으로 인한 모든 결과에 대한 책임은 사용자에게 있습니다.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables users to search LinkedIn's public job listings with advanced filters like location, salary, and experience level. It allows MCP-compatible clients to retrieve real-time job opportunities without requiring LinkedIn authentication or API keys.
    1
    2
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Searches 104 job listings with natural-language filters and retrieves full postings via MCP tools.
    3
    22
    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.

View all related MCP servers

Related MCP Connectors

  • Search live startup jobs from Claude, Cursor, or ChatGPT via MCP. Free, no account needed.

  • Job search and interview prep MCP. 11 tools, OAuth 2.1, cross-LLM. four-leaf.ai.

  • Search remote and onsite jobs through the public Corvi Careers MCP server.

View all MCP Connectors

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/a7512cs/104-mcp-server'

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