OpenAI  Agents SDK でローカルファイルを MCP 経由で使ってみた

# はじめに

OpenAI Agents SDK が 2025 年 3 月 11 日にリリースされました。この記事では、[公式ドキュメント](https://openai.github.io/openai-agents-python/)を参考にして実際に動作を確認しながら、特に重要なポイントや興味深い点を深掘りしていきます。

検証に使用したライブラリのバージョンは openai-agents==0.0.9 です。


# OpenAI Agents SDK の紹介

別のページでご紹介します。

https://qiita.com/osamasao/items/a9f2dffa1f310c5ed8b7#openai-agents-sdk-%E3%81%AE%E7%B4%B9%E4%BB%8B

# 背景と目的

AI エージェント界隈では MCP が大流行です。(2025年4月現在)

OpenAI Agents SDK を通して MCP を試して、動作を理解したいと思います。


# 方法

公式サンプルを修正して、挙動を深堀りしたいと思います。

## 環境構築

MCP Server を起動するため npx コマンドをインストールします。

```bash
$ sudo apt update
$ sudo apt install nodejs npm
```

python パッケージをインストールします。

```bash
pip install openai-agents
```


## コードとファイル


以下のフォルダ構成とします。

```text
src/
├── mcp_filesystem.py       --- MCP を利用するエージェントのコード
└── sample_files            --- filesystem MCP Server がアクセスするディレクトリ
    ├── favorite_books.txt  --- 好きな書籍の一覧
    ├── favorite_cities.txt --- 好きな都市の一覧(今回は中身なし)
    └── favorite_songs.txt  --- 好きな曲の一覧
```


コードです。MCP サーバーの起動、エージェントの起動と利用を書いています。

```python:src/mcp_filesystem.py 
import asyncio
import os
import shutil

from agents import Agent, Runner, gen_trace_id, trace
from agents.mcp import MCPServer, MCPServerStdio


async def run(mcp_server: MCPServer):
    """エージェントの定義と実行"""
    agent = Agent(
        name="アシスタント",
        instructions="ファイルシステムの読み込むツールを使って、"
        "ファイルの内容に基づいて質問に答えて。",
        mcp_servers=[mcp_server],
    )

    # ファイルの一覧
    message = "ファイルの一覧を取得して。"
    print(f"実行中: {message}")
    result = await Runner.run(starting_agent=agent, input=message)
    print(result.final_output)

    # 書籍についての質問
    message = (
        "ファイルの一覧を取得して、好きな書籍のファイルを見て。"
        "私が最初に挙げている書籍は？"
    )
    print(f"\n\n実行中: {message}")
    result = await Runner.run(starting_agent=agent, input=message)
    print(result.final_output)

    # 理由に関する質問
    message = (
        "ファイルの一覧を取得して、好きな歌のファイルを見て。"
        "私が好きそうな新しい歌をサジェストして。"
    )
    print(f"\n\n実行中: {message}")
    result = await Runner.run(starting_agent=agent, input=message)
    print(result.final_output)


async def main():
    """メイン処理"""
    current_dir = os.path.dirname(os.path.abspath(__file__))
    samples_dir = os.path.join(current_dir, "sample_files")

    async with MCPServerStdio(
        name="MCP ファイルシステムサーバー",
        params={
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                samples_dir,
            ],
        },
    ) as server:
        trace_id = gen_trace_id()
        with trace(workflow_name="MCP ファイルシステム", trace_id=trace_id):
            print(
                "トレース情報: https://platform.openai.com/traces/trace"
                f"?trace_id={trace_id}\n"
            )
            await run(server)


if __name__ == "__main__":
    # npx コマンドのチェック
    if not shutil.which("npx"):
        raise RuntimeError(
            "npx がインストールされていません。`npm install -g npx` "
            "コマンド等でインストールして下さい。"
        )

    asyncio.run(main())
```

コードのポイントです。

- MCP Server
    - [@modelcontextprotocol/server-filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) を実行
        - 指定のディレクトリに対してアクセス許可
    - MCPServer オブジェクトを取得して Agent に渡す
- エージェントの定義
    - コンストラクタ引数の mcp_servers に MCPServer インスタンスを指定
    - ツールの利用とユーザーの指示に従うことを指示
- エージェントの実行
    - ファイル一覧の取得
    - ファイル一覧から「好きな書籍のファイル」を探して「リストの先頭」の記述を抜き出す
    - ファイルの一覧から「好きな歌のファイル」を探して類似する新しい歌をレコメンド


## サンプルファイル

好きな書籍一覧を作ります。以下のプロンプトで Gemini 2.5 Pro に作ってもらいました。

> 日本のデータサイエンティストが好きそうな書籍をリストアップして。好きそうな順番に20個。

```text:cat src/sample_files/favorite_books.txt
1. ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 (斎藤 康毅)
2. データ解析のための統計モデリング入門――一般化線形モデル・階層ベイズモデル・MCMC (久保 拓弥)
3. scikit-learn、Keras、TensorFlowによる実践機械学習 第3版 (Aurélien Géron)
4. 効果検証入門〜正しい比較のための因果推論／計量経済学の基礎 (安井 翔太)
5. 統計的学習の基礎 ―データマイニング・推論・予測― (Trevor Hastie, Robert Tibshirani, Jerome Friedman)
6. パターン認識と機械学習 上・下 (Christopher M. Bishop)
7. 解釈可能な機械学習―ブラックボックスモデルを解明する技術 (Christoph Molnar)
8. Kaggleで勝つデータ分析の技術 (門脇 大輔, 阪田 隆司, 保坂 桂佑, 平松 雄司)
9. データ指向アプリケーションデザイン ―信頼性、スケーラビリティ、メンテナンス性に優れたシステム設計の原理 (Martin Kleppmann)
10. SQLアンチパターン (Bill Karwin)
11. リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Dustin Boswell, Trevor Foucher)
12. 機械学習デザインパターン ―データ準備、モデル構築、MLOpsの実践上の問題と解決策 (Valliappa Lakshmanan, Sara Robinson, Michael Munn)
13. Feature Engineering for Machine Learning ―特徴量エンジニアリング (Alice Zheng, Amanda Casari)
14. ゼロから作るDeep Learning ❷ ―自然言語処理編 (斎藤 康毅)
15. 深層学習 (Ian Goodfellow, Yoshua Bengio, Aaron Courville)
16. BERTによる自然言語処理入門: Transformersを使った実践プログラミング (近江 崇宏)
17. Storytelling with Data: A Data Visualization Guide for Business Professionals (Cole Nussbaumer Knaflic)
18. Rユーザのための RStudio[実践]入門〜tidyverseによるモダンな分析フローの世界 (松村 優哉, 湯谷 啓明, 紀ノ定 保礼, 前田 和寛)
19. イシューからはじめよ―知的生産の「シンプルな本質」 (安宅和人)
20. ベイズ統計の理論と方法 (渡辺 澄夫)
```

好きな曲の一覧を作ります。以下のプロンプトで Gemini 2.5 Pro に作ってもらいました。

> 竹内まりやに代表される日本のシティーポップの代表曲を有名な順番に提示して。 11曲。

推薦してもらう関係で、一番上の曲を除去しました。削除したのは「竹内まりや - Plastic love」でした。



```text:src/sample_files/favorite_songs.txt   
1. 松原みき - 真夜中のドア〜Stay With Me
2. 山下達郎 - RIDE ON TIME
3. 杏里 - CAT'S EYE (キャッツ・アイ)
4. 杏里 - 悲しみがとまらない
5. 山下達郎 - SPARKLE
6. 大貫妙子 - 都会
7. 大貫妙子 - 4:00 A.M.
8. 杉山清貴&オメガトライブ - ふたりの夏物語 NEVER ENDING SUMMER
9. 竹内まりや - September
10. 角松敏生 - After 5 Crash
```

## Filesystem MCP Server とは？

[MCP Server の総本山的なリポジトリ](https://github.com/modelcontextprotocol/servers)で公開されているファイルシステムにアクセスする仕組みです。

https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem

ドキュメントによると、

> ファイルシステム操作用のモデル コンテキスト プロトコル (MCP) を実装する Node.js サーバー。
> ### 特徴
> - ファイルの読み取り/書き込み
> - ディレクトリの作成/一覧表示/削除
> - ファイル/ディレクトリを移動する
> - ファイルを検索
> - ファイルのメタデータを取得する
> 
> 注意: サーバーは、引数で指定されたディレクトリ内でのみ操作を許可します。

とのことです。「ファイルを検索」というのは、search_files Tool で実現しているのですが、ファイル名やディレクトリ名を検索するもので、ファイルの内容は検索してくれません。edit_file Tool がファイルを編集してくれるようです。

# 結果

実行してみます。


```text
$ python src/mcp_filesystem.py
Secure MCP Filesystem Server running on stdio
Allowed directories: [ '/home/masao/work/test-openai-agensts/src/sample_files' ]
トレース情報: https://platform.openai.com/traces/trace?trace_id=trace_0000000000000000000

実行中: ファイルの一覧を取得して。
以下のファイルが見つかりました：

1. favorite_books.txt
2. favorite_cities.txt
3. favorite_songs.txt

どのファイルの内容を見たいですか？


実行中: ファイルの一覧を取得して、好きな書籍のファイルを見て。私が最初に挙げている書籍は？
あなたが最初に挙げている書籍は「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 (斎藤 康毅)」です。


実行中: ファイルの一覧を取得して、好きな歌のファイルを見て。私が好きそうな新しい歌をサジェストして。
あなたの好きな曲のリストには、シティポップや80年代の日本の音楽が多く含まれていますね。ここから新しい曲をサジェストします。

### おすすめの曲
1. **森高千里 - 渡良瀬橋**
2. **南佳孝 - スローなブギにしてくれ (I Want You)**
3. **杉山清貴 & オメガトライブ - サイレンスがいっぱい**
4. **EPO - う・ふ・ふ・ふ**
5. **竹内まりや - プラスティック・ラヴ**

これらの曲も気に入ると思います！ぜひ聴いてみてください。
```

## Trace 情報

OpenAI Platform で Trace を確認します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126852/3a902e43-29e4-4aa5-b352-eb7a690b49d7.png)

エージェントを3解呼び出しているのがわかります。最初はファイル一覧を実行。2回目は read_file でファイルの中身を読んでいます。

最初の List MCP Tools を開くと、Filesystem MCP Server の Tools エントリが見えます。当たり前ですが、[ドキュメント](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem)の通りになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126852/0510947b-2c59-4411-9f7a-a6252dc4211a.png)

