Upgrade to Pro — share decks privately, control downloads, hide ads and more …

管理画面いらずの運用を実現するため、Protocol Buffers から MCP サーバーを...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

管理画面いらずの運用を実現するため、Protocol Buffers から MCP サーバーを生成する protoc プラグインを作った

Avatar for yoshihiro shu

yoshihiro shu

July 21, 2026

More Decks by yoshihiro shu

Other Decks in Technology

Transcript

  1. 前提 言葉の定義 Protocol Buffers(proto) … データ構造や API を .proto に定義するスキーマ言語

    protoc … .proto からコードを生成するコンパイラ protoc プラグイン … protoc を拡張し、独自のコードを生成する仕組み MCP … AI エージェントが外部ツールを呼ぶための標準プロトコル OSS: github.com/yoshihiro-shu/connect-go-mcp 5
  2. 課題① それぞれのアクションごとにコミュニケーションが発生する 1 🙋 ユーザー 2 問い合わせ 🎧CS 3 「確認お願いします」

    エンジニア API を実⾏ 🔁 この⼀連のやりとりが、対応のたびに毎回発⽣する OSS: github.com/yoshihiro-shu/connect-go-mcp 10
  3. 解決策 MCP とは MCP (Model Context Protocol):LLM と外部ツールをつなぐ 標準プロトコル(Anthropic 提唱)

    MCP サーバーを実装すると、Claude Desktop 等の MCP クライアントから任意のツールを呼べる 既存の API を「LLM が使えるツール」に変えられる 🤖 MCP クライアント Claude 等 OSS: github.com/yoshihiro-shu/connect-go-mcp 🔧 MCP サーバー ツール定義 🗄 あなたの API 既存の管理 API 14
  4. 解決策のメリット APIレスポンスをわかりやすくしてくれる AIエージェントがレスポンスを "ツールの情報" をもとに、人間向けに整理・説明してくれる。 // API が返す生のレスポンス(機械向け) {"orders":[ {"id":123,"amount":4980,"status":"unshipped","created_at":"2026-07-01"},

    {"id":118,"amount":12800,"status":"shipped","created_at":"2026-06-20"} ]} ↓ AI が整理・説明(自然言語) 直近の注文は 2件 です。 ・#123 ¥4,980(7/1)… 未発送 ・#118 ¥12,800(6/20)… 発送済み → 未発送が 1 件あります。対応しますか? OSS: github.com/yoshihiro-shu/connect-go-mcp 16
  5. 実装 MCP サーバーの実装方法 AI エージェントに公開する ツールの仕様と説明を定義する // ① サーバーを作る s

    := mcp.NewServer(&mcp.Implementation{Name: "order"}, nil) // ② ツールを登録する(名前・説明・入力スキーマ + 呼ばれたときの処理) mcp.AddTool(s, &mcp.Tool{ Name: "GetOrders", Description: "指定したユーザーの注文履歴を取得する", InputSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "user_id": {Type: "string"}, "limit": {Type: "integer"}, "only_unshipped": {Type: "boolean"}, }, }, }, getOrdersHandler) // ③ 標準入出力で待ち受ける(Claude Desktop が接続してくる) s.Run(ctx, &mcp.StdioTransport{}) OSS: github.com/yoshihiro-shu/connect-go-mcp 17
  6. 課題② 私たちの開発スタイル スキーマ駆動開発:API(Protocol Buffers)設計を最初に定義し、フロントエンドとバックエンドの開発を並 行して進める Protocol Buffers が API仕様書の役割を持つ Protocol

    Buffers が Single Source of Truth(単一の信頼できる情報源) service OrderService { // 指定したユーザーの注文履歴を取得する rpc GetOrders(GetOrdersRequest) returns (GetOrdersResponse); } // 注文履歴の取得リクエスト。 // user_id のユーザーの注文を、新しい順に返す。 // limit で件数を制限、only_unshipped で未発送のみに絞れる。 message GetOrdersRequest { string user_id = 1; // 対象ユーザーID(必須) int32 limit = 2; // 取得件数(0 なら全件) bool only_unshipped = 3; // 未発送のみに絞る } OSS: github.com/yoshihiro-shu/connect-go-mcp 19
  7. 課題② Protocol Buffers と MCP サーバーの二重管理 Protocol Buffers に API(RPC)の仕様を定義しているため、二重管理になってしまう

    s := mcp.NewServer(&mcp.Implementation{Name: "order-service"}, nil) // ツールを1つずつ、手で定義していく mcp.AddTool(s, &mcp.Tool{ Name: "GetOrders", Description: "指定したユーザーの注文履歴を取得する", InputSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "user_id": {Type: "string"}, "limit": {Type: "integer"}, "only_unshipped": {Type: "boolean"}, }, }, }, getOrdersHandler) // rpc が増えるたびに、AddTool を手で書き足す… OSS: github.com/yoshihiro-shu/connect-go-mcp 20
  8. 課題② MCP サーバーを手で書くと、二重管理になる 同じ情報をProtocol Buffers と MCP サーバーの2箇所で管理 Protocol Buffers

    を変更するたびに、MCP サーバーを変更する必要がある Single Source of Truth が崩れる OSS: github.com/yoshihiro-shu/connect-go-mcp 21
  9. 仕組み このOSSがやっていること 1. Protocol Buffers の service / rpc /

    field を読み取る 2. service / rpc / field の 名前・コメント・型を取り出す 3. 標準パッケージの MCP サーバーとして、ファイルに書き出す OSS: github.com/yoshihiro-shu/connect-go-mcp 24
  10. 仕組み このOSSが使うライブラリ protobuf 公式( google.golang.org/protobuf ) protogen … protoc をプラグインとして拡張するためのライブラリ

    stdin/stdout のインターフェース proto の service / rpc / fieldやそのコメントの取得 コード・ファイル生成 protoreflect … proto の型定義の読み取り OSS: github.com/yoshihiro-shu/connect-go-mcp 25
  11. ① 解析 ① Protocol Buffers の service / rpc /

    field を解析する は指定した proto ファイルの service, rpc, field をまとめた構造体の配列 gen.Files を利用し、service / rpc / field をそれぞれ取得していく gen.Files for _, f := range gen.Files { for _, s := range f.Services { for _, m := range s.Methods { // .proto ファイル // service = OrderService // rpc = GetOrders for _, field := range m.Input.Fields { // リクエストの各フィールド // ↓ 1フィールドずつ ② の処理へ } } } } github.com/yoshihiro-shu/connect-go-mcp/blob/main/cmd/protoc-gen-connect-go-mcp/parser/parser.go OSS: github.com/yoshihiro-shu/connect-go-mcp 27
  12. ② 取得 ② service / rpc / field の 名前・コメント・型を取得する

    それぞれの要素の名前・コメント・型を取り出す s.Desc.Name() // service 名 s.Comments.Leading m.Desc.Name() // service のコメント // rpc 名 → ツール名 m.Comments.Leading field.Desc.Name() // rpc コメント → ツールの説明 // field 名 → 引数名 field.Comments.Leading field.Desc.Kind() // field コメント → 引数の説明 // field の型 → JSON Schema 型 github.com/yoshihiro-shu/connect-go-mcp/blob/main/cmd/protoc-gen-connect-go-mcp/parser/parser.go OSS: github.com/yoshihiro-shu/connect-go-mcp 28
  13. ③ 出力 ③ MCP サーバーとして、ファイルに出力する ( protogen.GeneratedFile )は、protogen のファイルを生成する構造体 地道に標準パッケージの

    MCP サーバーを生成していく g // service を受け取り、g.P で1行ずつコードを書き出す g.P("func New", service.Name, "MCPServer(...) *mcp.Server {") g.P(" server := mcp.NewServer(...)") g.P(" toolHandler := connectgomcp.NewToolHandler(baseURL)") for _, method := range service.Methods { g.P(" mcp.AddTool(server, &mcp.Tool{") g.P(" Name: \"", method.Name, "\",") g.P(" Description: \"", method.Comment, "\",") // ここで InputSchema を出力(各フィールドの型から) g.P(" }, handler)") } g.P(" return server") g.P("}") // 関数の入口 // MCP サーバー本体 // API を呼ぶ係 // rpc の数だけ繰り返す // ツールを1つ登録 // ツール名 ← rpc 名 // 説明 ← rpc コメント // 呼ばれたら API を叩く // 組み立てたサーバーを返す github.com/yoshihiro-shu/connect-go-mcp/blob/main/cmd/protoc-gen-connect-go-mcp/template/template.go OSS: github.com/yoshihiro-shu/connect-go-mcp 29
  14. ③ 出力 Protocol Buffers から MCP サーバーが生成される // 指定したユーザーの注文履歴を取得する ①

    rpc GetOrders(GetOrdersRequest) returns (...); message GetOrdersRequest { string user_id = 1; // ② int32 limit = 2; // ③ bool only_unshipped = 3; // ④ } ↓ buf generate を実行 &mcp.Tool{ Description: "指定したユーザーの注文履歴を取得する", // ① InputSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "user_id": {Type: "string"}, // ② "limit": {Type: "integer"}, // ③ int32 → integer "only_unshipped": {Type: "boolean"}, // ④ bool → boolean }}} OSS: github.com/yoshihiro-shu/connect-go-mcp 30
  15. 仕組み MCP サーバーのファイルが出力される .proto を渡すと、3ステップで MCP サーバーのファイルが出力される。 📄 order.proto ⼊⼒

    OSS: github.com/yoshihiro-shu/connect-go-mcp protoc プラグイン(connect-go-mcp) ① 解析 service / rpc / field を読み取る(protogen) ② 取得 名前・コメント・型を取り出す ③ 出⼒ g.P で Go コードを書き出す 📄 order.mcpserver.go MCP サーバー 31
  16. 使い方 使い方:導入は3ステップ # ① インストール go install github.com/yoshihiro-shu/connect-go-mcp/cmd/protoc-gen-connect-go-mcp@latest # ②

    buf.gen.yaml に1行追加 plugins: - local: protoc-gen-connect-go-mcp out: gen opt: paths=source_relative # ③ 生成 buf generate # *.mcpserver.go が生成される → Protocol Buffers と同期された MCP サーバーが生成される OSS: github.com/yoshihiro-shu/connect-go-mcp 32
  17. 実運用での配慮 本番データを、AI エージェントにどう安全に扱わせるか 本番の管理 API を AI エージェントから実行できる以上、安全面の配慮が必要になる。 ① 秘匿情報の制御

    個人を特定する情報は、そもそも出力しない ID を指定して、契約状態など必要最低限だけを取得 その ID の解決は、AI エージェントを介さない手段で行う ② 権限管理(アクセス制御) 利用者・実行環境を限定する ③ ガバナンス(監査) 実行履歴をログに残し、あとから監査できるようにする OSS: github.com/yoshihiro-shu/connect-go-mcp 33