世界を動かす技術を、日本語で。

MCPはツールではなく、コードが必要だ

概要

  • CLIツール にはプラットフォーム依存やセッション管理の課題が存在
  • MCP(Model Context Protocol) は状態管理に優れるが、ツールの合成が難しい
  • Pythonインタプリタ を1ツールとしてMCPサーバーで実装する手法の提案
  • pexpect を活用し、状態を保持したデバッグや自動化が可能
  • コード例を通じて、 MCPの利点 とCLIの課題を比較

CLIベースのツール利用における課題

  • CLIツール はプラットフォームやバージョン依存、ドキュメント不足の問題
  • 非ASCII文字列や制御文字入力時の不具合発生
  • エージェント型コーディングツール は新規ツールや未知のシンタックスに弱い傾向
  • セキュリティ対策としての 事前チェック(preflight) による遅延(特にClaude Code)
  • セッション管理の難しさ(例:tmuxセッションの状態喪失)
  • 小さなミスでセッションがリセットされるなど、失敗時のリカバリー困難

CLIにおける合成性とその限界

  • bash 等のシェル言語を介したツール合成が可能
  • シンプルなコマンドの組み合わせや スクリプト化 で柔軟性を担保
  • しかし、MCPでは 推論なしでのツール合成が困難
  • コマンドラインは複数ツールの連携が容易だが、MCPはツール単体利用が前提

MCPサーバーの新しいアプローチ

  • MCPサーバー で「1ツール=Pythonインタプリタ」を採用する手法
  • 状態管理 はMCPが得意とする分野
  • Pythonインタプリタを通じて pexpect 等のSDKを利用可能
  • MCPのインターフェースを プログラミング言語(Python) に統一
  • セッション中のコードをそのまま再利用可能なスクリプトに変換可能

pexpectを活用したMCPツールの実例

  • pexpect は古く安定したAPIを持つ、CLI操作自動化用Pythonライブラリ
  • MCPツールとしてpexpect_toolを実装
    • Pythonコードをセッション状態で実行
    • 例:LLDBデバッグセッションの自動化
  • コード例
    • プロセス起動、コマンド送信、出力取得、例外処理など一連の操作をPythonで記述
    • セッション内での状態維持が容易

MCPの利点とCLIとの比較

  • 状態管理 やセッション維持がMCPの強み
  • CLIではエージェントが状態を追いきれず失敗リスク増
  • プログラミング言語としてのPython を利用することで、エージェントの学習済みパターンを活用
  • MCPセッションの履歴を活かし、再利用可能なスクリプト生成も容易

まとめ

  • CLIツールは柔軟だが、 セッション管理や合成性に課題
  • MCPは状態管理に優れるが、 ツール合成や未知ツール対応が課題
  • Pythonインタプリタ+pexpect をMCPツールとして活用することで両者の利点を統合
  • 今後は MCPサーバーの拡張 やエージェントの適応力向上が期待

Hackerたちの意見

何かを略語で書くときの第一ルールは、まずその内容について説明を加えることだね。略語が何を指しているのかをちゃんと書くか、説明を入れるか、少なくとも他のページへのリンクを貼って、何が起こっているのかを説明する必要があるよ。編集:このリンクは修正されたので、今は古い情報だね。

または少なくとも何が起こっているのかを説明する他のページへのリンクがある その著者の以前の投稿へのリンクがあって(最初の10語の中にさえ!)、探しているコンテキストが含まれてるよ。

MCPはモデルコンテキストプロトコルのことだよ、生きてる世界へようこそ。洞窟の電気は消しておいてね。:) 今はMCPが何を指すのかはかなり知られていると思うけど、他の何かを指しているわけじゃないよね…?

略語が分からないなら、それはあなたがターゲットオーディエンスじゃないってことかも。このブログ投稿は、複数のMCPサーバーを使っている人たちのために書かれていて、LLMの使い方を変えることを主張してるんだ。用語の説明が必要で、略語をグーグルで調べる気もないなら、そもそも言ってることに興味がないってことだよね。株式市場のニュースに出てくる略語が何を意味するのか全く分からないし、株の人たちもCLIとAPI、LLMの違いなんて分からないけど、それが記事が悪いってわけじゃないよ。