曲のサジェストタスクのアウトプット直前のトレース情報です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126852/9cc1f5d2-9abd-4d1d-b2de-51989addf1d4.png)

Function Calling で MCP の機能を利用しているように見えます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126852/ac19469d-bc9c-408e-9108-ad8037d9ba0c.png)


# 考察

今回の検証では、OpenAI Agents SDK と MCP(Model Context Protocol) を利用して、ローカルファイルシステムを操作する AI エージェントを作ってみました。色々と理解が深まるポイントがありました。

1. MCP によるツールの標準化と拡張性
    - MCP Server を利用する側のエージェントは、対象の MCP の細かい使い方を知らなくても良さそうです。
    - MCP Server 側で利用可能な関数(Tool)や使い方をアナウンスしているように感じました。
    - ファイルシステムの管理は一般的な処理なので齟齬は無いのかもしれませんが、複雑な MCP やニッチなものがどのような実装になっているか気になります
        - 例えば状態管理が複雑なツール、リアルタイム性が求められるツール、エラーハンドリング等が気になります
    - Capability Navigation というプロセスで、MCP Server が「自己紹介」しているように見えます
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126852/5ec18e56-ccc0-4d8a-ad65-3e059d709580.png)
        - https://modelcontextprotocol.io/specification/2025-03-26/architecture/index#capability-negotiation から引用



    
