Skip to main content
Glama

job-posting-mcp

채용공고 수집 + 노션 등록을 하나의 MCP 서버로 묶은 프로젝트. db-schema.md, 사이트 별 정리.md, page-template.md, 준비물.md의 규칙을 코드로 옮긴 것입니다.

전체 동작 흐름(툴 간 호출 순서, Notion 속성 매핑, 배치 요약/디스코드 알림 내부 동작)을 자세히 정리한 문서는 docs/ARCHITECTURE.md 참고. 원티드·사람인 같은 agent-browser 사이트의 실제 수집 절차는 docs/browser-collection.md.

이 서버가 노출하는 툴

하는 일

search_jobs

사이트 + 키워드로 공고 목록(제목/회사/링크) 검색 — mcp-playwright 사이트만

get_job_detail

공고 상세 URL에서 주요업무/자격요건/우대사항/마감일/근무지 추출 — mcp-playwright 사이트만

register_posting

수집한 데이터를 노션 "🗃️ 공고 분석" DB에 등록 (중복 시 건너뜀) — 모든 사이트 공통

send_collection_summary

register_posting 결과들을 모아 티어별 현황을 디스코드로 한 번에 보고

Related MCP server: job-tracker-mcp

수집 방식이 사이트마다 다릅니다 (중요)

이 서버는 Playwright(자동화 Chromium)로 직접 페이지를 연다. 그런데 원티드·사람인처럼 자동화 자체를 탐지해 차단하는 사이트가 있어서, 사이트별로 수집 경로가 둘로 나뉜다:

방식

대상

누가 수집하나

무인 자동화

mcp-playwright

링커리어, 점핏, 잡플래닛

이 서버의 search_jobs/get_job_detail

✅ 가능

agent-browser

원티드, 사람인

에이전트가 mcp__claude-in-chrome(크롬 확장)으로 직접 읽고, register_posting만 호출

❌ 불가 (세션 필요)

unimplemented

잡코리아(자체 검색만)

아직 없음

-

agent-browser 사이트의 실제 수집 절차는 **docs/browser-collection.md**에 정리되어 있다 — 사용자가 "원티드에서 찾아줘" 처럼 직접 요청했을 때, 에이전트가 이 문서를 따라 브라우저를 조작하고 마지막에 register_posting만 호출한다.

사이트 현황

사이트

collectionMethod

비고

링커리어

mcp-playwright

구조 깔끔. 채용 공고 다수가 본문 없이 "홈페이지 지원"(외부 링크)만 있음

점핏

mcp-playwright

6곳 중 가장 안정적인 구조. 마감일도 이미 YYYY-MM-DD로 내려옴

잡플래닛

mcp-playwright

검색 API는 Node fetch가 TLS 차단당해 Playwright 페이지 안에서 fetch 실행으로 우회. 결과 대다수가 잡코리아 원본 공고 제휴 게시라 상세는 잡코리아 파서를 재사용(아래 참고)

원티드

agent-browser

CDN 레벨 자동화 차단(robots.txt 403). docs/browser-collection.md 참고

사람인

agent-browser

Playwright/진짜 Chrome 둘 다 TLS 단계에서 차단(ERR_CONNECTION_RESET). docs/browser-collection.md 참고

잡코리아

unimplemented(자체 검색만)

자체 검색 UI는 필터 패널과 결과 목록이 분리돼 있어 자동화 불가. 대신 상세 페이지 파서(src/sites/jobkorea.js)는 구현되어 있고 잡플래닛 검색이 찾은 잡코리아 링크의 본문을 읽는 데 쓰인다

mcp-playwright 사이트를 추가하려면 src/sites/에 파일을 만들고 src/tools/searchJobs.js/getJobDetail.jsSITE_MODULES, src/config/sites.js에 등록하면 됩니다. 구현 전에 항상 robots.txt부터 확인하세요 — 위 표의 사례처럼 "접속은 되는데 정책상 막혀있는" 경우가 실제로 더 많았습니다. 만약 차단이 Playwright 자체를 겨냥한(TLS/CDP 핑거프린팅) 것이라면, mcp-playwright가 아니라 agent-browser로 분류하고 docs/browser-collection.md에 절차를 추가하는 쪽이 맞습니다.

