MCP サーバー
KUKAN は Model Context Protocol (MCP) に準拠したサーバーエンドポイントを提供します。Claude、ChatGPT、その他の MCP 対応 AI エージェントからデータカタログの検索・閲覧が可能です。
エンドポイント
Section titled “エンドポイント”POST /api/mcpStreamable HTTP トランスポートを使用したステートレスモードで動作します。
Claude Code
Section titled “Claude Code”コマンドで追加します。
claude mcp add --transport http kukan https://your-kukan-site/api/mcpプロジェクトの .mcp.json に書く場合は、type を http にします。
{ "mcpServers": { "kukan": { "type": "http", "url": "https://your-kukan-site/api/mcp" } }}所属組織の非公開データセットも扱う場合は、API トークンをヘッダーで渡します(コマンドなら --header "Authorization: Bearer kukan_..."、.mcp.json なら "headers": { "Authorization": "Bearer kukan_..." })。
Claude Desktop / claude.ai
Section titled “Claude Desktop / claude.ai”設定の「コネクタ」から、カスタムコネクタとして https://your-kukan-site/api/mcp を追加します(使えるプランは Claude のヘルプセンターを参照してください)。
- 接続は利用者の PC からではなく Anthropic のクラウドから行われます。インターネットから届かないサイト(閉域網・VPN の内側など)には接続できません。その場合は、利用者の PC から接続する Claude Code などのクライアントを使ってください
- カスタムコネクタには API トークンのヘッダーを設定できないため、公開データセットだけを扱います
curl でのテスト
Section titled “curl でのテスト”curl -X POST https://your-kukan-site/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-03-26", "capabilities": {}, "clientInfo": { "name": "test", "version": "0.1" } } }'接続時の案内
Section titled “接続時の案内”初期化(initialize)の応答の instructions で、ツール全体の使い方をクライアントに伝えます。MCP 対応のクライアントは、これをモデルへの指示に加えます。
- 検索する言語:カタログの言語で検索し、利用者の言語で答えるよう伝えます。カタログの言語は、公開されているデータセットの題名(最近更新された 50 件)の文字から判定します。判定するのは日本語と韓国語だけです。漢字だけの題名(日本語と中国語を区別できない)やラテン文字の言語、言語が混在するカタログでは言語名を出さず、「検索結果の題名と同じ言語で」とだけ伝えます
- 検索語の選び方:質問文をそのまま渡さず、データセットの題名や文書が使いそうな語を少数渡し、見つからなければ語を減らすか言い換えるよう伝えます
- ツールの組み合わせ:答えが文書の本文にあれば
search_passagesからget_document_sectionへ、表の数値にあればsearch_datasetsからget_resource_schemaとquery_resourceへ進むよう伝えます - 出典:各ツールが返すリソース・ページや行・URL を引用するよう伝えます。意味の判断は呼び出し側に委ねます
すべてのツールは読み取り専用です。認証済みユーザーの権限に基づいて、非公開データセットへのアクセスが制御されます。
| ツール | 説明 |
|---|---|
search_datasets |
キーワードまたは自然文でデータセットを検索(ハイブリッド検索)。どのファイルが一致したかも返す |
get_dataset |
データセットの詳細情報を取得(リソース一覧含む) |
get_resource |
リソース(ファイル)のメタデータ・URL・AI による説明を取得 |
get_resource_schema |
リソースの列スキーマ(列名・型・行数・統計)と OData 配信の可否を取得。表形式のみ |
query_resource |
リソースのデータに読み取り専用 SQL(SELECT/WITH のみ)を実行。表形式のみ |
get_document_outline |
文書の目次(見出しとそのページ、ブックのシートと行)を取得。PDF/Word/PowerPoint/Excel/一太郎/Markdown |
get_document_section |
文書の本文を、ページ・スライド・シート・見出しを指定して、出典付きで取得。PDF/Word/PowerPoint/Excel/一太郎/Markdown |
search_passages |
文書の本文から、検索語に一致する箇所を出典・ページ付きで取得。PDF/Word/PowerPoint/Excel/一太郎/Markdown |
list_organizations |
組織の一覧を取得 |
list_groups |
グループ(カテゴリ)の一覧を取得 |
list_tags |
タグの一覧を取得 |
search_datasets
Section titled “search_datasets”データカタログを検索します。キーワードのほか自然文でも検索でき、
意味の近いデータセットも結果に含まれます(ハイブリッド検索)。
語の一致では、検索語のすべての語を持つデータセットが一致します。質問文をそのまま渡すより、
題名や説明に使われていそうな語を少数渡すほうが見つかります。すべての語を持つデータセットが無いときは、
語の少ない一致に緩めて返し、先頭でそう知らせ、各データセットに持たない語を Lacks: として付けます。
データセットが複数のファイルを持つ場合、どのファイルが一致したかを Matched files: として
返します。各行には一致の根拠が付きます — in its name or description(メタデータ)、
in its contents(本文)、in its AI-written description(AI による説明)、
by meaning 0.42(意味。数値は類似度)。意味で一致した場合、検索語はそのファイルの
どこにも現れませんので、語を探しに行っても見つからない点に注意してください。
一致が多いときは先頭 5 件を挙げ、残りは件数で示します。
各結果には組織・説明(先頭 200 文字)・フォーマット(データベースから取得)も付きます。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
q |
string | Yes | 検索キーワードまたは自然文 |
organization |
string | No | 組織名(slug)でフィルタ |
tags |
string[] | No | タグ名でフィルタ |
semantic |
boolean | No | false でキーワード一致のみ(デフォルト: true) |
offset |
number | No | スキップ件数(デフォルト: 0) |
limit |
number | No | 最大件数(デフォルト: 10、最大: 50) |
get_dataset
Section titled “get_dataset”データセットの詳細情報を取得します。リソース一覧は公開ページと同じ並びで、セクションが
始まる位置に [セクション名] の見出し行が入ります。/ の入れ子は公開ページと同じ深さで
字下げされ、配下のリソースも見出しより 1 段下がります。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
nameOrId |
string | Yes | データセット名(slug)または UUID |
get_resource
Section titled “get_resource”リソースのメタデータを取得します。アップロード済みファイルの場合はダウンロード URL を返します。
セクションに入っているリソースは Section: 行を持ちます。
本文を抽出済みの文書(PDF・Word・PowerPoint・Excel・一太郎。2007 より前の Office 形式を含む)は Document text: 行を持ち、
get_document_outline と get_document_section で読めることを示します(全ページがスキャンの文書はその旨)。
サイトで AI による説明が有効な場合、末尾に説明文が
付きます。あわせてそのファイルのどこまでを読んで書いたか(read the column layout and the first 100 of 1200 rows など)と、どの版を説明しているかが返ります。ファイルが差し替え済みで
説明が追いついていない場合は describes v1, and the file is now v2 のように示されるため、
古い説明を最新と取り違えることはありません。説明が生成されなかった場合は理由が返ります。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string | Yes | リソース UUID |
get_resource_schema
Section titled “get_resource_schema”リソースの列スキーマ(列名・型・null 許容・行数、数値列の min/max)を取得します。リソースに
主キーが確定されていれば Primary key: 行として併記されます。各列には役割(名称、カテゴリ、
自由記述、識別子、数値・日付、文字列表記数値)が付き、名称とカテゴリの列には出現の多い値が、
文字列表記数値の列には数値として読めない値が添えられます。表形式(CSV/TSV と、レコードの一覧として
読める JSON/GeoJSON)でプレビュー生成済みのリソースのみクエリ可能です。クエリ可能な場合のみ、出力にクエリ用
テーブル名 data とクエリ例が含まれ、エージェントはこれを見てから SQL を書けます。
クエリ不可の場合(プレビューが無い・現在の内容を反映していない)は、列一覧は参考として
返しつつクエリ案内を省きます。
OData フィードの可否も併せて返します。 配信される場合はフィード URL(末尾 /Rows)と、
行を同定する列 — 主キーがその役を果たすか、KUKAN が RowId 列を足すか、足すならその理由 — を
示します。1 行が大きく読み込みに失敗しうる表には、その注意も付きます。
配信されない場合は理由(見出しが OData 識別子にならない、同名の列がある、データセットが
非公開・下書きなど)を返します。SQL が撃てることと OData で読めることは一致しませんので、
取得方法を選ぶ前にこの行を見てください。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string | Yes | リソース UUID |
query_resource
Section titled “query_resource”リソースのデータに対して読み取り専用 SQL(SELECT / WITH のみ)を実行し、結果を Markdown
テーブルで返します。データは data というテーブルとして参照します。get_resource_schema で列名・型を
確認してから利用してください。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string | Yes | リソース UUID |
sql |
string | Yes | 単一の SELECT/WITH 文(data テーブルを対象) |
使い捨ての in-memory DuckDB 上で実行され、外部アクセス禁止・行数/バイト/時間の上限付きです。列名に
非 ASCII を含む場合は二重引用符で囲みます。制限・エラーの詳細は REST の /resources/{id}/query を参照。
get_document_outline
Section titled “get_document_outline”文書の目次を取得します。何を読むかを決めるために、get_document_section の前に呼びます。
- 見出し:PDF のしおり(しおりが無ければ見出しのタグ)、Word の見出しスタイル、スライドのタイトルを、階層の字下げ付きで並べます。
それぞれに、その見出しの範囲のページ(スライド)が付きます(
pages 15–18 1-1-3 職員に関する事項) - ブック:見出しの代わりにシートを並べ、シート名と行の範囲を付けます
- ページ数と読めないページ:ページ(スライド・シート)の範囲と、読める文字の無いページ(スキャンなど)、一部の文字が読めないページ(PDF のフォントが文字の対応を持たない字形。本文からは外しています)を示します
- 先頭には
get_document_sectionと同じ出典が付きます
2007 より前の Word(DOC)と一太郎は、読み取れる見出しを持たないので、本文は 1 ブロックになります。 一太郎でシートが複数ある文書は、シートごとに 1 ブロックになり、シートの番号で引けます。
全ページがスキャンで本文の無い文書でも、ページ数・見出し・読めないページは返します。
長い目次は約 12,000 字で切り(見出しは 1 件 120 字まで、読めないページの一覧はその 4 分の 1 まで)、残りの件数を示します。そのときは from・to でページを絞って見てください。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string | Yes | リソース UUID |
from |
number | No | 最初のページ・スライド・シート(1 始まり) |
to |
number | No | 最後のページ・スライド・シート |
get_document_section
Section titled “get_document_section”KUKAN が文書(PDF・Word・PowerPoint・Excel・一太郎。2007 より前の Office 形式を含む)から抽出した本文を、ファイルの中の位置で指定して 取得します。位置はページの範囲(PDF はページ、プレゼンテーションはスライド、ブックはシート)、 見出し、またはその両方で指定します。AI のモデルは呼ばず、ファイルにある本文をそのまま返します。
応答の先頭には、引用に使う出典が付きます — リソース名とデータセット名、リソースページとファイルの
URL(PDF は #page=N を付けるとそのページで開きます)、フォーマット、版。本文はブロックごとに、
ページ(印刷上のページ番号が違う場合はそれも)・スライド・シートと行、その上の見出しで示されます
(--- page 12 (iv) · 第2章 > 人口)。読める文字の無いページ(スキャンなど)は、省かずにその旨を
示します。一部の文字が読めないページは、本文から外した字数を示します。ファイルが差し替えられ、本文の抽出がまだ追いついていない場合は、Version: の代わりに
本文の版(Text from: version 1)と今のファイルの版(Current file version: 2)を分けて示します。
引用には本文の版を使ってください。
見出しは、指定した文字列を含むものに一致します。大文字・小文字、全角・半角、空白の違いは無視し、
シート名にも一致します。Word のファイルはレイアウトするまでページを持たないため、見出しでだけ
指定できます。第1章 > 概要 のように見出しを > でつなぐと、ある見出しの下の見出しを指定できます。
一致するものが無い場合は、その文書のページの範囲を返し、get_document_outline で目次を見るよう案内します。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string | Yes | リソース UUID |
from |
number | No | 最初のページ・スライド・シート(1 始まり) |
to |
number | No | 最後のページ・スライド・シート(その番号を含む) |
heading |
string | No | 本文の上にある見出し、またはシート名の一部 |
max_chars |
number | No | 返す本文の文字数(デフォルト: 8,000、最大: 32,000) |
cursor |
string | No | 前の応答の末尾にあったカーソル。from・to・heading はカーソルから取る |
長い範囲は途中で切り(できるだけ改行の位置で)、続きを読むためのカーソルを末尾に付けます。 文書の抽出がやり直されると、それ以前のカーソルは使えなくなります。
目次と本文は REST の GET /api/v1/resources/{id}/document-outline・document-section でも読めます(パラメータは同じで、応答は JSON です)。
search_passages
Section titled “search_passages”カタログ全体の文書(PDF・Word・PowerPoint・Excel・一太郎)の本文から、検索語に一致する箇所を、
よく一致するものから順に返します。まず search_datasets と同じ検索でデータセットとリソースを探し、
次にその文書の本文の中から一致する箇所を選びます。すべての語を持つデータセットが無いときは、
search_datasets と同じく語の少ない一致に緩めて文書を探し、先頭でそう知らせます。生成 AI は呼びません(文書を意味の近さでも探すため、
検索語の埋め込みは作ります。埋め込みのモデルが無いサイトでは語の一致だけで探します)。CSV などの表は
対象外です(get_resource_schema と query_resource を使ってください)。
各箇所の先頭には、get_document_section と同じ出典が付きます(PDF のファイルの URL は、その箇所の
ページを開く #page=N 付き)。続いて、箇所の位置(ページ・スライド・シートと、その上の見出し)、
一致した語、本文を示します。各箇所にはカーソルが付き、get_document_section に渡すと、その箇所の
ページから前後を読めます。ページの無い文書(Word)でも、箇所の位置から読み始められます。
文書の中の箇所は語で照合し、意味では照合しません。見つからない場合は、文書で使われていそうな語 (行政の用語など)に言い換えて検索し直してください。返した数より多くの箇所が一致した場合は、 応答の末尾でそう知らせます。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
q |
string | Yes | 検索語 |
organization |
string | No | 組織名(slug)でフィルタ |
tags |
string[] | No | タグ名でフィルタ |
k |
number | No | 返す箇所の数(デフォルト: 5、最大: 20) |
per_resource |
number | No | 1 つのリソースから返す箇所の数の上限(デフォルト: 2) |
max_chars |
number | No | 返す本文の文字数、全箇所の合計(デフォルト: 8,000、最大: 32,000) |
同じ検索は REST の GET /api/v1/passages でも使えます(パラメータは同じで、semantic=false で語の一致だけにできます)。
list_organizations
Section titled “list_organizations”| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
q |
string | No | 名前で検索 |
offset |
number | No | スキップ件数(デフォルト: 0) |
limit |
number | No | 最大件数(デフォルト: 20、最大: 100) |
list_groups
Section titled “list_groups”| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
q |
string | No | 名前で検索 |
offset |
number | No | スキップ件数(デフォルト: 0) |
limit |
number | No | 最大件数(デフォルト: 20、最大: 100) |
list_tags
Section titled “list_tags”| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
q |
string | No | 名前で検索 |
offset |
number | No | スキップ件数(デフォルト: 0) |
limit |
number | No | 最大件数(デフォルト: 50、最大: 200) |
MCP エンドポイントは KUKAN の認証システムと連携しています。
- 未認証: 公開データセットのみアクセス可能
- 認証済み: 所属組織の非公開データセットもアクセス可能
- システム管理者: すべてのデータセットにアクセス可能
認証する場合は、API トークンを Authorization: Bearer kukan_... ヘッダーで送ってください(認証)。
- プロトコル: MCP (Model Context Protocol)。版は初期化時にクライアントと交渉します(2024-11-05 以降の版に対応)
- トランスポート: Streamable HTTP
- モード: ステートレス(セッション管理なし)
- レスポンス形式: JSON-RPC 2.0