Skip to main content
Glama
README.md
# patent-mcp

特許情報を取得して Agent にコンテキストとして渡すための、ローカル実行の MCP サーバー。

データソースはインターフェースの背後に隠してあるので、あとから
Google Patents → 特許庁 API → EPO OPS のように差し替え・追加ができる。
ツールも `tools/` にファイルを置くだけで増える。

## ツール

| ツール | 用途 |
| --- | --- |
| `search_patents` | キーワード・出願人・発明者・期間で特許を検索する |
| `find_similar_patents` | 既存特許や自由文(アイデア・請求項案)に似た特許を探す |
| `get_patent` | 公開番号を指定して要約・請求項・明細書・分類・引用・ファミリーを取得する |
| `list_patent_providers` | 利用可能なデータソースと対応機能を確認する |

## セットアップ

```bash
uv sync
```

動作確認:

```bash
uv run patent-mcp --help
```

## エディタ / エージェントへの登録

以下、リポジトリの絶対パスを `/path/to/patent-mcp` と表記する(`pwd` で確認できる)。
`uv` のフルパスは `which uv` で確認する(通常 `~/.local/bin/uv`)。

### Claude Code

```bash
claude mcp add patent -- uv --directory /path/to/patent-mcp run patent-mcp
```

### Claude Desktop

`claude_desktop_config.json` に追加:

```json
{
  "mcpServers": {
    "patent": {
      "command": "uv",
      "args": ["--directory", "/path/to/patent-mcp", "run", "patent-mcp"],
      "env": { "PATENT_MCP_LANG": "ja" }
    }
  }
}
```

### GitHub Copilot(VS Code)

VS Code の Copilot Chat(Agent モード)は MCP サーバーに対応している。
ワークスペース直下に `.vscode/mcp.json` を作る(チーム共有したくない場合は
`.vscode/mcp.json` を `.gitignore` に入れるか、ユーザー設定側の MCP 設定に書く)。

```json
{
  "servers": {
    "patent": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "/path/to/patent-mcp", "run", "patent-mcp"],
      "env": { "PATENT_MCP_LANG": "ja" }
    }
  }
}
```

有効化手順:

1. VS Code でこのリポジトリ(または `.vscode/mcp.json` を置いたワークスペース)を開く
2. コマンドパレットで `MCP: List Servers` を実行し、`patent` が認識されているか確認(表示されない場合は `MCP: Add Server` から同じ内容を登録する)
3. Copilot Chat を **Agent モード**にする(チャット入力欄のモード切り替え)
4. ツール一覧(レンチ/ツールアイコン)に `search_patents` などが並んでいることを確認して使う

ユーザー全体で使い回したい場合は、ワークスペースではなくコマンドパレットの
`MCP: Open User Configuration` から同じ内容をユーザー設定側に書いてもよい。
VS Code の MCP サポートは変更が速いので、上記でうまくいかない場合は
VS Code 側の最新ドキュメント(Copilot Chat の MCP servers)を確認すること。

## 設定(環境変数)

| 変数 | 既定値 | 説明 |
| --- | --- | --- |
| `PATENT_MCP_PROVIDER` | `google_patents` | 使用するデータソース |
| `PATENT_MCP_LANG` | `ja` | 本文の言語 |
| `PATENT_MCP_TIMEOUT` | `30` | HTTP タイムアウト(秒) |
| `PATENT_MCP_MAX_RESULTS` | `25` | 1回の検索で返す上限 |
| `PATENT_MCP_MAX_SECTION_CHARS` | `20000` | 1セクションの最大文字数 |

プロバイダ固有の設定は `PATENT_MCP_<プロバイダ名>_<キー>` で渡す。
例: `PATENT_MCP_EPO_OPS_KEY=xxx` → `settings.options_for("epo_ops") == {"key": "xxx"}`

`google_patents` プロバイダ固有:

| 変数 | 既定値 | 説明 |
| --- | --- | --- |
| `PATENT_MCP_GOOGLE_PATENTS_MIN_INTERVAL` | `1.0` | リクエスト間の最小間隔(秒) |
| `PATENT_MCP_GOOGLE_PATENTS_MAX_RETRIES` | `3` | 429/503 を受けたときの再試行回数 |

Google Patents は短時間に連続アクセスすると 503 を返す。
まとめて多数の特許を調べる用途では `MIN_INTERVAL` を 2〜3 秒に上げるとよい。

## 使用例(Agent 側の会話)

- 「全固体電池の界面抵抗低減について、2022年以降の日本の特許を10件調べて」
- 「JP2020123456A に似た特許を、優先日が2019年より前のものに限って探して」
- 「この請求項案に近い先行技術がないか調べて: 〈本文〉」
- 「US9634296B2 の請求項1と、引用されている文献を出して」

## HTML構造の変更をどう検知するか

既定のプロバイダは Google Patents の HTML を読むので、Google が構造を変えると壊れる。
やっかいなのは**例外を出さずに中身だけ欠ける**壊れ方で、放っておくと Agent が
「請求項の無い特許」と誤解して結論を出す。3段構えで検知する。