시작하기

npm install          # playwright install chromium까지 자동 실행됨 (postinstall)
cp .env.example .env # NOTION_API_KEY, NOTION_DATA_SOURCE_ID 채우기
npm start             # stdio로 MCP 서버 실행

주의: .env는 절대 커밋하지 마세요 (.gitignore에 이미 포함). Notion API 키/디스코드 웹훅 URL이 한 번이라도 평문으로 노출됐다면(문서, 채팅 등) 각각 Notion 설정 > 연동, 디스코드 채널 설정 > 연동 > 웹훅에서 즉시 재발급/재생성하세요. (discord-webhook.txt에 있던 실제 웹훅 URL을 .env로 옮기며 이 대화에도 값이 그대로 노출됐으니, 이 프로젝트를 공개 레포로 올릴 계획이라면 재생성을 권장합니다.)

등록 시 자동으로 처리되는 것들

register_posting이 새 페이지를 만들 때(중복이라 건너뛴 경우는 해당 없음) job 객체와 무관하게 서버가 직접 채우는 값:

  • created_at — "언제 이 서버가 수집해서 노션에 넣었는지"를 나타내는 타임스탬프. 호출자가 넣는 값이 아니라 register_posting 실행 시점의 현재 시각을 서버가 직접 찍는다. 공고 자체의 게시일과는 다른 개념이다 (아래 참고).

job.postedDate(선택, YYYY-MM-DD)를 넘기면 "공고 등록일"(공고 사이트에 실제 게시된 날짜)에 채워진다 — 사이트에 명시된 경우만 채우고, 없으면 생략한다 (추측 금지 원칙은 마감일과 동일).

디스코드 알림은 등록마다가 아니라 배치 끝에 한 번만

register_posting은 호출될 때마다 Discord로 알림을 보내지 않는다 — 30건을 등록하면 30개의 메시지가 아니라 아무 메시지도 안 나간다. 대신:

  1. 에이전트가 register_posting을 후보마다 호출하면서, 그때마다 돌아오는 JSON 결과 ({status, company, companySize, newOptions, ...})를 자기 컨텍스트의 배열에 쌓아둔다.

  2. 수집이 다 끝나면 그 배열 전체를 send_collection_summary에 한 번만 넘긴다.

  3. 이 툴이 예전 스킬(discord-webhook.md)과 같은 형식 — 검토/신규/중복/조건불일치 건수, 티어별 등록 현황(1티어 대기업·공기업·외국계 / 2티어 중견·벤처 / 3티어 중소·스타트업, src/config/notionSchema.jsCOMPANY_SIZE_TIER), 🆕 새로 생성된 select 옵션(전형단계 등 자유 입력 필드에서 자동 감지, detectNewOptions), ⚠️ 확인 필요 항목 — 으로 메시지 하나를 조립해 디스코드로 보낸다.

웹훅 미설정이거나 전송이 실패해도 이미 끝난 Notion 등록들은 절대 되돌리지 않는다send_collection_summary의 반환 메시지에 전송 여부만 보고된다 (src/discord/notify.js, src/discord/summary.js).

동작 확인

npm run smoke:linkareer   # 읽기 전용, 안전
npm run smoke:jumpit      # 읽기 전용, 안전
npm run smoke:jobplanet   # 읽기 전용, 안전 (검색 → 잡코리아 GI_Read 상세까지 검증)
npm run smoke:wanted      # agent-browser 방식이라 "이 툴로 수집할 수 없다"는 안내 에러가 나는 게 정상
npm run smoke:saramin     # agent-browser 방식이라 "이 툴로 수집할 수 없다"는 안내 에러가 나는 게 정상
npm run test:register     # 노션 DB에 진짜 테스트 페이지 1개를 생성함 — 끝나면 지워도 됨
npm run test:discord      # created_at/공고 등록일/디스코드 알림까지 한 번에 검증 — 마찬가지로 실제 등록됨

트러블슈팅

