user icon

MCPサーバ開発を試してみた

MCPサーバをPython SDKを使って、作ってみました。

プロジェクトの作成

まずテンプレートからプロジェクト作成します。

uvx create-mcp-server

プロジェクト名等を聞かれるので、適当に入力します。プロジェクト作成後、指示に従って以下のコマンドを実行します。

cd <プロジェクト名>
uv sync --dev --all-extras

テンプレートプロジェクトの考察

作成されたファイル「src/test_notes/server.py」を見てみると、以下のデコレータを持つ関数があります。

  • @server.list_resources()
  • @server.read_resource()
  • @server.list_prompts()
  • @server.get_prompt()
  • @server.list_tools()
  • @server.call_tool()

resourceprompttoolの一覧を配列で返すのと、項目の実行結果を返す関数のようです。

このMCPサーバをClaudeデスクトップClineClaudeコードの3つのMCPホストで使ってみました。
ClaudeデスクトップClineはJSONファイルによって設定します。Claudeコードは、以下のような感じで設定します。

claude mcp add-json test-notes '{"command":"uv","args":["--directory","/path/to/test-notes","run","test-notes"]}'

MCPホスト起動時にMCPサーバはバックグラウンドプロセスとして起動します。なおMCPホスト終了時にMCPサーバのプロセスは終了しません。その後にMCPホストを起動すると、二重にMCPサーバのプロセスが起動しています。
MCPサーバ起動時にtool等の一覧取得してるようです。

このMCPサーバはプロパティに名前と内容を持つノートを追加する機能です。
toolは、3つのMCPホストで利用できましたが、resourcepromptは、Claudeデスクトップでしか利用できませんでした。ドキュメントを見てみると、ClinepromptがNGでresourceはOK、ClaudeコードpromptがOKでresourceはNGと書いてあるので、多分やり方が分からなかっただけだと思います。

なお、ドキュメントのクイックスタートでは、上記の実装方法とはちょっと違っていて、デコレータを作るクラスがServerではなく、FastMCPになっています。
FastMCPを使うと、Pythonの型ヒントとdocstringを使用してツール定義を自動生成するので、一覧を返す関数を作る必要がなくなります。関数のコメントから一覧を生成し返してくれます。
ただ、実際にFastMCPを使ってMCPサーバを作ってみましたが、ClaudeデスクトップClaudeコードでは正常動作しましたが、ClineではMCPサーバ接続時にListToolsRequestが失敗し、うまくいきませんでした。ただ調べてみるとissueに上がっているので、そのうちClineでもできるようになると思います。

SSH接続するMCPサーバを作ってみる

Clineを使って作っていきます。LLMはclaude-sonnet-3.7です。

src/ssh_connect/server.pyはMCPサーバのサンプルコードです。
これを参考に、MCPでSSH接続できるコードを作って。
ホスト名等の設定は、MCP設定のenvで設定するようにして。

これだけで、ほぼ完成しました。
以下のtoolを作成してくれました。

  • connect
  • disconnect
  • execute
  • upload
  • download
  • list_files

paramikoを使ってSSHしています。頼んでもないのにsftpでファイルアップロード・ダウンロード・ファイル一覧のツールも作ってくれました。

ただ実際にClineで実行してみると、ClineはこのMCPの使い方が分からず、使えませんでした。
以下のプロンプトで修正依頼しました。

Clineで実行したら、以下のように使い方が分からないと言われた。

The user wants to establish an SSH connection. Based on the environment details, I can see that we're in a directory that appears to be an SSH connection tool for MCP (Model Context Protocol). The directory structure shows files like server.py in the src/ssh_connect/ directory and an example file ssh_example.py in the examples/ directory.
I should first understand what this SSH connection tool does and how to use it. Let me examine some of the key files to understand how to proceed.
First, let's look at the README.md file to get an overview of the project

毎回、README.mdを見ることなく、使えるようにしたい。

その結果、ツール一覧を返す関数を修正し、各ツールにdescriptionを追加してくれました。
追加した各ツールのdescriptionは、VSCのClineのMCP Serversに表示されていました。


これでClineはMCPサーバ起動してListToolsRequestすれば、このMCPサーバの使い方がわかるようになりました。
以下、実行結果です。

User:SSH接続して。設定は環境変数から取得して。
Assistant: Successfully connected to the SSH server at 192.168.1.35 on port 22 with username lanuser. The connection is now established and ready for use.
Is there anything specific you'd like me to do with this SSH connection? For example, I can:

Execute commands on the remote system
List files in a directory
Upload or download files
Take notes about what we find

User:実行してるプロセス一覧を表示して。
Assistant:現在のシステムで実行されているプロセスの一覧を表示しました。主なプロセスは以下のようになっています:

システム関連プロセス:

/sbin/init(PID 1)- システムの最初のプロセス
systemd-journald、systemd-udevd、systemd-resolved などのシステムサービス
カーネルスレッド([kthreadd]、[kworker]など)


ネットワーク関連:

NetworkManager(PID 369)
wpa_supplicant(PID 429)- 無線ネットワーク
sshd(PID 1425)- SSHサーバー


グラフィック関連:

Xorg(PID 1829)
gdm3(PID 1279)- GNOMEディスプレイマネージャ
gnome-shell(PID 2715)


ハードウェア関連:

nvargus-daemon(PID 1235)
nvfancontrol(PID 1038)- ファン制御
bluetoothd(PID 1034)- Bluetooth管理


コンテナ関連:

dockerd(PID 1617)
containerd(PID 1261)


ユーザーセッション:

現在のSSHセッション(PID 3458、3502)
bash(PID 3352)

システムは複数のユーザー(root、gdm、lanuser など)でプロセスを実行しており、GNOME環境が稼働していることが分かります。また、Docker関連のプロセスも実行されているため、コンテナ技術が使用可能な状態です。

作成したコードはこれです。
なぜかテストコード、インストールのシェルやHTMLのガイドまで作ってくれました。

MCPクライアントを作ってみる

これもClineで作ります。

@https://modelcontextprotocol.io/quickstart/client 
上記を参考にpythonでMCPサーバに接続できるチャットボットを作って。

クライアントだけでなく、テスト用のMCPサーバを作成してくれましたが、
テスト用のMCPサーバが正常動作しなかったので、以下のプロンプトで修正をお願いしました。

@https://modelcontextprotocol.io/quickstart/server
のMCPサーバの作り方を見ると、test_server.pyとだいぶ違うようです。
FastMCPを使って作り直して。

テスト用のMCPサーバで動作確認後、先程作ったSSH接続のMCPサーバで確認します。

uv run client.py - --directory ~src/samples/test-mcp-server/ssh-connect run ssh-connect --env SSH_HOST=192.168.1.35 --env SSH_PORT=22 --env SSH_USERNAME=lanuser --env SSH_PASSWORD=****

結果、ほぼうまくいきましたが、時々何故か以下のようなエラーが出ます。

'ToolUseBlock' object has no attribute 'text'

機会があれば、MCPクライアントをSlackで作ってみたいと思います。

Facebooktwitterlinkedintumblrmail

タグ: