はじめに#

最近、MCP(Model Context Protocol)が話題です。今回はこいつがナニモノなのかを話していきたいと思います。

さらっと紹介したあとに、実際にサーバーを構築して公開する方法を説明します。 https://github.com/jlowin/fastmcp?tab=readme-ov-file

何が凄いか#

MCPにより、LLMに合わせる形で、各社がAPIを提供するような事が起きています。

これは例えば日本の全市区町村がゴミ出し曜日のMCPを作りさえすれば、LLMはすべての市区町村のゴミ出しの曜日を答えることが出来るようになります。

共通化の流れを作ったことが凄いことなのです。

例えばZapierやIFTTTなど自動化アプリはご存知でしょうか?彼らは各社のAPIを調べ実装し、繋げ自動化ツールを作ってきました。ところが、MCPの登場により、各社が勝手に共通の窓口を作ってくれているため、IFTTTなどなくてもLLMにより自動化ができてしまうどころか、言葉を汲んで自動で様々なことができてしまう、いわゆる完全に上位互換とも呼べるサービスが出来てしまったことになります。

MCPはどうすればいいのか#

MCPの解説を読むと、難しい言葉が踊ります。今回はシンプルに何をすれば良いのかを端的に説明していきます。

サーバーを公開する#

MCPサービスを提供するには、要するにLLMからくる問い合わせに答えるサーバーを用意すればいいだけです。それだけなんです。公開の仕方ですが、Pythonを例にご紹介します。

uvコマンド(pip, rye のようなもの)で、fastmcpをインストールします。

uv add fastmcp

続いて、サーバーを起動します。

# server.py
from fastmcp import FastMCP

mcp = FastMCP("Demo 🚀")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

if __name__ == "__main__":
    # mcp.run() #stdioの場合
    mcp.run(transport="sse", host="127.0.0.1", port=8000)

これで終わりです。mcp.toolというデコレーターでくくり関数を定義すればいいだけです。

走らせるにはpython main.pyを叩くだけです。

toolというのは、MCPサーバー側で使うツールとして定義することを意味します。MCPではこうしたメソッドをtoolという名称で表現しているため,mcp.toolと言われています。その他にresource, promptなどありますが、とりあえずはtoolを抑えておけばOKです。 https://gofastmcp.com/servers/tools

LLMはどうやって必要な関数を見つけるのか#

ポイントはdocstringと型の明記にあります。docstringでadd two numbersと書いていますが、ここに書いておくことで、開発者が書いた関数名とdocstringが、LLMが参照するツール名と説明として自動的に利用されます。詳しい説明はここを参照してください。

型情報も非常に重要で、LLMがどのようなデータを渡すべきかを理解する上で不可欠であり、同時にMCPサーバー側でのバリデーションにも使われます。

これだけでは足りない場合もあるかもしれません。その際にはLLMによりヒントを与える方法としてAnnotatedとFieldを使うことで、LLMにヒントを与えることが可能になります。

次がAnnotationの例で、process_image関数を見てみましょう。

@mcp.tool()
def process_image(
    image_url: Annotated[str, Field(description="URL of the image to process")],
    resize: Annotated[bool, Field(description="Whether to resize the image")] = False,
    width: Annotated[int, Field(description="Target width in pixels", ge=1, le=2000)] = 800,
    format: Annotated[Literal["jpeg", "png", "webp"],
    Field(description="Output image format")] = "jpeg"
) -> dict:
    ...

関数名、docstring、型アノテーション、Field の description といった開発者による定義が、LLMから見たツールの姿や使い方を直接的に形作ることができるのです。

なお、LLMがツールを利用するためには、明確で固定的なインターフェース(パラメータスキーマ)が必要であり、可変長引数ではそれが生成できないことには注意が必要です。

さいごに#

今回はサーバーの構築方法について説明しました。何やら難しいと思っていたと思うのですが意外と簡単で拍子抜けたと思います。

実は細かい話、例えばMCPのバージョンがVersion1からVersion2に変わったなど難しい話はあるのですがほかサイトに譲ります。

今回はサーバーでどのように構築すれば良いのか非常に簡単に説明しましたが、次回で、このサーバーや、他のサーバーへアクセスするにはどうすれば良いのかご紹介します。

参考#

https://gofastmcp.com/deployment/running-server