雑に学ぶMCP
いまさらですがcaki.icon
Host、Client、Serverで構成される
自分の理解でclientとserverがやることがごちゃついてる
すべてのメッセージは JSON-RPC 2.0 形式でやりとりされる
llmさんがこのアプリの機能使いたいなーと思う
initialize
request: clientがserverにinitializeリクエストを送る
clientのcapabilitiesが宣言される
roots: どのファイルシステムのルートにアクセスできるか
sampling: サーバからクライアント経由でLMの推論を依頼できる?その内容がどう定義されているか?
sampling/createMessageで定義されてるっぽい
serverがなんらかの理由でLLMの推論がさらに必要だ、となったときがどう定義されてるんだ?というのがよくわからない
こういうことか?
LLMが「水をバケツにためよう」と思って、clientに「蛇口をひねりなさい」と指示
clientは蛇口をひねる機能がserverからもらったリストにあるか確認する、ある場合はserverに「蛇口をひねる」と指示する
server側でsampling/createMessageを見ると「蛇口をひねって水がちゃんと出たとき、どのくらいで止めるかを聞く」とかいてある。serverは「水をどれくらいで止めるか?」とclientに聞く
そして、clientはllmに「どれくらいたまったら蛇口をしめる?」と聞く
MCP clientとMCP serverが別々で用意されるのかcaki.icon*2
result: serverが返答を返す
「ええよ〜、こんなん使えるよ」
toolsのリストを返す
返答を受け取ったclientがnotifications/initializedを返す
「り、使いはじめますー」
つまりMCPサーバにはアプリをつかうためのロジック(たぶんAPI経由でアプリが使える?)とMCPで決められた挙動を定義する部分がふくまれてる…ってコト!? そうっぽい
code:蛇口アプリを扱うMCPサーバの構成例
my-mcp-server/
├── package.json
├── tsconfig.json
└── src/
├── index.ts # エントリーポイント・サーバー起動
├── tools/ # 「手」の定義
│ ├── index.ts # ツール一覧をまとめてexport
│ ├── faucet.ts # 蛇口をひねる関数
│ └── bucket.ts # バケツを置く関数
└── clients/ # 外部APIとの通信
└── faucetApi.ts # 蛇口のAPIクライアント