MCPサーバー構築入門ならSDKのREADMEがおすすめ

## 前回までのあらすじ
https://qiita.com/kaisumi/items/bbcb771d8589c2d526ab

前回はなんだか微妙な終わり方をしたので、MCPサーバーを今日は確実に構築したい。
改めてBuilding MCP with LLMsに沿ってやってみたけど、ライブラリの依存関係やimportでループに陥るので、LLMに作ってもらうのは一旦諦める。

MCP公式の手動チュートリアルは以下

https://modelcontextprotocol.io/quickstart/server

だけど、Python SDKのREADMEが一番シンプルでMCPの大枠を掴みやすかったのでお勧め。

https://github.com/modelcontextprotocol/python-sdk

↑のQuickstartに沿って実装し、MCP公式のInspector↓で動作確認する。

https://github.com/modelcontextprotocol/inspector

## 動作確認
Python SDKのREADMEよりQuickstartのコード：
>```py
># server.py
>from mcp.server.fastmcp import FastMCP
>
># Create an MCP server
>mcp = FastMCP("Demo")
>
>
># Add an addition tool
>@mcp.tool()
>def add(a: int, b: int) -> int:
>    """Add two numbers"""
>    return a + b
>
>
># Add a dynamic greeting resource
>@mcp.resource("greeting://{name}")
>def get_greeting(name: str) -> str:
>    """Get a personalized greeting"""
>    return f"Hello, {name}!"
>```

### Resources
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/e3c18fa4-6288-4743-afa5-c775a0fe1485.png)

Inspectorで接続し、`List Resources`と`List Templates`をクリックした後の画面。
- `Resources`タブが選択されている
- `Resources`が空
- `Resource Templates`に`get_greeting`がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/04078366-ce9a-4dc0-a245-317c4e4db227.png)
`get_greeting`を選択すると、nameを入力して機能を利用してみることができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/b84111fa-879a-4319-a4e6-0013b7de9f39.png)


### Tools
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/3da6ddf5-56ef-40bb-8826-5833e2e1e337.png)

Toolsタブに切り替えると、`add`が表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/e1a47644-7200-4e75-9ad7-86cd62ff33d5.png)
こんな感じで機能も使えるようだ。

## 拡張してみる
### Resourcesに表示させる
上の`Resources`タブで`Resources`リストが空だったので、ここに表示させるように拡張したい。

Python SDKのREADMEのResourcesセクションのコードを末尾に追加してみる。
>```py
>@mcp.resource("config://app")
>def get_config() -> str:
>    """Static configuration data"""
>    return "App configuration here"
>
>
>@mcp.resource("users://{user_id}/profile")
>def get_user_profile(user_id: str) -> str:
>    """Dynamic user data"""
>    return f"Profile data for user {user_id}"
>```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/1a8ba50c-4733-40ed-924b-53e8c3104e80.png)

`Resources`欄に`config://app`が、`Resource Templates`欄に`get_user_profile`が追加された。
引数を取るResourceが`Resource Templates`に分類される模様。

### Promptを追加する
Python SDKのREADMEのPromptsセクションのコードを末尾に追加した。
>```py
>@mcp.prompt()
>def review_code(code: str) -> str:
>    return f"Please review this code:\n\n{code}"
>
>
>@mcp.prompt()
>def debug_error(error: str) -> list[base.Message]:
>    return [
>        base.UserMessage("I'm seeing this error:"),
>        base.UserMessage(error),
>        base.AssistantMessage("I'll help debug that. What have you tried so far?"),
>    ]
>```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2559587/857e066d-529f-46d1-964b-f746541eccaf.png)
Promptsタブに`review_code`と`debug_error`が表示され、それぞれ引数を入力してプロンプトを作成することができた。

## まとめ
MCPに関しては、正直情報量の多さに追いつけなかったので、やるべきことをできるだけシンプルにすることを目指した。結果としてMCP機能の全体像を俯瞰することができた。今後はクライアントでMCPサーバーを実際に使用してみたい。