Korean Patent MCP (KIPRIS)

특허청 KIPRIS Plus 오픈API를 MCP 도구로 노출하는 서버. 특허·실용신안·상표·디자인을 키워드/항목/출원인/권리자로 검색하고, 출원번호로 상세 서지정보를 조회한다.
korean-law-mcp 아키텍처를 벤치마킹 — lib/tools 레이어 분리, fetch 재시도·키 마스킹, Zod 검증, stateless HTTP, TTL 캐시, 응답 크기 제한, [NOT_FOUND] 환각방지 패턴.
도구 (7)
원격 엔드포인트 (설치 없음)
공개 remote 서버가 떠 있어 설치 없이 바로 쓸 수 있다. 공식 주소는 통합 호스트 하나뿐이다
(구 개별 주소 korean-patent-mcp.fly.dev 는 통합 후 중단 — 설정에 남아 있으면 아래로 교체):
https://mcp.gomdori.app/patent
- claude.ai 커스텀 커넥터 URL로 붙여넣으면 끝 (자체 KIPRIS 키는
kipris-key 헤더로 전달 가능, 없으면 서버 공용 키 폴백)
- Claude Code:
claude mcp add --transport http korean-patent https://mcp.gomdori.app/patent
- 서버 공용 키 폴백은 무키 사용자 전원이 공유하는 전역 쿼터(운영값: 분당 30 + 롤링 24시간 30회)라 상시 사용에는 부족하다. 자기 키를 헤더로 넘기면 이 게이트를 타지 않는다.
설치 & 빌드
npm install
npm run build
인증키
KIPRIS Plus 인증키가 필요하다. plus.kipris.or.kr 회원가입 후
사용할 서비스(특허·실용 / 상표 / 디자인)를 각각 활용신청하면 단일 인증키로 모두 호출된다.
(data.go.kr 발급 키도 동일 키 체계.)
cp .env.example .env
# .env 에 KIPRIS_API_KEY=발급키 입력
권한은 오퍼레이션(상세기능) 단위다. 신청하지 않은 기능은 resultCode 30(미등록)으로 거부된다.
예: 특허만 신청했다면 search_trademark/search_design 은 30 을 반환한다. 각 서비스를 추가 신청하면 즉시 동작한다.
실행
STDIO (Claude Desktop / Claude Code)
{
"mcpServers": {
"korean-patent": {
"command": "node",
"args": ["/절대경로/korean-patent-mcp/build/index.js"],
"env": { "KIPRIS_API_KEY": "발급키" }
}
}
}
HTTP (stateless, 클라우드 배포)
node build/index.js --mode http --port 8000
# 키: 요청 헤더(apikey / x-api-key / kipris-key / Authorization: Bearer) 또는 서버 환경변수 폴백
키는 요청별(BYOK) 헤더가 우선이고, 없으면 서버 KIPRIS_API_KEY 로 폴백한다.
폴백 호출은 무료 한도(1,000회/월)를 보호해야 하는데, 실질 방어선은 분당이 아니라 일일 총량이다
(분당 상한만으로는 하루 이론 최대가 월 한도를 수십 배 넘는다). 그래서 분당 게이트는 버스트 흡수용으로만
두고 총량은 FALLBACK_DAILY_CAP(기본 30 ≈ 1,000÷31)이 잡는다. 두 게이트 모두 tools/call만 계수하며,
핸드셰이크(initialize/tools/list)는 KIPRIS 쿼터를 쓰지 않으므로 계수하지 않는다 — 계수하면 커넥터가
붙을 때마다 쿼터가 깎여 도구 목록조차 못 싣는다.
HTTP 모드 환경변수
429 응답에는 Retry-After 헤더와 본문 대기 초 안내가 실린다.
Docker / Fly.io:
flyctl launch --dockerfile Dockerfile
flyctl secrets set KIPRIS_API_KEY=발급키
flyctl deploy
사용 예 (사용자 질의 → 도구)
공통 옵션 (get_patent_detail 은 applicationNumber 만 받는다)
numOfRows (1~100, 기본 10), pageNo (기본 1) — 검색 6종 공통, 페이징 지원
patent / utility — 검색 대상 (특허/실용신안). 상표·디자인 검색에는 없음
descSort — 내림차순(최신순) 여부. 상표·디자인 검색에는 없음
sortSpec — AD(출원일) OPD(공개일) GD(공고일) RD(등록일) PD(우선일). 자유검색·항목검색만
withAbstract — (자유검색) 초록 본문 포함
동작·한계 (실측 기준)
- 검색 연산자: 자유검색어의
+ * ? ! ^ 는 KIPRIS 검색연산자로 해석된다.
예) C++ 는 + 가 연산자로 작동해 의도와 다른 결과가 나올 수 있다. 정확검색은 항목검색(search_patents_advanced)을 사용.
- 해외특허는 별도 서비스(
ForeignPatentAdvencedSearchService)이며 현재 인증키에 미신청 상태(resultCode 30)라 미지원. 활용신청 시 도구 추가 가능.
- 응답 5만 자 초과 시 항목 경계에서 자동 절단(
⚠️ 표기) — 레코드가 중간에 끊겨 LLM 이 오인하는 것을 방지. (문자 수 기준이라 한글은 UTF-8 로 최대 ~150KB) 더 보려면 numOfRows 를 줄이거나 pageNo 로 페이징.
- 0건은
[NOT_FOUND] 로 명시 반환 (LLM 환각 방지). 깊은 페이지(pageNo>1)의 0건은 "마지막 페이지 도달" 가능성을 별도 안내.
- 전송 보안: KIPRIS 호출은 기본
https. 키가 쿼리스트링에 실리므로 평문 노출 방지. (KIPRIS_API_PROTOCOL=http 로만 평문 전환)
resultCode (KIPRIS 공식)
구조
src/
├── index.ts 진입점 (STDIO / HTTP 모드)
├── version.ts 서버 버전 단일 출처 (MCP serverInfo · 루트 `/` 정보 응답)
├── tool-registry.ts 도구 7개 등록 + Zod→JSON Schema 변환 (apiKey 숨김)
├── lib/
│ ├── api-client.ts KIPRIS 엔드포인트 래핑 (openapi/rest + kipo-api)
│ ├── fetch-with-retry.ts 타임아웃·재시도·키 마스킹
│ ├── xml-parser.ts 헤더검사·검색목록·항목검색·상표·디자인·서지상세 파싱
│ ├── format.ts 도메인별 결과 텍스트 포맷팅
│ ├── errors.ts KIPRIS resultCode 표준화 + 환각방지
│ ├── rate-limit.ts 폴백 게이트 — 토큰버킷 + 롤링 일일 캡
│ ├── cache.ts TTL+LRU 캐시
│ ├── schemas.ts 응답 크기 제한
│ ├── session-state.ts 요청별 키 격리 (AsyncLocalStorage)
│ └── types.ts
├── tools/ search / advanced / applicant / rightholder / detail / trademark / design
└── server/http-server.ts Streamable HTTP (rate limit, CORS, trust proxy)
라이선스
MIT