MCPのことを言ってるの?そうなら、最初の段落の最初の文でちゃんとフルスペルが書かれてるし、詳しい投稿へのリンクもあるよ。それで、君が言った3つの基準のうち2つは満たしてるね。

「MCP」が何の略か知らないなら、この文章はあなたには向いてないよ。読んでみて、ターゲットオーディエンスじゃないと気づいたら、次に進んでいいんだ。あるいは、自分の時間を使って調べてもいい。HTTPやAPIが説明されてないと文句を言うようなものだよ。

これをやりたい人のために言っておくと、初頭の略語を紹介する正しい方法は、最初にフルタームを使って、その後に略語をカッコ内に入れることだよ。その後は略語だけを使えばいい。常にオーディエンスを考慮するべきだけど、ほとんどの非カジュアルな文章では、いろんな理由からこれが良いデフォルトだよ。

「MCP」は新しい「webscale」だね。 LLMが産業システムの間接的に所有されているオントロジーをオーケストレーションすることについて、哲学的な論文を書くのに使えるよ。SCADAシステムも含めてね。 https://arxiv.org/html/2506.11180v1 SCADAシステムは、以前STUXNETにハッキングされる必要があったから有名になったんだ。未来では、ただ雰囲気でハッキングできるようになるかも。

定義を探してるなら、初心者向けの記事を読むべきだよ。上級者向けじゃなくて。

これは単なるコードインジェクションなの? Pythonコードを渡すことについて話してるけど、Pythonインタープリタツールが必要だね。ガードレールを設置しても、ちょっと危険な感じがするけど、今はAIにコードを書かせる時代だから、他の人にリモートコード実行のアクセスを与えてもいいんじゃないかな、もうどうでもいいし。

そうだね、現代の開発プラクティスはRCEを機能として導入して、それを基に資金調達をすることだよ。

セキュリティについて:AIアシスタントをサンドボックスに入れてるよ。そこで、何でも好きなことができるし、危険なものを削除したり変異させたりもできる。Guixを使ってどうやるか書いたよ:https://200ok.ch/posts/2025-05-23_sandboxing_ai_tools:_how_g... それ以来、Bubblewrapを使うように切り替えた:https://github.com/munen/dotfiles/blob/master/bin/bin/bubble...

MCPには確かに欠点があると思う。LLMが既存のAPIエンドポイントに接続できるのに、なぜMCPサーバーが必要なのか分からない。エージェントが「マニュアル」や「プロバイダー」を通じてネイティブエンドポイント(HTTP/CLI/WebSocket)に直接呼び出せる代替プロトコルに取り組み始めたよ。特注のラッパーサーバーを立ち上げる代わりにね:https://github.com/universal-tool-calling-protocol/python-ut... MCPサーバーにも接続できるから、ぜひ見てみて、君の意見を聞きたいな。

LLMが既存のAPIエンドポイントに接続できるとき MCPの主な違いは、エンドポイントの発見が含まれていることだよ。LLMにMCPツールの一般的な場所を教えると、そのツールが提供する機能をすぐに把握できるんだ。そしてツールが更新されると、LLMはすぐにその更新された機能を再学習する。残りの部分は不必要に複雑だと思うし(私の意見では)、普通のHTTP APIで十分だと思う。これまで出会ったMCPサーバーは実際にそういうことをしていて、さまざまなSSE機能を使っている人は見たことがない。MCP v.01(現行)は、正しい方向への一歩(機能の発見)であり、簡単な部分(APIの構造自体)でのぎこちない誤りでもある。

なんでMCPサーバーが必要なのか分からない。LLMが既存のAPIエンドポイントに「ただ接続」できるじゃん。 LLMはAPIコールのための入力パラメータを生成できるけど、呼び出しコードを実装する必要があるんだよね。LLMに提供したいAPIごとに呼び出しコードを実装するのは、最低でもめんどくさいし、エラーが出やすい。MCPは一度書けば済む、一貫した呼び出し実装を提供してくれるんだ。

