手を動かして学ぶ！MCPステップバイステップ実践ガイド for Beginners - Vol.3 サーバーに「お願い」！requestsで作るMCPクライアントの基本

## 1. はじめに: サーバーの次は「クライアント」の出番です！

皆さん、こんにちは！「手を動かして学ぶ！MCPステップバイステップ実践ガイド for Beginners」へようこそ！シリーズ第3回目となりました。

前回の[Vol.2](https://qiita.com/QueryPie/items/19e87985394db096562a)では、PythonのFlaskライブラリを使って、皆さんの手で初めての「MCPサーバー」の原型を作成し、実際に起動するところまでを体験しましたね。```http://127.0.0.1:5000/``` にブラウザでアクセスすると、自分で作ったサーバーから「Hello, MCP Server from Flask!」というメッセージが返ってくるのを確認できたでしょうか？ あの瞬間は、プログラミングの面白さを感じられる第一歩だったのではないかと思います。

さて、サーバー、つまり「お願いを待つ窓口」が準備できたということは、次は何が必要でしょう？ そうです、その窓口に「お願いをする人」が必要ですよね！

今回のVol.3では、その **「クライアント」** 、つまりサーバーにリクエスト（お願い）を送る側のプログラムをPythonで作っていきます。前回作った私たちの小さなMCPサーバーに対して、今度はPythonプログラムから「こんにちは！」とアクセスし、サーバーからの応答を受け取ってみましょう。

サーバーとクライアント、この二つが揃って初めて「通信」というものが成り立ちます。お店の窓口だけがあっても、お客さんが来なければ商売は始まりませんよね。今回は、その「お客さん」の役目を果たすプログラムを作ることで、MCPの基本的なやり取りの全体像を掴んでいきます。

それでは、今回も一緒に、楽しく手を動かしながら学んでいきましょう！

## 2. 「クライアント」ってどんな役割？ ～サーバーに「お願い」する専門家～

まずは、[Vol.2](https://qiita.com/QueryPie/items/19e87985394db096562a)でも少し触れましたが、「クライアント」という言葉について、もう少し詳しく見ていきましょう。

#### クライアントとサーバー、再びお店とお客さんで例えると

コンピューターネットワークの世界では、役割に応じてプログラムやコンピューターを呼び分けることがあります。

- **サーバー (Server):** サービスや情報を提供する側。「お店」や「窓口」のような存在。
- **クライアント (Client):** サーバーに対してサービスや情報を要求する側。「お客さん」や「利用者」のような存在。

この関係は、MCPの世界でも全く同じです。

#### MCPクライアントのお仕事: 情報収集と操作依頼のエキスパート

MCP（Model Context Protocol）は、様々な「モデル（モノやコト）」とその「コンテキスト（状況）」を扱うための共通言語でしたね。

このMCPの世界において、**MCPクライアント** は、MCPサーバーに対して以下のような「お願い」をする専門家です。

- **情報収集:** 「あのモデルの現在の状態（コンテキスト）を教えてください」とサーバーに問い合わせる。
    - 例：スマートホームの温度センサー（モデル）を管理するMCPサーバーに対して、クライアントアプリが「現在の室温は何度ですか？」と尋ねる。
- **操作依頼:** 「このモデルの設定をこのように変更してください」とサーバーに指示を出す。
    - 例：エアコン（モデル）を管理するMCPサーバーに対して、クライアントアプリが「設定温度を24度にしてください」とお願いする。

MCPクライアントは、人間が直接画面を操作するアプリケーション（例えば、スマートフォンのアプリやパソコンの管理ツールなど）であることもありますし、あるいは、別のコンピューターシステムの一部として、裏側で自動的にMCPサーバーと情報をやり取りするプログラムであることもあります。

#### なぜプログラムでクライアントを作るの？ブラウザだけじゃダメ？

前回の[Vol.2](https://qiita.com/QueryPie/items/19e87985394db096562a)では、私たちが作ったFlaskサーバーにアクセスするために、ウェブブラウザを使いました。ウェブブラウザも、ウェブサーバーに対してページ情報をリクエストする立派な「クライアント」の一種です。

では、なぜわざわざPythonでクライアントプログラムを作る必要があるのでしょうか？

- **自動化と柔軟性:** ブラウザは人間が操作することが前提ですが、プログラムで作るクライアントなら、定期的にサーバーに情報を問い合わせたり、特定の条件が満たされたら自動的にサーバーに操作を依頼したり、といった処理を自動化できます。また、リクエストの内容をより細かく、柔軟に制御することも可能です。
- **データの活用:** サーバーから受け取った応答（例えば、センサーの測定値など）を、プログラムの中でさらに加工したり、分析したり、別のシステムに連携したりすることができます。ブラウザでただ表示するだけではできない、高度なデータ活用が可能になります。
- **システム間連携の実現:** MCPの大きな目的の一つは、異なるシステムやデバイスがスムーズに連携することです。そのためには、システム同士がプログラムを通じて自動的に情報をやり取りする必要があります。まさに、プログラムで作るクライアントがその役割を担うのです。

もちろん、手軽にサーバーの動作を確認するだけならブラウザも便利ですが、MCPの本格的な利用シーンを考えると、プログラムによるクライアント作成は必須のスキルと言えるでしょう。今回は、その第一歩を踏み出します。

## 3. requestsライブラリを使ってみよう！ ～PythonでHTTP通信を簡単にする魔法の杖～

さて、PythonでMCPクライアントプログラムを作るにあたり、サーバーと実際に「会話」するための道具が必要です。その会話のルールとなるのが **「HTTP（HyperText Transfer Protocol）」であり、その会話をPythonで簡単に行うための魔法の杖が「requests」** ライブラリです。

#### HTTP通信って何だろう？ウェブ世界の共通言語

皆さんが普段インターネットでウェブサイトを見るとき、ブラウザとウェブサーバーの間では、目に見えない形で情報のやり取りが行われています。この情報のやり取りに使われている最も基本的な「お約束事（プロトコル）」がHTTPです。

HTTPは、クライアントがサーバーに「こんな情報が欲しいな（リクエスト）」と伝え、サーバーがそれに対して「はい、どうぞ（レスポンス）」と情報を返す、という一連の手順やメッセージの形式を定めています。

MCPも、多くの場合、このHTTPという土台の上で情報をやり取りするように設計されています。つまり、MCPクライアントがMCPサーバーに「お願い」をするときも、基本的にはHTTPのルールに従って通信を行うのです。

HTTPのリクエストには、いくつかの種類（HTTPメソッドと呼ばれます）があります。代表的なものとしては、

- **GET（ゲット）:** サーバーから情報を取得したいときに使う。「このページをください」「このデータをください」というイメージ。
- **POST（ポスト）:** サーバーに新しい情報を登録したいときに使う。「この情報を登録してください」というイメージ。手紙をポストに投函するのに似ていますね。
- **PUT（プット）:** サーバーの既存の情報を更新したいときに使う。「この情報を新しい内容に置き換えてください」というイメージ。
- **DELETE（デリート）:** サーバーの情報を削除したいときに使う。「この情報を削除してください」というイメージ。

今回のVol.3では、まず最も基本的なGETメソッドを使って、サーバーから情報を取得するクライアントを作ります。

#### requestsライブラリとは？人間にも優しいHTTPの道具箱

Pythonには、標準でHTTP通信を行うためのライブラリ（例えば ```urllib.request```）も用意されています。しかし、これらの標準ライブラリは、時として少し記述が複雑だったり、直感的でなかったりすることがあります。

そこで登場するのが、requestsライブラリです。requestsは、PythonでHTTP通信を驚くほど簡単かつ直感的に行えるように設計された、非常に人気のあるサードパーティライブラリ（Python本体には含まれていないが、多くの開発者に愛用されている外部の部品）です。

そのキャッチフレーズは「HTTP for Humans（人間のためのHTTP）」。まさにその名の通り、人間が読んで理解しやすく、そして書きやすいように作られています。複雑な設定や手順を気にすることなく、数行のコードでサーバーにリクエストを送り、レスポンスを受け取ることができてしまいます。

このシリーズでも、この```requests```ライブラリを全面的に活用していきます。

#### requestsライブラリをインストールしよう！新しい魔法を覚える

それでは、この便利な```requests```ライブラリを、私たちの開発環境にインストールしましょう。前回Flaskをインストールした時と同じ手順です。

1. **仮想環境の有効化（おさらい）**
[Vol.1](https://qiita.com/QueryPie/items/0004908e90a8796c3da1)、[Vol.2](https://qiita.com/QueryPie/items/19e87985394db096562a)と同様に、コマンドプロンプト（Windows）またはターミナル（macOS/Linux）を開き、プロジェクトフォルダ（例：```mcp_beginner_guide```）に移動し、仮想環境（例：```mcp_env```）を有効化してください。行頭に (```mcp_env```) と表示されていることを確認しましょう。
1. **requestsのインストール**
仮想環境が有効になっている状態で、以下のコマンドを実行します。

```
pip install requests
```

```pip```さんが、インターネット上から```requests```ライブラリを探してきて、あなたの仮想環境にインストールしてくれます。

特にエラーメッセージが出ず、最後に「Successfully installed requests-x.x.x ...」（x.x.xはバージョン番号）のようなメッセージが表示されれば、インストール成功です！

これで、HTTP通信という新しい魔法を操るための杖、```requests```ライブラリを手に入れました！

## 4. PythonとrequestsでMCPクライアントを作ってみよう！ ～サーバーに最初のお願い～

さあ、道具も揃ったところで、いよいよPythonでMCPクライアントのプログラムを書き、前回作ったMCPサーバーに「最初のお願い」をしてみましょう！

#### 準備はOK？サーバーを起動しておこう！

クライアントプログラムを実行する前に、お願いの相手であるMCPサーバーが起動している必要があります。もし、前回のVol.2で作ったFlaskサーバー（```app.py```）がまだ起動していなければ、先にそちらを起動しておきましょう。

ここで一つポイントです。サーバープログラムは、一度起動すると、私たちが停止するまでリクエストを待ち続けるために、ターミナルを一つ占有してしまいます。クライアントプログラムもターミナルから実行するので、**ターミナルが2つ必要** になります。

多くのターミナルソフトやVS Codeのターミナル機能には、ウィンドウを分割したり、新しいタブを開いたりする機能があります。

- **方法1：ターミナルを2つ開く**
    1. 一つ目のターミナルで、```mcp_beginner_guide``` フォルダに移動し、仮想環境を有効化（```mcp_env\Scripts\activate``` または ```source mcp_env/bin/activate```）した後、```python app.py``` (または ```python3 app.py```) を実行してFlaskサーバーを起動します。
    1. もう一つ新しいターミナルウィンドウを開き、同様に ```mcp_beginner_guide``` フォルダに移動し、仮想環境を有効化します。こちらのターミナルで、後ほどクライアントプログラムを実行します。
- **方法2：VS Codeのターミナル分割機能を使う (おすすめ)**
    1. VS Codeで ```mcp_beginner_guide``` フォルダを開きます。
    1. VS Codeのターミナルを開きます（メニュー「ターミナル」 > 「新しいターミナル」）。
    1. ターミナル内で仮想環境を有効化します。
    1. このターミナルで ```python app.py``` (または ```python3 app.py```) を実行してFlaskサーバーを起動します。
    1. ターミナルパネルの右上あたりにある「＋」アイコンの隣の「分割」アイコン（四角が左右に分かれたようなアイコン）をクリックすると、ターミナルが左右（または上下）に分割されます。
    1. 新しくできた方のターミナルで、再度仮想環境を有効化します（既に有効になっている場合もあります）。こちらのターミナルでクライアントプログラムを実行します。

どちらの方法でも構いませんので、サーバーが元気にリクエストを待ち受けている状態にしておいてください（```Running on http://127.0.0.1:5000/``` と表示されている状態です）。

#### 新しいファイルを作って、クライアントのコードを書こう

サーバーの準備ができたら、次にクライアントプログラムのコードを書くための新しいファイルを作成します。

VS Codeのファイルエクスプローラーで ```mcp_beginner_guide``` フォルダを右クリックし、「新しいファイル」を選択して、ファイル名を ```client.py``` としましょう。

この ```client.py``` ファイルに、以下のPythonコードを記述してください。

```Python
import requests

# アクセス先のURL（前回作成したFlaskサーバーのアドレス）
url = "http://127.0.0.1:5000/"

print(f"これからサーバー ({url}) にアクセスします...")

# サーバーにGETリクエストを送信し、応答を受け取る
response = requests.get(url)

print("サーバーからの応答を受け取りました！")

# 応答のステータスコードを表示
print(f"ステータスコード: {response.status_code}")

# 応答の本文（サーバーが返したメッセージ）を表示
print(f"応答メッセージ: {response.text}")
```

これが、私たちの最初のMCPクライアントプログラムです。前回作ったサーバーにアクセスし、その応答を表示するという、シンプルな内容です。

#### コードの解説：サーバーへの「お願い」の手紙を解読する

それでは、このクライアントのコードが何をしているのか、詳しく見ていきましょう。

- ```import requests```
これは、先ほどインストールした```requests```ライブラリを使えるようにするための宣言です。「これから```requests```さんの魔法を使いますよー」とPythonに伝えています。
- ```url = "http://127.0.0.1:5000/"```
変数 ```url``` に、アクセスしたいサーバーのURL（インターネット上の住所）を文字列として保存しています。これは、前回Flaskサーバーを起動したときに表示された、あの見慣れたアドレスですね。
- ```print(f"これからサーバー ({url}) にアクセスします...")```
プログラムが何をしているか分かりやすくするために、コンソール（ターミナルのこと）にメッセージを表示しています。```f"..."``` という書き方（f-stringと言います）は、文字列の中に ```{url}``` のように変数の値を埋め込むことができるPythonの便利な機能です。
- ```response = requests.get(url)```
ここがクライアントの仕事の核心部分です！```
requests.get(url)``` という命令で、指定した ```url``` に対してHTTPの **GETリクエスト** を送信しています。GETリクエストは、「そのURLにある情報をください」というお願いでしたね。サーバーがこのリクエストを受け取って処理をし、何らかの応答を返してきます。そのサーバーからの応答全体が、```response``` という名前の箱（変数）に格納されます。この ```response``` は、ただの文字列ではなく、サーバーからの応答に関する様々な情報（ステータスコード、メッセージ本体、ヘッダー情報など）が詰まった特別な「オブジェクト」です。レストランで注文したら、料理だけでなく、伝票やお店の情報も一緒に来るようなイメージでしょうか。
- ```print("サーバーからの応答を受け取りました！")```
無事にサーバーから応答が返ってきたことを知らせるメッセージです。
- ```print(f"ステータスコード: {response.status_code}")```
```response``` オブジェクトが持っている情報の一つ、```status_code```（ステータスコード）を表示しています。ステータスコードは、サーバーのリクエスト処理が成功したかどうかを示す3桁の数字です。例えば、200なら「成功」、404なら「見つかりませんでした」といった意味があります（詳しくは後述します）。
- ```print(f"応答メッセージ: {response.text}")```
```response```オブジェクトが持っているもう一つの重要な情報、```text```（テキスト）を表示しています。これは、サーバーが返してきた応答の本文（メッセージ本体）を文字列として取り出したものです。前回作ったサーバーなら、```"Hello, MCP Server from Flask!"``` という文字列がここに入っているはずです。

#### クライアントプログラムを実行！サーバーからの返事は？

さあ、コードの意味も理解できたところで、いよいよこの ```client.py``` を実行してみましょう！

**実行前の確認事項:**

1. Flaskサーバー（```app.py```）が別のターミナルで起動していること。
1. 現在のターミナルで、仮想環境（```mcp_env```）が有効になっていること。
1. 現在のターミナルで、カレントディレクトリ（現在の作業場所）が ```client.py``` ファイルのある ```mcp_beginner_guide``` フォルダになっていること。

準備ができたら、クライアントプログラムを実行するためのターミナルで、以下のコマンドを入力してEnterキーを押します。

```
python client.py
```

(macOSやLinuxで python3 を使っている方は python3 client.py としてください。)

実行すると、ターミナルに次のような表示が出るはずです。

```
これからサーバー (http://127.0.0.1:5000/) にアクセスします...
サーバーからの応答を受け取りました！
ステータスコード: 200
応答メッセージ: Hello, MCP Server from Flask!
```

どうでしょうか？ サーバーからのお返事、ちゃんと受け取れましたか？「ステータスコード: 200」と「応答メッセージ: Hello, MCP Server from Flask!」が表示されていれば、クライアントプログラムは大成功です！

このとき、サーバー側のターミナル（```app.py``` を実行している方）にも、クライアントからのアクセスを示すログ（```GET / HTTP/1.1" 200 -``` のような行）が新たに追加されていることを確認してみてください。サーバーとクライアントが、ちゃんと会話している様子が分かりますね。

## 5. サーバーからの応答（レスポンス）を詳しく見てみよう～サーバーからの「お手紙」の中身～

クライアントプログラムが無事にサーバーからの応答を受け取れることが確認できました。```requests.get(url)``` の結果として得られた ```response``` 変数には、実はサーバーからの「お手紙」のような形で、様々な情報が詰まっています。

この「お手紙」の中身をもう少し詳しく見ていきましょう。

#### レスポンスオブジェクト: サーバーからの情報が詰まった宝箱

```response = requests.get(url)``` で得られる ```response``` は、```requests```ライブラリが提供する特別な「レスポンスオブジェクト」です。このオブジェクトは、サーバーからの応答に関する情報を属性（オブジェクトが持っているデータ）やメソッド（オブジェクトができる操作）という形でたくさん持っています。まるで、情報が詰まった宝箱のようです。

主なものをいくつか紹介します。

#### 応答の「成績表」: HTTPステータスコード (```response.status_code```)

既に出てきましたが、```response.status_code``` は、サーバーがクライアントのリクエストを処理した結果どうだったかを伝える3桁の数字です。まるで、リクエストに対するサーバーの「成績表」のようなものです。

主なステータスコードの意味を覚えておくと、問題が発生したときの原因究明に役立ちます。

- **200番台: 成功 (Success)**
    - ```200 OK```: リクエストは成功し、要求された情報がレスポンスに含まれています。（今回これが出ましたね！）
    - ```201 Created```: リクエストが成功し、新しいリソースが作成されました。（例：POSTリクエストでデータを登録した場合など）
    - ```204 No Content```: リクエストは成功しましたが、返すコンテンツ（本文）はありません。（例：DELETEリクエストで削除が成功した場合など）
- **300番台: リダイレクション (Redirection)**
    - ```301 Moved Permanently```: 要求されたリソースの場所が恒久的に移動しました。新しいURLが示されます。
    - ```302 Found``` (または ```307 Temporary Redirect```): 一時的に別の場所にリダイレクトします。
- **400番台: クライアントエラー (Client Error)**
    - ```400 Bad Request```: リクエストの形式が正しくないなど、クライアント側の問題で処理できませんでした。
    - ```401 Unauthorized```: 認証が必要です。アクセス権がありません。（例：ログインが必要なページにアクセスしようとした場合）
    - ```403 Forbidden```: アクセスは禁止されています。認証は通ったが、権限がない場合など。
    - ```404 Not Found```: 要求されたリソース（URL）が見つかりませんでした。（一番よく見るエラーかもしれません）
- **500番台: サーバーエラー (Server Error)**
    - ```500 Internal Server Error```: サーバー内部で予期しないエラーが発生し、リクエストを処理できませんでした。サーバー側のプログラムに問題がある可能性があります。
    - ```502 Bad Gateway```: ゲートウェイやプロキシとして動作しているサーバーが、上流サーバーから不正な応答を受け取りました。
    - ```503 Service Unavailable```: サーバーが一時的に過負荷であったり、メンテナンス中であったりして、リクエストを処理できません。

クライアントプログラムでは、このステータスコードをチェックして、処理が成功したかどうかを判断し、その後の動作を分岐させることが一般的です。

#### お手紙の「本文」: ```response.text```

```response.text``` は、サーバーが返してきた応答の本文（ボディとも言います）を、文字列として取得するものです。

今回は、サーバーが ```"Hello, MCP Server from Flask!"``` という単純な文字列を返したので、response.text にもその文字列が入っていました。もしサーバーがHTMLページを返せばHTMLのコードが、後々扱うJSONデータを返せばJSON形式の文字列がここに入ってきます。

#### お手紙の「付箋」: ```response.headers```

```response.headers``` は、サーバーが返してきた **HTTPヘッダー情報** をPythonの辞書（キーと値のペアでデータを格納するもの）のような形式で取得するものです。

HTTPヘッダーは、応答本文（```response.text```）に付随するメタデータ（付加情報）で、以下のような情報が含まれていることがあります。

- ```Content-Type```: 応答本文の種類（例：```text/html``` ならHTML文書、```application/json``` ならJSONデータ、```image/jpeg``` ならJPEG画像など）。
- ```Content-Length```: 応答本文のサイズ（バイト単位）。
- ```Server```: サーバーソフトウェアの種類とバージョン（例：```Werkzeug/2.0.1 Python/3.9.7``` のように、Flaskの開発サーバーの情報が見えることも）。
- ```Date```: サーバーが応答を生成した日時。

これらのヘッダー情報は、クライアントが応答を正しく解釈したり、キャッシュ（一度取得した情報を一時的に保存しておく仕組み）を制御したりするのに使われます。

試しに、```client.py``` を少し変更して、これらの情報も表示してみましょう。変更した後、必ずファイルを保存してから```client.py```を実行してください。

```Python
import requests

url = "http://127.0.0.1:5000/"

print(f"これからサーバー ({url}) にアクセスします...")
response = requests.get(url)
print("サーバーからの応答を受け取りました！\n") # \n を追加して改行

print(f"--- 応答詳細 ---")
print(f"ステータスコード: {response.status_code}")
print(f"応答ヘッダー:")
for key, value in response.headers.items(): # ヘッダー情報を一つずつ表示
    print(f"  {key}: {value}")
print(f"応答本文 (テキスト): {response.text}")
print(f"----------------")
```

この変更版 ```client.py``` を実行すると、サーバーから返ってきたヘッダー情報もずらっと表示されるはずです。```Content-Type``` が ```text/html; charset=utf-8``` のようになっていることや、```Content-Length```（本文の文字数とほぼ一致するはず）などが確認できるでしょう。

#### もしもの時のために: 簡単なエラーキャッチ (try-except)

ネットワーク通信には、予期せぬエラーがつきものです。例えば、

- アクセスしようとしたサーバーが起動していない。
- ネットワークが繋がっていない。
- URLのタイプミス。

このような場合、```requests.get(url)``` のような命令は、エラー（専門用語では **例外 (Exception)** と言います）を発生させてプログラムが途中で停止してしまうことがあります。

プログラムをより頑健（エラーに強く）にするためには、このような例外が発生する可能性のある処理を ```try...except``` ブロックで囲んで、エラーを適切に処理（キャッチ）することが推奨されます。

本格的なエラー処理については後の回（Vol.7）で詳しく学びますが、ここでは最も基本的な形だけ紹介しておきます。例えば、サーバーに接続できなかった場合に発生する可能性のある ```requests.exceptions.ConnectionError``` をキャッチするには、以下のように書けます。

```Python
import requests

url = "http://127.0.0.1:5000/" # わざと間違ったURLにしてみるのもアリ 例: "http://localhost:12345/"

print(f"これからサーバー ({url}) にアクセスします...")

try:
    response = requests.get(url, timeout=5) # timeoutを追加してみる (5秒待っても応答がなければエラー)
    print("サーバーからの応答を受け取りました！\n")

    print(f"--- 応答詳細 ---")
    print(f"ステータスコード: {response.status_code}")
    
    # ステータスコードが200番台でなければエラーメッセージを表示することもできる
    if 200 <= response.status_code < 300:
        print("リクエスト成功！")
        print(f"応答ヘッダー:")
        for key, value in response.headers.items():
            print(f"  {key}: {value}")
        print(f"応答本文 (テキスト): {response.text}")
    else:
        print(f"リクエストは成功しましたが、ステータスコードが正常ではありません: {response.status_code}")
        print(f"応答本文 (エラーの可能性あり): {response.text}")

    print(f"----------------")

except requests.exceptions.ConnectionError as e:
    print(f"エラー: サーバー ({url}) に接続できませんでした。")
    print(f"詳細: {e}")
except requests.exceptions.Timeout as e:
    print(f"エラー: サーバー ({url}) からの応答がタイムアウトしました。")
    print(f"詳細: {e}")
except requests.exceptions.RequestException as e: # その他のrequests関連のエラーをキャッチ
    print(f"エラー: リクエスト中に問題が発生しました。")
    print(f"詳細: {e}")
```

このコードでは、```requests.get()``` の処理を ```try:``` の下に置き、もし ```requests.exceptions.ConnectionError```（接続エラー）が発生したら、```except requests.exceptions.ConnectionError as e:``` の下の処理（エラーメッセージの表示）が実行されるようになっています。```timeout=5``` は、5秒待ってもサーバーから応答がなければタイムアウトエラーにする設定です。

試しに、Flaskサーバーを停止した状態でこのクライアントを実行したり、```url``` を存在しないものに変えてみたりすると、```except``` ブロックが動作するのが確認できるはずです。

このようにエラー処理を挟むことで、プログラムが突然クラッシュするのを防ぎ、何が起こったのかをユーザーに優しく伝えることができます。

## 6. まとめと次回予告: ついに繋がった！サーバーとクライアント

今回のVol.3は、盛りだくさんの内容でしたね！一緒に振り返ってみましょう。

- **クライアントの役割:** サーバーにリクエストを送り、サービスや情報を要求する「お願いの専門家」であることを学びました。
- **requestsライブラリ:** PythonでHTTP通信を驚くほど簡単にする「魔法の杖」、```requests```ライブラリをインストールし、その便利さを体験しました。
- **初めてのクライアント作成:** Pythonと```requests```を使って、前回作成したFlaskサーバーにGETリクエストを送信し、応答メッセージとステータスコードを受け取るクライアントプログラムを作成・実行しました。
- **レスポンスの詳細:** サーバーからの応答（レスポンスオブジェクト）には、ステータスコード、本文（テキスト）、ヘッダー情報など、様々な情報が含まれていること、そして簡単なエラーハンドリングの方法について触れました。

ついに、私たちの手で「サーバー」と「クライアント」の両方を作り上げ、プログラム同士がネットワークを通じて「会話」をするという、MCPの最も基本的な形を体験することができました！ この一歩は、皆さんのプログラミング学習において、非常に大きなマイルストーンとなるはずです。

さて、ここまでのやり取りでは、サーバーは常に ```"Hello, MCP Server from Flask!"``` という固定の文字列を返していました。しかし、実際のMCPでは、もっと複雑で構造化されたデータ、例えば「エアコンモデルの現在の設定温度は25度で、運転モードは冷房です」といったような具体的な「モデル」や「コンテキスト」の情報をやり取りする必要があります。

そこで、次回Vol.4のテーマは、**「情報を分かりやすく！JSON形式でMCPデータをやり取りする」** です！

次回は:

- プログラム同士がデータを交換するのによく使われる「JSON（ジェイソン）」というデータ形式とは何か？
- Flaskサーバーから、このJSON形式でデータを返すように変更する方法。
- Pythonクライアントで、サーバーから送られてきたJSONデータを受け取り、内容を理解（パースと言います）する方法。

といった内容で、より実践的なデータのやり取りに挑戦します。いよいよMCPらしい情報交換の始まりです。

今回作った ```app.py``` と ```client.py``` は、次回も土台として使っていきますので、引き続き大切に保存しておいてくださいね。

プログラミングは、一つ一つ新しいことを学び、それを自分の手で試していくことの繰り返しです。今回の「サーバーとクライアントが繋がった！」という感動を胸に、次回のステップも楽しんでいきましょう。

今回も最後までお読みいただき、ありがとうございました！また次回の記事でお会いできるのを楽しみにしています。