コンテンツにスキップ
コンソール →
公式サイト →
URL を貼り付けて AI に質問 https://keelson.dev/ja/llms.txt

AI クライアントから使う(MCP)

アプリを MCP サーバー(AI クライアントからアプリを使う機能)にできます。MCP(Model Context Protocol)は、Claude や ChatGPT などの AI クライアントが、外部の「ツール」を一覧して呼び出すための取り決めです。たとえば在庫管理アプリに「品目を検索する」「入荷を記録する」ツールを用意すると、利用者は AI クライアントとの会話の中から、自分の権限の範囲でアプリを操作できます。

アプリ側で用意するのは、keelson.yaml の mcp: でのツールの宣言と、ツールごとの JSON の受け口(ハンドラ)だけです。ログイン、同意画面、AI クライアントとの MCP のやり取りは Keelson が受け持ちます。

  1. アプリ作者が keelson.yaml の mcp: にツールを宣言してデプロイします
  2. 利用者が AI クライアントに接続 URL(アプリの URL + /mcp)を登録します
  3. 初回は Keelson のログインと同意画面が出ます。利用者が承認すると、AI クライアントがその利用者として接続されます
  4. AI クライアントがツールを呼ぶと、Keelson がメンバーであること・アプリの権限・IP 制限を確かめ、引数を宣言どおりか検査します
  5. Keelson がアプリの POST /api/mcp/<ツール名> を呼び、アプリが返した JSON をツールの結果として AI クライアントに返します

使えるのは、サーバー側のプログラムが動くアプリ(command があり assets がないアプリ)だけです。静的サイト・SPA・ハイブリッド構成では宣言できません。全プランで使え、プランによる違いはありません。

keelson.yaml に mcp: を書いてデプロイします。次の例は、読み取りのツール search_items と、書き込みのツール create_arrival を宣言しています。

slug: stock-desk
runtime: python-slim
command: "python app.py"
db:
mode: libsql
mcp:
enabled: true
instructions: "Look up stock levels and record incoming deliveries."
tools:
- name: search_items
description: "Search stock by item name."
access: read
input:
type: object
properties:
query:
type: string
required: [query]
- name: create_arrival
description: "Record one incoming delivery."
access: write
permission: manage
input:
type: object
properties:
item_id:
type: string
quantity:
type: integer
minimum: 1
required: [item_id, quantity]
キー意味
enabledtrue でツールを公開します。false にすると宣言を残したまま呼び出しを止めます
instructionsAI クライアントに渡す、ツール全体の説明(省略可)
tools[].nameツール名。英小文字で始まり、英小文字・数字・_ だけ。アプリの受け口は POST /api/mcp/<name> になります
tools[].descriptionAI クライアントに見せるツールの説明。AI はこれを読んで、いつ呼ぶかを決めます
tools[].accessread(読み取り)か write(データを変更する)。読み取りと書き込み・権限を参照
tools[].permissionview(既定)か manage。manage のツールはアプリの管理権限を持つ人だけが使えます
tools[].input引数の形(JSON Schema 2020-12)。最上位は type: object

各キーの型・上限・検査の詳細は keelson.yaml リファレンスを参照してください。

ツールが多いときは別ファイルに分ける(mcp.file)

Section titled “ツールが多いときは別ファイルに分ける(mcp.file)”

mcp.file を使うと、instructions と tools を別の YAML ファイルに置けます。keelson.yaml には enabled と file だけを書きます。

slug: stock-desk
runtime: python-slim
command: "python app.py"
db:
mode: libsql
mcp:
enabled: true
file: mcp.yaml

keelson.yaml と同じフォルダの mcp.yaml:

instructions: "Look up stock levels and record incoming deliveries."
tools:
- name: search_items
description: "Search stock by item name."
access: read
input:
type: object
properties:
query:
type: string
required: [query]
- name: create_arrival
description: "Record one incoming delivery."
access: write
permission: manage
input:
type: object
properties:
item_id:
type: string
quantity:
type: integer
minimum: 1
required: [item_id, quantity]
  • デプロイ時に Keelson CLI が mcp.yaml の中身を keelson.yaml に差し込んでから検査・送信します。手元のファイルは書き換えません
  • 別ファイルに書けるのは instructions と tools だけです。mcp.file と mcp.instructions / mcp.tools は同時に書けません
  • mcp.file を読めるのは新しい Keelson CLI だけです。古い CLI は「未対応のキー」としてデプロイを拒否します。その場合は keelson upgrade で CLI を最新版にしてください

ツールが呼ばれると、Keelson がアプリに POST /api/mcp/<ツール名> を送ります。パスはツール名で決まり、変更できません。