**1. 実行時の自動チェック(常に効く)**

毎回の取得でパースの妥当性を自己点検し、怪しければ結果の冒頭に警告を出す。

- どの特許にも必ずあるはずのもの(タイトル・要約・請求項・明細書)が空
- セクションは存在するのに中身が抽出できない
- **ページが書いている請求項の件数と、抽出できた件数が食い違う**

```
# JP2020123456A — 蓄電素子、蓄電素子の製造方法

> **取得できていない情報があります**
> - 請求項: ページには16項とあるのに2項しか抽出できていません。内容が欠けています。
>
> この結果だけで「存在しない」と判断せず、元ページを確認してください: ...
```

引用やファミリーは本当に0件のことがあるので対象外。誤検知しない範囲に絞ってある。

**2. ライブ契約テスト(触ったときに実行)**

```bash
uv run python -m pytest -m network
```

実ページに接続し、パーサが依存する11個のセレクタが今も存在するか確認する。

**3. オフラインテスト(編集時の回帰防止)**

HTML をわざと壊して、上記1の検知が働くことまでテストしている。

## テスト

網羅は狙っていない。このプロジェクトのバグは実データで動かしたときにしか
見つからなかったので、テストは「一度やらかした罠の記録」と
「Google の HTML が変わったことの検知」に絞ってある。

```bash
uv run python -m pytest          # オフライン20件
uv run python -m pytest -m network   # ライブ契約テスト
```

| ファイル | 役割 |
| --- | --- |
| `test_parse_gotchas.py` | 実際に壊れたパースの再発防止(請求項の潰れ、二重エンコード等) |
| `test_number_formats.py` | 「特開2020-123456」等の表記ゆれ吸収 |
| `test_provider_swap.py` | データソース差し替えの前提が壊れていないこと |
| `test_live_contract.py` | **実ページに接続**し、依存セレクタが今も存在するか確認 |

`tests/fixtures/patent_page.html` は実ページのダウンロードではなく、
**構造だけを再現した手書きのファイル**。実ページを置かないのは、
他社の著作物を取り込むことになるうえ、Google 自身のウィジェット用 API キーが
埋まっていてシークレットスキャナが誤検知するため。

手書きなので「パーサを編集して壊したか」は分かるが、
「そもそも Google の HTML を誤解していたか」は分からない。
そこは `-m network` のライブ契約テストが実物に当てて確認する。
セレクタを触ったときや、パース結果が変になったときに実行すること。

ライブ契約テストは既定でスキップされる(レート制限を避けるため)。
レート制限中も失敗ではなくスキップになるので、時間をおいて再実行する。

## 拡張する

### データソースを足す

`src/patent_mcp/providers/` にファイルを1つ作るだけ。

```python
from . import register
from .base import Capability, PatentProvider, SearchQuery
from ..models import SearchResult

@register
class JpoProvider(PatentProvider):
    name = "jpo"
    description = "特許庁 特許情報取得API"
    capabilities = frozenset({Capability.SEARCH, Capability.BIBLIOGRAPHIC})
    requires_credentials = True

    async def search(self, query: SearchQuery) -> SearchResult:
        token = self.options["token"]   # PATENT_MCP_JPO_TOKEN
        ...
```

未実装のメソッドは基底クラスが `NotSupportedError` を投げ、ツールが
「このプロバイダは未対応」と Agent に伝える。登録リストの編集は不要
(`providers/__init__.py` がモジュールを自動検出する)。

`PATENT_MCP_PROVIDER=jpo` で既定を切り替えられるほか、
各ツールの `provider` 引数で呼び出しごとに切り替えられる。

### ツールを足す

`src/patent_mcp/tools/` にファイルを1つ作り、`register` を定義する。

```python
def register(mcp, ctx):
    @mcp.tool()
    async def my_tool(...) -> str:
        """Agent 向けの説明。"""
        provider = ctx.provider()
        ...
```

## 注意

既定の `google_patents` プロバイダは Google Patents の公開ページを読む非公式実装で、
サイト構造の変更やレート制限の影響を受ける。業務で確実性が必要な場合は、
特許庁の特許情報取得API や EPO OPS のプロバイダを追加して切り替えること。

取得できるのは公開情報であり、権利範囲の解釈や侵害判断は専門家の確認が必要。

TDQS

A4.2/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a distinct purpose: provider metadata, direct retrieval by number, keyword search, and similarity search. Any potential overlap between search_patents and find_similar_patents is clearly resolved through descriptions of input types and use cases.

Naming Consistency5/5

All tool names follow the consistent verb_noun pattern (list_, get_, search_, find_) with snake_case. The pattern is predictable and makes the tool set easy to navigate.

Tool Count5/5

Four tools is an ideal size for this domain. Each tool is necessary and covers a core aspect of patent search and retrieval without redundancy or bloat.

Completeness4/5

The set covers the full workflow of patent discovery and examination: find providers, search, retrieve specific patents, and find similar ones. Minor gaps like legal status or batch export exist but are not critical for typical patent research tasks.

Maintenance

ActivityMaintained
ResponsivenessSyncing