CloudFront 403 — Playwright 기본 헤드리스 UA가 차단당함 (원티드) CloudFront 뒤에 있는 사이트에 Playwright 기본 헤드리스 Chromium UA로 접속하면 403 The request could not be satisfied를 반환한다. 실제 Chrome과 비슷한 User-Agent + Accept-Language 헤더를 주고 --disable-blink-features=AutomationControlled 플래그로 navigator.webdriver 탐지를 끄면 통과한다 (src/browser.js) — 다만 이건 명시적 차단을 우회하는 것이므로 자동화 파이프라인에는 쓰지 않기로 했다 (사이트 구현 현황 표 참고).

net::ERR_CONNECTION_RESET — UA 위장으로도 못 뚫는 더 깊은 차단 (사람인) 같은 UA로 curl은 200이 오는데 Playwright(자동화 Chromium)로는 연결 자체가 끊긴다. 헤더가 아니라 TLS/CDP 핑거프린팅 기반으로 자동화 브라우저 자체를 탐지하는 것으로 보인다 (Akamai류로 추정). 이 이상은 스텔스 플러그인 등 "탐지 자체를 회피"하는 기법이 필요해서 보류.

robots.txt가 실제 검색 URL만 콕 집어 막아놓은 경우 (잡코리아) 사이트 접속과 크롤링 자체는 문제없지만, robots.txt의 일반(*) 규칙에 실제 검색 엔드포인트 (/Search/?stext=)가 Disallow로 명시되어 있었다. AI 크롤러 전용 규칙은 오히려 더 관대해서 (/recruit/joblist 등 허용) 헷갈리기 쉬운데, 그 경로는 카테고리 브라우징 전용이라 키워드 검색을 대체하지 못했다. robots.txt는 섹션별로(일반 * / 이름 붙은 AI 크롤러) 다른 규칙을 가질 수 있으니 둘 다 확인해야 한다.

networkidle이 상세 페이지에서 타임아웃남 Sentry/GA/카카오픽셀 같은 애널리틱스가 백그라운드에서 계속 요청을 쏴서 네트워크가 절대 "idle" 상태가 되지 않는다. domcontentloaded로 받은 뒤, 원하는 콘텐츠(예: "주요업무" 제목)가 실제로 나타날 때까지 waitForFunction/waitForSelector로 명시적으로 기다리는 쪽이 안정적이다.

waitForSelector가 통과해도 evaluate는 빈 배열 (점핏) state: "attached"로 기다린 셀렉터가 실제로 매치됐는데도, 바로 이어서 page.evaluate()로 같은 셀렉터를 다시 찾으면 아무것도 안 나오는 경우가 있었다. React 하이드레이션 전 스켈레톤 DOM이 "attached" 조건은 통과시키고, 직후 클라이언트 렌더링이 그 노드들을 통째로 교체해버려서 생긴 레이스 컨디션으로 보인다. waitForSelector 뒤에 짧은 waitForTimeout(1~1.5초)을 추가해서 해결했다 — SPA 사이트를 스크래핑할 때 일반적으로 의심해볼 만한 패턴이다.

같은 iframe인데 다른 공고 내용이 나옴 (사람인) 상세 페이지 하단에 "추천 공고" 미리보기가 각각 자기 iframe을 갖고 있어서, 대상 공고의 실제 설명은 반드시 첫 번째 iframe(iframe_content_0)이라는 걸 직접 비교해보고야 확인했다. 인덱스를 확인하지 않고 아무 iframe이나 읽으면 엉뚱한 회사의 JD를 가져오게 된다.

공고 상세에 본문이 없는 경우가 생각보다 많음 사이트 별 정리.md가 이미 경고했던 내용이지만 실제로 부딪혀보니 체감 빈도가 높았다: 이미지 한 장으로만 된 공고(사람인/잡코리아), "홈페이지 지원"으로 본문 없이 외부 링크만 있는 공고 (링커리어/잡코리아 대기업), 교육/연수 프로그램이라 통상적인 담당업무/자격요건 구조 자체가 없는 공고. get_job_detail은 이런 경우 duties/requirements를 억지로 채우지 않고 빈 배열을 돌려주도록 설계했다 — page-template.md의 "공고에 미기재" 규칙과 자연스럽게 맞물린다.

