Task API MCP
README.md
# Task API MCP
[English](README.en.md)
既存REST APIをAIクライアントから利用するための、ローカル実行可能なPythonサンプルです。FastAPIで作られたタスク管理APIを正規の入り口として残し、stdio MCPサーバーは `create_task` ToolとHTTPの間を変換する薄いアダプターとして動作します。
> このリポジトリは学習・ローカル検証用です。認証、複数プロセス対応、冪等性など、実運用で必要になる機能は意図的に含めていません。
最終更新: 2026-07-15
## できること
- `POST /tasks` でタスクを作成し、`data/tasks.json` へ保存する
- `GET /tasks` と `GET /tasks/{task_id}` でタスクを確認する
- MCPの `create_task` Toolから同じREST APIを呼び出す
- 入力エラー、一時障害、想定外レスポンスを安全なMCPエラーへ変換する
- 実サーバーを使わず、API・HTTP・MCP各層を自動テストする
## アーキテクチャ
```mermaid
flowchart LR
User[ユーザー] -->|自然言語| AI[AIクライアント]
AI -->|MCP / stdio| MCP[task_mcp]
MCP -->|HTTP POST /tasks| API[task_api]
API --> JSON[(data/tasks.json)]
```
| コンポーネント | 責務 |
|---|---|
| AIクライアント | 自然言語をTool引数へ変換する |
| `task_mcp` | Tool Schemaを公開し、MCPとHTTPを変換する |
| `task_api` | 入力・業務ルールを検証し、タスクを作成する |
| `data/tasks.json` | ローカル環境でタスクを永続化する |
MCPサーバーはJSONファイルを直接変更しません。保存処理と過去日付の禁止はREST API側にだけ実装されています。
## クイックスタート
### 必要なもの
- Python 3.10以上
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
- Node.js 18以上(MCP Inspectorを使う場合のみ)
- Codex CLI(Codexから試す場合のみ)
### 1. 依存関係をインストールする
リポジトリをcloneしたディレクトリで実行します。
```bash
cd task-api-mcp
uv sync --dev
```
`uv.lock` が含まれているため、記事と同じ `mcp[cli]==1.28.1` を含む検証済みの依存関係がインストールされます。
### 2. REST APIを起動する
```bash
uv run task-api
```
開発中に自動リロードを使う場合は、代わりに次を実行します。
```bash
uv run uvicorn task_api.app:app --reload --port 8000
```
APIは `http://localhost:8000` で起動します。Swagger UIは [http://localhost:8000/docs](http://localhost:8000/docs) です。
### 3. タスクを作成する
別のターミナルで実行します。
```bash
curl -X POST http://localhost:8000/tasks \
-H "Content-Type: application/json" \
-d '{
"title": "MCPの記事を公開する",
"description": "図とコードを最終確認する",
"priority": "high"
}'
```
`201 Created` と、次のようなタスクが返れば成功です。
```json
{
"id": "b48b8da3-f80b-40e3-a78d-8d70b11e58c4",
"title": "MCPの記事を公開する",
"description": "図とコードを最終確認する",
"priority": "high",
"due_date": null,
"status": "todo",
"created_at": "2026-07-15T21:30:00+09:00"
}
```
作成結果は `data/tasks.json` に保存されます。
## MCP Inspectorで試す
REST APIを起動したまま、別のターミナルで実行します。
```bash
TASK_API_BASE_URL=http://localhost:8000 \
npx -y @modelcontextprotocol/inspector \
uv run python -m task_mcp.server
```
Inspectorで次を確認できます。
1. `Tools` から `create_task` を選ぶ
2. `title` が必須であることを確認する
3. `priority` が `low` / `medium` / `high` のenumであることを確認する
4. `due_date` に今日以降の日付を入力して実行する
## Codex CLIへ登録する
リポジトリのルートで次を実行します。
```bash
codex mcp add task-manager \
--env TASK_API_BASE_URL=http://localhost:8000 \
--env TASK_API_TIMEOUT_SECONDS=10 \
-- uv run python -m task_mcp.server
```
登録結果を確認します。
```bash
codex mcp list
```
その後、Codexへ次のように依頼できます。
```text
明日までに「MCPの記事を公開する」というタスクを作成してください。
優先度はhighにしてください。
```
Codexの設定方法は[公式MCPドキュメント](https://developers.openai.com/codex/mcp)も参照してください。
## REST APIリファレンス
ベースURL: `http://localhost:8000`
認証: なし(ローカルデモのみ)
| メソッド | パス | 成功時 | 説明 |
|---|---|---:|---|
| `POST` | `/tasks` | `201` | タスクを作成する |
| `GET` | `/tasks` | `200` | 全タスクを作成順で返す |
| `GET` | `/tasks/{task_id}` | `200` | IDでタスクを1件取得する |
### `POST /tasks` の入力
| フィールド | 型 | 必須 | デフォルト | 制約 |
|---|---|---:|---|---|
| `title` | string | はい | — | 空白除去後1〜100文字 |
| `description` | string / null | いいえ | `null` | 最大1000文字 |
| `priority` | string | いいえ | `medium` | `low`, `medium`, `high` |
| `due_date` | string / null | いいえ | `null` | `YYYY-MM-DD`、今日以降 |
未知のフィールドは受け付けません。時刻は保存しないため、「明日の17時」の17時部分は `due_date` には入りません。
### 主なエラー
| 状態 | HTTP | MCPでの扱い |
|---|---:|---|
| 必須・型・文字数・enum・日付形式の不正 | `422` | 通常はTool Schemaで先に検出 |
| 過去の `due_date` | `422` | 修正可能な `ToolError` |
| 存在しないタスク | `404` | `GET` APIのみ |
| JSON保存障害 | `500` | 一時的な利用不能 |
| APIタイムアウト・接続失敗 | — | 一時的な利用不能 |
| 不正JSON・未知のHTTP状態 | — | 詳細を隠した想定外エラー |
## 設定
| 環境変数 | デフォルト | 使用箇所 | 説明 |
|---|---|---|---|
| `TASK_API_BASE_URL` | `http://localhost:8000` | MCP | 接続先REST API |
| `TASK_API_TIMEOUT_SECONDS` | `10` | MCP | HTTPタイムアウト秒数。0より大きい数値 |
| `TASK_API_DATA_FILE` | `data/tasks.json` | REST API | JSON保存先 |
`.env.example` を使う場合、uvへ明示的に渡します。
```bash
cp .env.example .env
uv run --env-file .env task-api
```
MCPサーバーにも同じ方法を使えます。
```bash
uv run --env-file .env task-mcp
```
## プロジェクト構成
```text
task-api-mcp/
├── data/tasks.json # ローカルのタスクデータ
├── docs/plans/ # 設計判断
├── src/
│ ├── task_api/
│ │ ├── app.py # FastAPIのルートと起動処理
│ │ ├── models.py # REST APIの入出力モデル
│ │ └── repository.py # JSON永続化
│ └── task_mcp/
│ ├── api_client.py # 非同期REST APIクライアント
│ ├── errors.py # HTTP結果の意味的なエラー分類
│ ├── models.py # MCP境界の構造化モデル
│ └── server.py # create_task Toolとstdio起動処理
├── tests/ # API、HTTP、MCPのテスト
├── .env.example # 環境変数の例
├── pyproject.toml # パッケージと依存関係
└── uv.lock # 解決済み依存関係
```
## テスト
```bash
uv run pytest
```
テストでは一時ディレクトリと `httpx.MockTransport` を使うため、起動中のAPIや既存の `data/tasks.json` は変更しません。
## トラブルシューティング
### `Address already in use` と表示される
ポート8000を使用中のプロセスを停止するか、別ポートでAPIを起動し、MCP側のURLも合わせます。
```bash
uv run uvicorn task_api.app:app --port 8001
TASK_API_BASE_URL=http://localhost:8001 uv run task-mcp
```
### MCPから `temporarily unavailable` が返る
REST APIが起動していることと、`TASK_API_BASE_URL` が正しいことを確認してください。コンテナ内から接続する場合、`localhost` はコンテナ自身を指します。
### `due_date must be today or later` が返る
`due_date` をAPIが動作している環境の今日以降へ変更してください。
### `Task storage is unavailable` が返る
`TASK_API_DATA_FILE` の親ディレクトリへ書き込めることと、既存ファイルがJSON配列であることを確認してください。デモデータを破棄してよければ、API停止後に `data/tasks.json` を削除できます。次回作成時に再生成されます。
## 実運用へ進む前に
- JSONファイルをトランザクションと複数プロセスに対応したデータベースへ置き換える
- API認証情報をTool引数ではなく、環境変数またはシークレットストアから取得する
- REST API側へ冪等性キー、重複検出、監査ログ、レート制限を追加する
- リモート利用ではstdioではなく、認証とOrigin検証を備えたStreamable HTTPを検討する
## ライセンス
[MIT License](LICENSE)
TDQS
B3.3/5.0
Scored across 1 tool
Disambiguation5/5
Only one tool exists, so there is no possibility of confusion or overlap.
Naming Consistency5/5
With a single tool, naming is trivially consistent; no pattern violations occur.
Tool Count2/5
A task management service with only one creation tool is too thin; typical requires at least list, read, update, and delete operations.
Completeness2/5
The tool surface lacks critical operations like listing, retrieving, updating, and deleting tasks, leaving significant gaps for agents.
Maintenance
ActivitySlowing
ResponsivenessNo issues