2. MCPServerStdio による連携
    - 使い方は MCPServer インスタンスを取得して Agent のコンストラクタに渡すだけです
    - 異なる機能をもった MCP や、複数の MCP を混在させるのも簡単そうです
    - 機能をうまく使いこなせるかは、エージェントの専門性(機能分離というか)やプロンプト、モデルの賢さがものをいいそうです
3. エージェントの自立性と Tool の利用
    - 今回はローカルファイルシステムを利用しましたが、自然言語で適切なファイルを探して読み込んだりしています
4. Filesystem MCP Server の安全性
    - ドキュメントでは安全ですよと書いていますが、普通に脆弱性があるかもしれません
    - 実装の確認やサンドボックスなどへの絶縁が大事だと思います
5. LLM とのシームレスな連携
    - 最後のタスクである「好きな歌のサジェスト」では、favorite_songs.txt ファイルの内容から曲を提案しました
    - トレースをみても間違ったファイルを開いて探索するなどの迷いは感じられませんでした
    - 結果的に事前にリストから削除した「竹内まりや - プラスティック・ラヴ」がサジェストされて感動です
        - 世界的にはシティーポップの代表曲ということになっているそうです
        - LLM が知っている内容で出題しているので、知らない内容で出題させるとよりハードなテストかもしれません
    - ちょっとタスクが簡単だったかもしれません
6. Trace 機能の有用性
    - OpenAI Platform の Trace 機能は「何が起こっていたのか」を知るための重要なツールだと思います
    - AI エージェントの機能改善や性能改善に役立ちそうです
    - ほぼリアルタイムに情報が更新されるので、デバッグ作業がはかどります


# まとめ

この記事では OpenAI Agents SDK と MCP を連携させて、ローカルファイルシステムを操作する AI エージェントの挙動を確認しました。非常に手軽に使えるため流行るのも頷けます。情報セキュリティについても手軽なフレームワーク等があるとより手軽になると思いました。すでに「MCP サーバー全部入り Docker サンドボックス」みたいなものが出ているのかもしれません。

今後も MCP Server に注目してゆきたいと思いました。果たして「デファクトスタンダード」になれるのか？

最後までお読み頂きありがとうございました！


# 参照

## 公式リファレンス Model context protocol (MCP)

https://openai.github.io/openai-agents-python/mcp/

## MCP のアーキテクチャと仕様

https://modelcontextprotocol.io/specification/2025-03-26/architecture/index#capability-negotiation