Claude Code / 다른 MCP 클라이언트에 연결하기

Claude Code라면 프로젝트 MCP 설정에 아래처럼 추가합니다 (경로는 실제 설치 위치로 변경):

{
  "mcpServers": {
    "job-posting-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/job-posting-mcp/src/index.js"]
    }
  }
}

MCP는 모델에 종속되지 않는 표준 프로토콜이라, Antigravity 등 다른 MCP 호환 클라이언트에도 같은 방식으로 연결할 수 있습니다.

데이터 흐름

search_jobs(site, keyword)
  → get_job_detail(site, link)          # 후보마다 반복
    → (적합도 판단은 이 서버 바깥, 에이전트/오케스트레이션 레이어의 몫)
      → register_posting({...})          # 노션 DB에 실제 등록 (created_at 자동 기록)
        └→ 결과(JSON)를 에이전트가 배열에 누적                     ← 후보마다 반복 구간 끝
  → send_collection_summary({ results: [...] })  # 배치 끝나면 딱 한 번, 티어별 요약을 디스코드로

MCP 서버는 "도구"만 제공합니다. "이 공고가 신입 프론트엔드에 적합한가?", "언제 실행할까?" 같은 판단/스케줄링 로직은 이 서버가 아니라 이 서버를 호출하는 에이전트(Claude Code 스킬, Antigravity 서브에이전트 등) 쪽 책임입니다.

Available Tools

4 tools
get_job_detailA

공고 상세 페이지에서 주요업무/자격요건/우대사항/마감일/근무지를 추출합니다. register_posting에 넘길 입력을 만들 때 사용합니다.

ParametersJSON Schema
NameRequiredDescriptionDefault
linkYes공고 상세 페이지 URL
siteYes공고가 올라온 사이트

TDQS

A4/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 clearly frames the tool as a read-only extraction operation and lists what gets extracted, which is useful. However, it does not disclose potential failure modes, network dependency, output format, or error behavior, leaving some behavioral ambiguity.

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 short sentences, no filler. The first sentence front-loads the action and extracted fields, and the second explains the purpose. Every word earns its place.

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 two-parameter tool with no output schema and no annotations, the description provides the key information: what is extracted and why it is used. It stops short of specifying the exact return shape or handling of invalid links, but the listed fields and the register_posting connection cover most of what an agent needs 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?

Schema description coverage is 100%, so the baseline is 3. The description adds context about what the extracted data is used for, but it does not add parameter-specific meaning beyond the schema's existing descriptions for 'site' and 'link'.

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 uses a specific verb ('추출합니다' – extracts) and names the resource (job posting detail page) plus the exact fields extracted: 주요업무/자격요건/우대사항/마감일/근무지. It also explicitly ties the tool to register_posting, which distinguishes it from siblings like search_jobs and send_collection_summary.

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 a clear trigger condition: 'register_posting에 넘길 입력을 만들 때 사용합니다' (use when creating input to pass to register_posting). It does not explicitly enumerate when not to use it or name alternative tools, but the stated use case is enough for an agent to route correctly among the listed siblings.

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

register_postingA

수집한 공고를 노션 "🗃️ 공고 분석" DB에 등록합니다. 채용링크 기준으로 중복이면(단, 기존 상태가 "마감"이면 예외) 건너뜁니다. created_at은 자동으로 기록되고, 디스코드 알림은 이 호출마다 보내지 않습니다 — 결과를 JSON으로 반환하니 여러 건을 배열에 모아뒀다가 마지막에 send_collection_summary를 한 번만 호출하세요.