本文は、AI クライアントが渡した引数の JSON オブジェクトです(引数がなければ {})。宣言した input で検査済みのものだけが届きます。

ヘッダーは Keelson が組み立てたものだけが届きます。AI クライアントが送ったヘッダーは 1 つも引き継がれないため、AI クライアントのアクセストークンや、偽造された X-Keelson-* ヘッダーはアプリに届きません。

ヘッダー内容
X-Keelson-User-Id接続した利用者のユーザー ID。本人の識別にはこれを使います
X-Keelson-User-Email同じ利用者のメールアドレス
X-Keelson-User-Name同じ利用者の表示名
X-Keelson-User-App-Permsその利用者のアプリの権限(view または view,manage)
X-Keelson-Auth-Sourcemcp(MCP 経由の呼び出しであることを示す)
X-Keelson-Mcp-Tool呼ばれたツール名
X-Keelson-Mcp-ClientAI クライアントの識別子(URL)
X-Request-Idリクエスト ID。エラーの結果にも request id: として表示されます

Authorization ヘッダーには Keelson の内部で使う値が入ります。AI クライアントのトークンではないため、アプリでは使いません。ユーザー情報ヘッダーの使い方はログイン中のユーザー情報を使うと同じです。

応答は 2xx の JSON(1 MiB まで)で返します。JSON オブジェクトを返すと、AI クライアントが項目を読み取りやすくなります。

アプリの応答AI クライアントに返る結果
2xx と JSON の本文ツールの結果として本文の JSON を返す
2xx で本文が空・JSON でない・1 MiB を超えるエラー(ツールの応答が不正)
4xxエラー。本文の先頭 4 KiB を利用者と AI クライアントにそのまま見せる
3xx・5xxエラー(ツールの実行に失敗)。本文は見せない
60 秒以内に応答がないエラー(実行されたか分からない)
  • 4xx の本文は利用者と AI クライアントに見えます。 見せてよい説明だけを書きます(例:「品目 A-100 が見つかりません」)
  • 1 回の呼び出しは全体で 60 秒までです。時間がかかる処理はバックグラウンドタスクに投入して、すぐに応答を返します
  • Keelson は失敗した呼び出しを再試行しません
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.post("/api/mcp/search_items")
async def search_items(request: Request):
user_id = request.headers["X-Keelson-User-Id"]
args = await request.json() # 例: {"query": "ねじ"}
items = find_items(owner=user_id, query=args["query"]) # アプリの検索処理
return {"items": items}
@app.post("/api/mcp/create_arrival")
async def create_arrival(request: Request):
perms = request.headers.get("X-Keelson-User-App-Perms", "").split(",")
if "manage" not in perms:
return JSONResponse({"error": "入荷を記録する権限がありません"}, status_code=403)
args = await request.json()
if not item_exists(args["item_id"]):
# 4xx の本文は利用者に見える
return JSONResponse({"error": f"品目 {args['item_id']} が見つかりません"}, status_code=404)
arrival_id = record_arrival(args["item_id"], args["quantity"])
return {"arrival_id": arrival_id}
app.use(express.json());
app.post("/api/mcp/search_items", (req, res) => {
const userId = req.headers["x-keelson-user-id"];
const items = findItems({ owner: userId, query: req.body.query }); // アプリの検索処理
res.json({ items });
});
app.post("/api/mcp/create_arrival", (req, res) => {
const perms = (req.headers["x-keelson-user-app-perms"] ?? "").split(",");
if (!perms.includes("manage")) {
return res.status(403).json({ error: "入荷を記録する権限がありません" });
}
const { item_id, quantity } = req.body;
if (!itemExists(item_id)) {
// 4xx の本文は利用者に見える
return res.status(404).json({ error: `品目 ${item_id} が見つかりません` });
}
res.json({ arrival_id: recordArrival(item_id, quantity) });
});

permission: manage のツールは、管理権限を持たない人からは Keelson が呼び出しを通しません。上の例のようにアプリ側でも X-Keelson-User-App-Perms を確かめておくと、宣言を変えたときにも安全です。

  • access: write のツールは、同意画面で「書き込みツール(データを変更できる)」として別に表示されます。 利用者は「読み取りツールだけ承認」を選べます。その場合、書き込みツールは使えません。後から使うには、接続し直して承認します
  • permission: manage のツールは、アプリの管理権限(manage)を持つ人だけが使えます。 権限の割り当てはメンバーとロールを参照してください
  • 使えないツールは一覧に出ません。 権限が足りないツールと、同意していない書き込みツールは、AI クライアントのツール一覧から除かれます
  • 呼び出しはすべて、接続した利用者本人として、その人の権限の範囲で行われます。メンバーから外れた人やアプリの閲覧権限を失った人の呼び出しは、通常 2 分以内に拒否されるようになります