あなたが作ってるもの、すごく理解できるよ。MCPがよく使う通信の間接的な部分がちょっと気になるし、OpenAPI仕様のようなところでの労力の重複も気になるね。このリポジトリを注目しておくつもりだし、いつか試してみたいな(ただ、TypeScript版もあればいいのに)。

MCPサーバーを書き始めた最初の数日で、APIをバインドするもの(DataBento、Buttplug.io)を作ったんだ。それが目的だと思ってた。私の即座の気づきは、1) 自動バインダー(例えばOpenAPI)か、UTCPのようなより良いバインディングシステムが必要だということ、2) システムやAPIのために安全なサンドボックスが必要だ(UAT環境のような)。MCPサーバーやツールを作り続けて、(1)が誤解だったことに気づいた。ほとんどのAPIはコンピュータのために作られていなくて、人間が他の人間と自分のコードをつなげるために作られているんだ。説明するのは難しいけど、エルゴノミクス的なことなんだ。データベースへのAPIはページングやフィルタリングのようなものがあるかもしれない。デザインはURLに収める必要があって、物事を簡素化したり隠したりしたい。LLMはそんなの気にしない。私の洞察はこの記事と似てる。LLMはデータセットへの可愛いAPIなんて必要ない。彼らはコードを書くことができるから、APIを与える必要はなくて、SQLエンドポイント(私の焦点)、Pythonの仮想環境、またはbashプロンプトを与えればいい。そうすれば、UTCPマニュアルのように、ユーザーとLLMがツールの説明やコードヘルパー(SQL、ビュー、ストアドプロシージャ)を開発して、必要なことをより上手くできるようになる。メインのツール説明があって、ユーザー特有の補足もあるかもしれない。だから、私はDuckDBを使ってデータをロードしてロックダウンし、DBテーブルをCSVで返す単一のSQLエンドポイントを提供する。そして、LLMと一緒にエージェントループでツールの説明やヘルパーを作っていく。だから、あなたたちがやっていることはクールだと思うけど、力はAPI接続そのものにはなくて、LLMがそれをどう使うかにあるんだ。でも、そのエージェントアシスト部分を製品に組み込むことができるし、誰かがそれを取り巻く何かを作ることもできるよ。

REST APIがあるのに、なんでGraphQLが必要なの?両方とも目的は違うけど、同じことを実現できるんだよね。

数週間前、実際にMCPサーバーの開発を始めたんだ。これは、LLMが安全なサンドボックスC#ランタイム内でJavaScriptを生成・実行できるように設計されていて、Jintがインタープリターとして使われてる。 https://github.com/CharlieDigital/runjs これでLLMは必要なコードを安全に生成・実行できるんだ。ステートメント数、メモリ制限、ランタイム制限に縛られてるけどね。内蔵のシークレットマネージャAPIもあって(生成されたコードがリモートAPIを使えるように)、HTTPフェッチのアナログやJSON処理用のJSONPath、HTTPリクエストのレジリエンシーのためのPollyもあるよ。

君の玩具を批判するつもりはないけど、開発者を嫌う言語を使わせる予測モデルを作るのは本当に運任せな結果になると思うよ。

MCPの約束は「あなたのモデルを世界とつなげる」ってことなんだけど、私の経験では実際はその逆だと思う。LLMにツールのセットを与えると、記事のPlaywrightのケースで言えば30個、基本的にできることを制限しちゃうんだ。この意味では、MCPはLLMのためのガードレールやサンドボックスって感じで、スーパーパワーではない(これらのStripeコマンドの中から選ばなきゃいけない!)。これは、あなたの「エージェント」が特定のツールのサブセットを持つことを望む場合には良いけど、LLMをタスクのためのコンパニオンやペアプログラマーとして使う場合にはあまり良くない。出力が本当に無限であることを望むからね。 [0] https://modelcontextprotocol.io/docs/getting-started/intro [1] こういう場合はMCPを使わない方がいいかも。代わりに、1つのコンテキスト内でツールを明示的に定義した方がいいよ。