ParametersJSON Schema
NameRequiredDescriptionDefault
linkYes채용공고 URL — 중복 체크 기준 키 (필수)
titleNo채용직무 / 공고 제목
dutiesNo주요 업무 불릿 목록
stagesNo전형 절차, 순서대로 1차~6차에 매칭
companyYes기업명 (필수)
deadlineNo마감일 YYYY-MM-DD. 상시채용/미기재면 생략 (추측 금지)
industryNo
locationNo근무지
preferredNo우대 사항 불릿 목록
postedDateNo공고 등록일 YYYY-MM-DD — 채용 사이트에 이 공고가 게시된 날짜. 사이트에 명시되어 있을 때만 채우고, 없으면 생략 (추측 금지). 이 서버가 실제로 수집해서 노션에 '적재'한 시각은 별도로 created_at에 자동 기록되므로 여기 넣지 말 것.
submitDocsNo
careerLevelNo경력직 공고는 애초에 등록하지 않는다
companySizeNo
jobCategoryNo
requirementsNo자격 요건 불릿 목록
employmentTypeNo
industryDetailNo산업군을 select 옵션으로 분류하기 애매할 때

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It discloses the deduplication behavior (skip if link already exists, with an exception for '마감' status), that created_at is auto-recorded, that no Discord notification is sent per call, and that the tool returns JSON. These are important behavioral traits beyond what a schema would show. It does not mention error handling or permissions, but for a registration tool, the covered aspects are sufficient.

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 a single paragraph of about 4 sentences, efficient and front-loaded with the primary purpose. It includes crucial operational notes (dedup rule, auto-timestamp, notification batching) without unnecessary filler. It is concise while conveying all key behavioral guidance.

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 complexity (17 params, no output schema), the description covers the essential context: what the tool does, dedup logic, auto-created_at, the JSON return and the recommendation to batch and call send_collection_summary. It does not explain the exact JSON structure or error cases, but those are not critical for correct invocation, and the schema handles parameter details. Overall, it provides enough for an agent to use the tool correctly.

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 coverage is 71% (12 of 17 params have descriptions). The description itself adds little beyond the schema: it reinforces that 'link' is the dedup key (already stated in schema) and explains the intended flow of collecting results. Since the schema already documents most parameters in detail, the description does not need to repeat them. It adds marginal value but does not compensate for the few undocumented params.

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: registering collected postings into a specific Notion DB ('🗃️ 공고 분석'). It uses a specific verb ('등록합니다'), names the resource, and explains the deduplication rule. It is distinct from siblings like search_jobs and get_job_detail, which are for retrieval, and send_collection_summary, which is for final notification.

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 implicitly indicates when to use this tool: when you have collected postings to register. It also explicitly instructs to accumulate results and call send_collection_summary only once at the end, rather than sending per-call notifications. However, it does not contrast with search/get tools, but that is obvious given the verb. It provides clear operational guidance for the calling pattern.

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

search_jobsA

채용 사이트에서 키워드로 공고를 검색해 [제목, 회사, 링크] 목록을 반환합니다. Playwright로 직접 수집 가능한 사이트(현재 linkareer, jumpit)만 지원합니다 — 원티드/사람인처럼 자동화가 차단된 사이트는 대신 에이전트가 mcp__claude-in-chrome으로 직접 수집합니다 (docs/browser-collection.md 참고).

ParametersJSON Schema
NameRequiredDescriptionDefault
siteYes검색할 채용 사이트
limitNo최대 결과 개수 (기본 20)
keywordYes검색 키워드 (예: "프론트엔드")

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses that the tool uses Playwright automation and only supports two sites, and it notes the alternative for other sites. However, it doesn't specify error behavior if an unsupported site is passed (e.g., returns empty, throws error), which is a minor 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?

Two sentences, zero waste. The first sentence states purpose and output; the second addresses limitations and alternatives. Front-loaded and efficient.

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?

No output schema exists, so the description must cover return values, which it does (list of title, company, link). It also covers the key limitation (supported sites) and the alternative path. It doesn't mention pagination or timeouts, but those are minor given the schema covers limit.

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 100%, so the schema already documents all parameters. The description adds no additional parameter-specific meaning beyond the schema, so the baseline of 3 applies.

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 verb (search), the resource (job postings on job sites), and the output format ([title, company, link]). It also differentiates from siblings like get_job_detail and register_posting by focusing on searching. The explicit list of supported sites adds specificity.

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 explicitly states when to use this tool (only for linkareer and jumpit) and when not to (for automated-blocked sites like Wanted/Saramin, use mcp__claude-in-chrome instead). It also references documentation, giving clear routing guidance.

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

