Content
# Tool List
## Korean Patent MCP (KIPRIS)
KIPRIS Plus open API exposed as an MCP tool. Search patents, utility models, trademarks, and designs by keyword/item/applicant/right holder, and retrieve detailed bibliographic information by application number.
> Benchmarking korean-law-mcp architecture — lib/tools layer separation, fetch retry, key masking, Zod validation, stateless HTTP, TTL cache, response size limit, `[NOT_FOUND]` hallucination prevention pattern.
## Tools (7)
| Tool | Description | KIPRIS Operation |
|------|------|-------------------|
| `search_patents` | **Free Search** — Keyword-integrated search for patents and utility models (invention name, abstract, claims, applicant) | `freeSearchInfo` |
| `search_patents_advanced` | **Advanced Search** — Precise search combining IPC, invention name, abstract, claims, applicant, and inventor | `getAdvancedSearch` |
| `search_by_applicant` | **Applicant Search** — Applicant name search for application list | `applicantNameSearchInfo` |
| `search_by_rightholder` | **Right Holder Search** — Current patent right holder (reflecting right transfer) | `rightHolerSearchInfo` |
| `get_patent_detail` | **Bibliographic Detail** — Application number → applicant, inventor, IPC, examiner, claim count, final disposition, registration status | `getBibliographyDetailInfoSearch` (fallback `applicationNumberSearchInfo`) |
| `search_trademark` | **Trademark Search** — Trademark name keyword (application status, product class, right holder, sample image) | `trademarkInfoSearchService/getWordSearch` |
| `search_design` | **Design Search** — Product name keyword (design classification, application status, drawing image) | `designInfoSearchService/getWordSearch` |
## Installation & Build
```bash
npm install
npm run build
```
## Authentication Key
A KIPRIS Plus authentication key is required. After registering on [plus.kipris.or.kr](https://plus.kipris.or.kr), apply for each service (patents/utility models, trademarks, designs) to receive a single authentication key that can be used for all services.
```bash
cp .env.example .env
# Enter the issued key in .env: KIPRIS_API_KEY=issued_key
```
> **Permissions are on an operation-by-operation basis**. If a function is not applied for, it will be rejected with `resultCode 30`.
> For example, if only patents are applied for, `search_trademark`/`search_design` will return 30. Each service can be added and will work immediately.
## Execution
### STDIO (Claude Desktop / Claude Code)
```json
{
"mcpServers": {
"korean-patent": {
"command": "node",
"args": ["/absolute/path/korean-patent-mcp/build/index.js"],
"env": { "KIPRIS_API_KEY": "issued_key" }
}
}
}
```
### HTTP (stateless, cloud deployment)
```bash
node build/index.js --mode http --port 8000
# Key: request header (apikey / x-api-key / kipris-key / Authorization: Bearer) or server environment variable fallback
```
The key is prioritized by request header (BYOK), and if not present, it falls back to the server's `KIPRIS_API_KEY`. The fallback call has a global limit (`FALLBACK_RATE_LIMIT_RPM`) to protect the free limit (1,000 times/month).
**HTTP Mode Environment Variables**
| Variable | Default | Description |
|------|------|------|
| `CORS_ORIGIN` | `*` (warning) | Allowed domain. Production recommends explicit specification |
| `RATE_LIMIT_RPM` | `60` | IP-based request limit per minute |
| `FALLBACK_RATE_LIMIT_RPM` | `60` | Server key fallback global limit. `0` blocks fallback (enforces BYOK) |
| `TRUST_PROXY` | `1` | Express trust proxy level. `true`/`all` risks XFF spoofing |
| `MCP_BODY_LIMIT` | `100kb` | POST body size limit |
Docker / Fly.io:
```bash
flyctl launch --dockerfile Dockerfile
flyctl secrets set KIPRIS_API_KEY=issued_key
flyctl deploy
```
## Usage Examples (User Query → Tool)
| User Query | Tool Call |
|------------------|-----------|
| "Find drone battery-related patents" | `search_patents(query="drone battery")` |
| "G06N classification AI patents from Samsung" | `search_patents_advanced(ipc="G06N", applicant="Samsung")` |
| "Patents with 'foldable' in invention name" | `search_patents_advanced(inventionTitle="foldable")` |
| "List of patents applied by Hyundai Motor" | `search_by_applicant(applicant="Hyundai Motor")` |
| "Current patents held by LG" | `search_by_rightholder(rightHolder="LG Electronics")` |
| "Detailed information on this application number" | `get_patent_detail(applicationNumber="10-2016-0172841")` |
| "Is 'Kakao' trademark registered?" | `search_trademark(query="Kakao")` |
| "Registered design cases for 'chair'" | `search_design(query="chair")` |
**Common Options**
- `numOfRows` (1~100, default 10), `pageNo` (default 1) — Paging supported
- `patent` / `utility` — Search target (patents/utility models)
- `sortSpec` — `AD`(filing date) `OPD`(publication date) `GD`(gazette date) `RD`(registration date) `PD`(priority date)
- `descSort` — Descending order (newest) flag
- `withAbstract` — (Free search) Include abstract text
## Operation and Limitations (Measured)
- **Search Operators**: Free search keywords `+ * ? ! ^` are interpreted as KIPRIS search operators.
For example, `C++` may produce unintended results due to `+` being treated as an operator. Use advanced search (`search_patents_advanced`) for exact searches.
- **Foreign Patents** are provided through a separate service (`ForeignPatentAdvencedSearchService`), currently not supported with the issued authentication key (`resultCode 30`). Can be added upon application.
- **Responses over 50KB** are automatically truncated at item boundaries (`⚠️` marked) to prevent LLM misinterpretation. Reduce `numOfRows` or use `pageNo` for paging.
- **Zero results** are explicitly returned as `[NOT_FOUND]` to prevent hallucination. Deep page (`pageNo>1`) zero results are separately notified for last page possibility.
- **Transmission Security**: KIPRIS calls are made over `https` by default. Keys are passed in query strings to prevent plain text exposure. (`KIPRIS_API_PROTOCOL=http` can switch to plain HTTP)
## resultCode (KIPRIS Official)
| Code | Meaning | Action |
|------|------|------|
| 00 | Normal | — |
| 10 / 11 | Parameter error / omission | Check search conditions |
| 20 | No results | Process as empty result |
| 30 | Authentication key not registered (service not applied) | Apply for the service |
| 31 | Authentication key expired | Renew/issue a new key |
## Structure
```
src/
├── index.ts Entry point (STDIO / HTTP mode)
├── tool-registry.ts 7 tools registered + Zod→JSON Schema conversion (apiKey hidden)
├── lib/
│ ├── api-client.ts KIPRIS endpoint wrapping (openapi/rest + kipo-api)
│ ├── fetch-with-retry.ts Timeout·retry·key masking
│ ├── xml-parser.ts Header inspection·search list·item search·trademark·design·bibliographic detail parsing
│ ├── format.ts Domain-specific result text formatting
│ ├── errors.ts KIPRIS resultCode standardization + hallucination prevention
│ ├── cache.ts TTL+LRU cache
│ ├── schemas.ts Response size limit
│ ├── session-state.ts Request-specific key isolation (AsyncLocalStorage)
│ └── types.ts
├── tools/ search / advanced / applicant / rightholder / detail / trademark / design
└── server/http-server.ts Streamable HTTP (rate limit, CORS, trust proxy)
```
## License
MIT