それはガードレールじゃなくて、ガイダンスだよ。子供やインターンに「ここにあるものは全部使って、好きにやって」って教えるわけじゃない。フレームワークやプログラミング言語、あるいは一般的な方向性を与えるんだ。

人気のコーディングエージェントを使っているなら、彼らはbashでコマンドを実行できるから、ほぼ無限のツールにアクセスできるんだ。私自身が仕事をするために使っているツールにアクセスできるってこと。以前は自分でやっていたLinuxラップトップのトラブルシューティングにも使ってるけど、今は面倒でやりたくない。これが私が出会った最も共感できるAIの瞬間につながったんだ。「これはイライラする」って、Bluetoothヘッドセットを6回連続で動かそうとした後にClaude Codeが思ったことだよ。

MCPに伴うセキュリティ問題を考えると、MCPを「ガードレール/サンドボックス」と呼ぶのは悪いアイデアだと思う。それに、ターミナルで任意のコマンドを実行できるMCPサーバーもあるし、apt installやbrew installも含まれてるよ。 [1] https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/

自分の経験から言うと、MCPはただのすごく構造化されたプロンプトに過ぎないと思う。 エージェントやモデルが使うツールを指示プロンプトで指定できるし、特定のプロジェクトに特に役立つ。Cursorで特定のファイルが変更されたときにトリガーされるワークフローを定義していて、だいたいモデルはしばらくの間、途切れずに動いてくれる。

ちゃんとコンテキストを与えるのが一番いいと思う。 LLMが調べ方を知らない情報(内部システムのステータスやログへのリンクなど)を与えたら、その調査を行うためのツールを渡してあげるといいよ。

自分のコーディングエージェントは、以下の機能にアクセスできるよ: ask> どんなツールがあるの? 以下のツールにアクセスできるよ: 1 code_search: ripgrepを使ってコードベース内のパターンを検索。 2 extract_code: 行範囲に基づいてファイルからコードの一部を抽出。 3 file_operations: ls、tree、find、diff、date、mkdir、create_fileなどのさまざまなファイル操作を実行。 4 find_all_references: ASTインデックスからシンボル(関数、クラスなど)へのすべての参照を見つける。 5 get_definition: ASTインデックスからシンボル(関数、クラスなど)の定義を取得。 6 get_library_docs: 一意のIDを使ってライブラリのドキュメントを取得。 7 rename_symbol: VS Codeを使ってシンボルの名前を変更。 8 resolve_library_id: ライブラリ名を一意のライブラリIDに解決。 MCPや他のエージェントは何のために必要なの?これでほとんどの問題は解決してるんだけど。

こんなに超人的な知能があるのに、「CALL MOM」デモがまだ解決できてないのは変だよね。

いくつかの問題(ドキュメントがない、セキュリティ、発見性、プラットフォーム特有)を解決しようとするMCPサーバーを作ったよ。 ツールを説明するyamlを書いて(lint/format/test/build)、それをMCPのエージェントに公開する感じ。エージェント用のpackage.jsonスクリプトみたいなものだね。これでスピードも上がるし、間違ったコマンドも減るし、人間の承認もいらないし、並行実行もできる。 https://github.com/scosman/hooks_mcp ここにあるインタラクティブなlldbセッションは、深いデバッグにめっちゃクールだよ。セキュリティについては、コンテナが解決策っぽい。今のところ、sketch.devがエージェントをコンテナ化するのに一番好きなやり方かな。

これが最新のGeminiモデル(gemini-2.5-flash-preview-native-audio-dialog)でツールが実装される方法だよ。 LLMはPythonでコードを実行できるツールにアクセスできて、すべてのツールはdefault_apiクラスで利用可能なんだ。

うん、これにはすごく同意するよ。なんでエディターがもっと言語サーバーを活用しないのか理解できない。エージェントがgrepやsed、awkを使ってるのを見るとびっくりするよ。そんなの、エディター自体が効率的なカーソルベースのインターフェースで提供すべきだと思う。ほとんどの言語では、文字列を操作するんじゃなくて、トークンストリームやASTを操作するべきだよね。