send_collection_summaryA

이번 수집 배치의 register_posting 결과들을 모아 티어별 등록 현황, 새로 생성된 select 옵션, 확인 필요 항목을 정리해 디스코드 웹훅으로 한 번에 보고합니다. 등록을 여러 건 반복한 뒤 맨 마지막에 딱 한 번만 호출하세요.

ParametersJSON Schema
NameRequiredDescriptionDefault
resultsYesregister_posting을 호출할 때마다 돌아온 JSON 결과를 그대로 순서대로 모은 배열. 이 호출 하나로 배치 전체의 등록 결과를 요약해서 디스코드로 보낸다 — 등록마다 개별 메시지를 보내지 않는다.
siteLabelNo메시지 헤더에 붙일 출처 설명. 예: "원티드 · 사람인". 생략하면 일반 문구만 표시
reviewNeededNo사람이 직접 확인해야 하는 항목 (모호한 분류, 이미지 전용 공고 등)
reviewedCountNo이번 수집에서 실제로 검토한 후보 총 건수 (조건 불일치라 register_posting을 아예 호출하지 않은 것까지 포함). 생략하면 results.length + excludedByCondition으로 계산.
excludedByConditionNo경력조건 등 수집 조건에 맞지 않아 애초에 register_posting을 부르지 않고 제외한 건수

TDQS

A4.1/5.0
Behavior3/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. It reveals the external side effect (sends to Discord) and notes that it batches results into one message rather than sending individual messages. However, it does not mention what happens on webhook failure, idempotency, or any rate-limit implications, leaving some gaps for a side-effect tool.

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 a single, dense sentence that front-loads the purpose and usage. It packs a lot of relevant detail (what is aggregated, the delivery channel, and when to call) without extraneous words. It could be slightly more scannable, but it is appropriately sized for the tool.

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 batch summary sender, the description covers the essential operational context: what inputs it expects, how to invoke it, and what it produces. The only missing aspects are error-handling details (e.g., webhook failure) and any output confirmation, but given this is a fire-and-forget notification tool with no output schema, these are minor and do not impede correct usage.

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 schema already describes all five parameters at 100% coverage, so the baseline is 3. The description adds meaningful context beyond this: it explains that `results` is the ordered array of JSON outputs from each register_posting call, and it specifies that `reviewedCount` defaults to `results.length + excludedByCondition` when omitted. This extra semantic clarification earns a 4.

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 is explicit: it aggregates register_posting results, organizes them into tier status, new options, and review items, and sends a single summary via Discord webhook. This clearly distinguishes it from siblings like search_jobs, get_job_detail, and register_posting by stating the specific resource (collection batch results) and action (report via webhook).

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 a clear directive: call it only once after completing multiple registrations, implying it should not be called per registration. It does not explicitly state alternatives or exclusions, but the context makes it obvious this is the final reporting step, so the guidance is sufficient.

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.1.0
    • First observedget_job_detail
    • First observedregister_posting
    • First observedsearch_jobs
    • First observedsend_collection_summary

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool maps to a distinct stage in a clear pipeline: searching job listings, fetching details, registering postings, and sending a summary. There is no overlap or ambiguity between tool purposes.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern: search_jobs, get_job_detail, register_posting, send_collection_summary. The style is uniform and predictable across the entire tool set.

Tool Count5/5

Four tools is well-scoped for this workflow: search, detail extraction, registration, and notification. Each tool serves a necessary step without redundancy or bloat.

Completeness5/5

The tool set covers the full collection lifecycle from searching and extracting details to registering in Notion and reporting via Discord. There are no obvious dead ends or missing operations for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • 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
  • A
    license
    A
    quality
    C
    maintenance
    Enables users to manage job applications (add, list, update status) through natural language conversations, using Notion as the backend.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An AI-powered job search and application assistant that enables multi-source job hunting, OpenAI matching, cover letter generation, and hybrid application automation via Playwright, Chrome CDP, screen OCR, and manual assist.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables natural-language job search and aggregation from multiple recruitment websites with zero configuration, providing filtered results and standardized output for AI assistants.
    26 npm
    ISC