利用者は、AI クライアントに接続 URL を登録します。接続 URL はアプリの URL の末尾に /mcp を付けたもの(例: https://acme--stock-desk.keelson.run/mcp)で、コンソールのアプリの MCP タブにも表示されます。接続 URL の登録方法は、各 AI クライアントの MCP 設定のドキュメントを参照してください。

  1. AI クライアントに接続 URL を登録します
  2. 初回は Keelson のログイン画面が開きます。アプリを使えるアカウントでログインします
  3. 同意画面で、AI クライアントに使わせるツールを確認して 承認 を選びます
  • 接続できるのは、そのアプリを閲覧できるメンバーだけです
  • 受け付ける AI クライアントは、claude.ai または chatgpt.com の身元を名乗るものだけです。それ以外のクライアントは、接続 URL を登録してもログインの段階で止まります
  • アクセストークンの有効期間は 1 時間で、AI クライアントが自動で更新します。更新用のトークンは、60 日使われないか、接続から最長 180 日で切れます。切れたら接続し直します
  • 同じ AI クライアントで同じアプリに接続し直すと、前の接続は解除されます
操作できる人効果
ワークスペースの MCP を停止(設定 → セキュリティ → MCP(AI クライアント))Owner / Adminワークスペースのすべてのアプリで呼び出しを止める。接続は残り、許可に戻すとそのまま使える
mcp.enabled: false にしてデプロイアプリをデプロイできる人そのアプリの呼び出しを止める。接続は残り、true に戻してデプロイするとそのまま使える
アプリの MCP タブの「接続中の AI クライアント」で 失効Owner / Admin、アプリの管理権限を持つ人その接続を解除する。AI クライアントは更新用のトークンも含めて直ちに使えなくなる
「自分の接続中の AI クライアント」で 失効接続した本人自分の接続を解除する

停止と mcp.enabled: false は呼び出しを止めるだけです。接続そのものを失効させるのは、解除(失効)だけです。 「自分の接続中の AI クライアント」は、設定 → セキュリティ と同意画面からリンクしています。

  • mcp.enabled: true のアプリでは、/mcp、/.well-known/oauth-protected-resource、/.well-known/oauth-protected-resource/mcp は Keelson が応答し、アプリには届きません
  • サーバー側のプログラムが動くアプリ(ハイブリッド構成のサーバー側を含む)では、/api/mcp と /api/mcp/ で始まるパスは、mcp: を宣言していなくても MCP 経由以外では 404 になります。このパスにはツールのハンドラ以外のルートを置かないでください。静的に配信される部分には影響しません

予約パスの一覧は Keelson Deploy Spec の予約 URL パスを参照してください。

項目上限
ツールの数1 アプリ 40 本
instructions4096 文字
ツールの description1024 文字
ツールの inputJSON にして 64 KB・入れ子 32 段
1 回の呼び出し60 秒
応答の本文(2xx)1 MiB
呼び出し回数1 接続あたり 1 分 60 回
同時に実行される呼び出し1 アプリ 10(Keelson の中継サーバー 1 台ごとの値。中継サーバーが増えるとアプリ全体ではこれより多く同時に届くことがあります)

回数と同時実行の上限を超えた呼び出しは、少し待ってから再試行するよう AI クライアントに返されます。上限はプランで変わりません。同時実行の 10 はアプリが受ける同時呼び出しの最大値ではないので、データベースの接続数などを 10 件前提で決めないでください。

症状確認すること
ツールが一覧に出ないその利用者にアプリの権限があるか(permission: manage のツールは管理権限が必要)。書き込みツールなら、同意画面で承認したか。mcp.enabled が true か。ワークスペースの MCP が停止されていないか(アプリの MCP タブの状態に表示されます)
IP 制限のあるワークスペースで呼び出しが拒否されるIP 制限は MCP 経由の呼び出しにも適用されます。claude.ai や ChatGPT からの呼び出しは利用者の PC ではなく各社のサーバーから届くため、そのままでは許可されません。IP 制御のアクセス元を見直してください
「ツールの応答が不正」と表示されるハンドラが 2xx で JSON の本文を返しているか。本文が空・テキスト・1 MiB 超になっていないか
ログインの後に接続できないAI クライアントが claude.ai または chatgpt.com の身元を名乗るものか。ログインしたアカウントがアプリを閲覧できるメンバーか
デプロイで mcp の file が未対応のキーとして拒否されるKeelson CLI が古いため。keelson upgrade で最新版にしてからデプロイし直します