codexやclaudeのコードがプロジェクト内の何十ものファイルを手動で読み込むのは変だよね。「使用箇所を探す」ってエディターに簡単に頼める方法がないからなんだろうけど。CLIツールを効率的に使えばトークンの消費はそれほどひどくならないかもしれないけど、モデルはコメントやREADME、メソッドのオーバーロードについて考えるのに余計な労力を使わなきゃいけない。

構造化された出力はパフォーマンスを向上させるから、同意するよ。特に、文脈自由文法のための広範な構造化出力サポートが見たいな。たまにvLLMみたいなのがあるけど、ほとんどのLLMサービスはJSON出力しかサポートしてなくて、これは何もないよりはマシだけど、このケースには全く対応してない。意味解析を伴う出力、スコープに基づいた出力があれば最高だけど、技術的には可能でも、すぐには実現しそうにないね。でも、製品の差別化のチャンスかも。

現在のツールの使い方は非効率的に見えるのには同意するよ。でも、構文木ではなくコードで操作する理由はしっかりあるんだ。* トレーニングセットにははるかに多くのコードがある。* コードはほとんどいつもより簡潔な表現だからね。過去にはASTのエッジ情報を取得するためにグラフニューラルネットワークやトランスフォーマーをトレーニングする研究もあったけど、そのアプローチが先行するLLMを超える可能性があるには、何らかのブレイクスルー(と大量の資金)が必要だと思う。実験的にエージェントがast-grepを使うのは結構うまくいってるみたい。だから、すべてをコードとして表現しつつ、構文を意識した検索置換ツールを使ってる感じだね。

文字列は依存関係のないユニバーサルインターフェースだよ。どんな言語でも、どんな数のファイルでも何でもできる。他の抽象化は達成できることを大幅に制限しちゃう。あと、LLMはASTでトレーニングされてるんじゃなくて、文字列でトレーニングされてるんだ。プログラマーと同じようにね。

ASTは全体の一部に過ぎないよ。重要なのはセマンティクス(つまり、抽象機械が行うアクション)なんだ。コードが助けるのはパターンを特定することで、それがコード生成(defmacroやAPIサービスの生成)に役立つから、主なインターフェースになるんだよ。ASTは実装の詳細に過ぎない。

LSPサーバーと統合するエージェントがいくつかあるけど、オープンコードが思い浮かぶね。ただ、まだgrepやsedを多用する傾向があるけど。

まさにその通りだと思う。数ヶ月前にAIに頼んだタスクが思ったよりも上手くできて驚いたけど、特定のコーディングスタンダードに合わせて変数名を変更するためにコードをリファクタリングさせたら、すごく下手だったのが面白かった。良いジュニア開発者が数日かかるような作業をした後に、リファクタリングで大失敗して、高校1年生レベルの結果だったよ。

LSPが公開しているAPIを見れば、その理由がわかるよ。LSPをエディタの外で使うのはすごく難しいんだ。なぜなら、多くが「ファイルXのY行で、この2つのカラムの間でシンボルがどこで使われているか」だから。

あなたが探しているのはSerenaだよ: https://github.com/oraios/serena

codeactは本当に面白い分野だと思う。https://www.youtube.com/watch?v=J3oJqan2Gv8 で描き始めたJSプラットフォームをさらに広げてみたよ。LLMは初めからたくさんのAPIを知っていて、文脈を通じて新しいものを学ぶのは得意だけど、ツールをいくつか与えると苦労するんだよね。実際、1つのツール定義を有効にするだけでモデルの雰囲気が「劣化」するんだ。eval()をいくつかの便利なライブラリ(例えば、treesitter)と一緒に与えると、うまく使えるだけじゃなく、自分で「ツール」(関数)を作ってトークンを大幅に節約できるようになる。さらに、普通のUIでほとんどのタスクをこなせるから、トークンがストリームされてLLMが結果を解釈するのを待つ必要がない「一時的な」アプリを作ることもできる。今のところ、私のこのプロジェクトは残念ながらプライベートだけど、基盤となるリポジトリをいくつか紹介するね。github.com/go-go-golems/jesus、https://github.com/go-go-golems/go-go-goja。