Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
9e1546a
MCPローカル環境実行用に設定追加
hitoshi-hasegawa May 8, 2025
de01586
MCPにmdファイルから変換するツール追加
hitoshi-hasegawa May 8, 2025
24830bb
MCPのSTG環境のドキュメントを修正
hitoshi-hasegawa May 8, 2025
27ab533
middleman-ai バージョン更新
hitoshi-hasegawa May 8, 2025
eab9dc0
MCPのエラーハンドリング追加
hitoshi-hasegawa May 8, 2025
20412a1
テスト追加
hitoshi-hasegawa May 8, 2025
403161c
MIDDLEMAN_BASE_URL_VCR => MIDDLEMAN_BASE_URL
hitoshi-hasegawa May 9, 2025
d39be8a
バージョンを0.1.1に変更
hitoshi-hasegawa May 9, 2025
5748fba
Merge pull request #26 from GenerativeAgents/feature/add-md-file-to-x…
hitoshi-hasegawa May 9, 2025
74b3827
CHANGELOGの更新
hitoshi-hasegawa May 9, 2025
601958e
単体テストではリテラルのベタ打ちを許可
mido-app May 14, 2025
8200a1a
マスク対応
mido-app May 14, 2025
ba143da
バリデーションエラー系をBadRequestErrorに統一
mido-app May 14, 2025
ba9570a
md_to_docxクライアントにテンプレートIDを追加し既存の単体テストを修正
mido-app May 14, 2025
edc523f
md_to_docxのクライアント単体テスト修正 & VCRテストで環境依存の値はマスクしてカセットに保存する仕組みを追加
mido-app May 14, 2025
bd56240
md-to-docxのテンプレートID指定ができるようCLIを修正
mido-app May 14, 2025
7df66c6
md-to-docxのToolをテンプレートID指定に対応
mido-app May 14, 2025
6839435
md-to-docxのテンプレートID指定にMCPを対応 & 単体テスト名の改善とテンプレートID指定があるツールのパラメタライズドテストを追加
mido-app May 14, 2025
a664f96
VCRテストの環境依存対策
mido-app May 14, 2025
9353d77
レビュー指摘対応
mido-app May 14, 2025
a396c5e
fix cassette
mido-app May 14, 2025
03b85e3
Merge pull request #28 from GenerativeAgents/feature/md-to-docx-template
mido-app May 14, 2025
e2d6aab
version v0.1.2に変更 & CLIにBASE_URL環境変数が効かないバグを修正
mido-app May 14, 2025
d81b87d
SDKのCI構築
mido-app May 19, 2025
751df11
mypyはsrcフォルダのみを対象に実行するようCIを修正
mido-app May 19, 2025
a40bbd0
古いアクションのバージョンを更新
mido-app May 19, 2025
cd579f8
Merge pull request #29 from GenerativeAgents/feature/ci
mido-app May 19, 2025
615b0ad
Cursor Rulesを追加
mido-app May 19, 2025
a4b8c11
fix typo
mido-app May 19, 2025
0226b24
Merge pull request #30 from GenerativeAgents/feature/cursor-rules
mido-app May 19, 2025
1db7793
mermaid-to-imageのClient実装を追加
mido-app Jul 2, 2025
77a8189
mermaid-to-imageのClientVCRテストを追加
mido-app Jul 2, 2025
e4d09f7
mermaid-to-image: Clientのデフォルト値の扱いを改善
mido-app Jul 2, 2025
e943ac6
mermaid-to-image: CLIの実装
mido-app Jul 2, 2025
459ba03
mermaidツールをmcpに追加
mido-app Jul 4, 2025
1516fe5
LangChainツールのサポート終了
mido-app Jul 4, 2025
24e60a2
CHANGELOGの更新 + バージョンアップ
mido-app Jul 4, 2025
04376d1
fix CHANGELOG.md
mido-app Jul 4, 2025
647f339
Merge pull request #32 from GenerativeAgents/feature/mermaid-to-image
mido-app Jul 7, 2025
680557e
fix CHANGELOG
mido-app Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .cursor/rules/cli.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
description:
globs: src/middleman_ai/cli/*.py,tests/cli/*.py
alwaysApply: false
---
# CLI実装ルール

このドキュメントにはMiddleman SDK用のコマンドラインインターフェース(CLI)に関するルールをまとめます。

## 実装の概要

CLIは [cli](mdc:src/middleman_ai/cli) ディレクトリに実装されており、コマンドラインからMiddleman.ai APIを呼び出すための機能を提供しています。実装にはclick(https://click.palletsprojects.com/en/stable/)を使用しています。

## 実装ルール

- 各コマンドは `@cli.command()` デコレータで定義する
- 環境変数 `MIDDLEMAN_API_KEY` からAPIキーを取得する
- 入力データは標準入力から受け取る
- コマンドの引数はClickの型アノテーションで定義する、引数が必須なのか非必須なのかは注意すること
- エラーハンドリングは `click.ClickException` を使用する
- 進捗状況は `click.progressbar` で表示する
- 今何をしているかがわかりやすいよう、利用者向けのログをprintで適宜表示する

```python
@cli.command()
@click.argument("template_id", required=False)
def md_to_pdf(template_id: str | None = None) -> None:
"""Convert Markdown to PDF."""
try:
client = get_client()
markdown_text = sys.stdin.read()
with click.progressbar(length=1, label="PDFに変換中...") as bar:
pdf_url = client.md_to_pdf(markdown_text, pdf_template_id=template_id)
bar.update(1)
print(f"変換結果URL: {pdf_url}")
except MiddlemanBaseException as e:
raise click.ClickException(str(e)) from e
```

## テストルール

CLIのテストは [tests/cli](mdc:tests/cli) ディレクトリに実装されています。

### test_cli.py の共通ルール

1. **テストフィクスチャ**: CLI実装の部分のみがテスト対象のため、中で利用しているクライアント部分をモック化してテストする
```python
def test_md_to_pdf_cli(runner, mock_client):
```

2. **コマンド呼び出し**: `runner.invoke` でCLIコマンドを実行し、標準入力はオプション引数 `input` で渡す
```python
result = runner.invoke(cli, ["md-to-pdf"], input="# Test")
```

3. **結果検証**: 終了コード、出力内容、モックの呼び出し状況を検証
```python
assert result.exit_code == 0
assert "https://example.com/test.pdf" in result.output
mock_client.md_to_pdf.assert_called_once_with("# Test", pdf_template_id=None)
```

4. **エラー処理のテスト**: APIキー未設定などのエラーケースもテスト
```python
def test_missing_api_key_cli(runner, mocker):
```

### test_mcp_cli.py

MCPサーバーコマンドのテストを実装しています。
MCPサーバー立ち上げコマンドのみ、他とは特徴が違います。
このコマンドはMiddlemanのAPIコールをするのではなくMCPサーバーを立ち上げる役割になります。

```python
def test_mcp_command(runner: CliRunner, mocker: "MockerFixture") -> None:
"""mcpコマンドのテスト。"""
mock_run_server = mocker.patch.object(mcp_server, "run_server")
result = runner.invoke(mcp_command)
assert result.exit_code == 0
assert "MCP server is running" in result.output
mock_run_server.assert_called_once_with()
```
63 changes: 63 additions & 0 deletions .cursor/rules/client.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
description:
globs: client.py,test_client.py,test_client_vcr.py
alwaysApply: false
---
# Pythonクライアント実装ルール

このドキュメントにはMiddleman SDKにアクセスできるPythonクライアント [client.py](mdc:src/middleman_ai/client.py) の実装ルールをまとめます。

## 実装ルール

- エラー処理は分散させずに共通化する
- レスポンスは正しいPydanticモデルでパースする

## テストルール

Pythonクライアントのテストは以下の2箇所で実装します。

- [test_client.py](mdc:tests/test_client.py): 単体テスト
- [test_client_vcr.py](mdc:tests/test_client_vcr.py): VCRテスト

### test_client.py

API呼び出しをpytestを使ってモック化することで、クライアントコードのみをテストする単体テストを記載します。
正常系、異常系やAPIに渡すパラメータパターンごとにテストケースが分かれれいます。

```python
# 例
def test_md_to_pdf_success(
client: ToolsClient, mocker: "MockerFixture", mock_response: Mock
) -> None:
"""md_to_pdf成功時のテスト。"""
mock_post = mocker.patch.object(client.session, "post", return_value=mock_response)

result = client.md_to_pdf("# Test")

assert result == "https://example.com/test.pdf"
mock_post.assert_called_once_with(
"https://middleman-ai.com/api/v1/tools/md-to-pdf",
json={"markdown": "# Test", "pdf_template_id": None},
timeout=30.0,
)
```

### test_client_vcr.py の共通ルール

VCRテストでは、以下のルールに従ってテストを実装します。
なお、 [vcr.mdc](mdc:.cursor/rules/vcr.mdc) に記載の共通ルールも守るようにしてください。


1. **テスト内のアサーション**: 環境に依存する値や戻り値が呼び出しごとに違う値は、環境によらずに成功するアサーションにします
```python
# https://xxx.xxx/s/xxxxx というURLであることを検証する場合の例、xxxの部分は環境依存
assert pdf_url.startswith("https://")
assert "/s/" in pdf_url
```

2. **環境変数の利用**: テンプレートIDなど環境依存の値は環境変数から取得する
```python
template_id = os.getenv("MIDDLEMAN_TEST_PPTX_TEMPLATE_ID") or ""
```


34 changes: 34 additions & 0 deletions .cursor/rules/mcp.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
description:
globs: src/middleman_ai/mcp/*.py,test_mcp_cli.py,test_mcp.py
alwaysApply: false
---
# MCP実装ルール

このドキュメントにはMiddleman SDKがModel Context Protocol(MCP)に準拠したサーバー実装に関するルールをまとめます。

## 実装の概要

MCPサーバーは [mcp](mdc:src/middleman_ai/mcp) ディレクトリに実装されています。MCPはAnthropicが提供する標準プロトコルで、AI(LLM)とツールを接続するための仕組みを提供します。これにより、Claude、Cursor、ZedなどのMCP対応クライアントからMiddleman.ai APIを直接利用できるようになります。

実装には`FastMCP`フレームワークを使用し、各ツールを関数としてMCPサーバーに登録しています。

## 実装ルール

- 各ツールは`@mcp.tool()`デコレータを使用して定義する
- 引数の型はPythonの型アノテーションを使用して明示する
- サーバー起動時には環境変数(`MIDDLEMAN_API_KEY`)からAPIキーを取得する
- ファイル読み込み機能を持つツールでは、パスの存在やアクセス権を確認する

## テストルール

MCPサーバーのテストは [test_mcp.py](mdc:tests/test_mcp.py) に実装されています。

### test_mcp.py の共通ルール

1. **モックの使用**: MCPの実装のみをテストしたいのでクライアントの処理はモック化します
```python
mock_client = mocker.patch("middleman_ai.mcp.server.client")
mock_client.md_to_pdf.return_value = "https://example.com/test.pdf"
```

44 changes: 44 additions & 0 deletions .cursor/rules/readme.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
description:
globs:
alwaysApply: true
---

# Middleman SDK

## 概要

このリポジトリでは AI エージェントが利用できるツールを API として提供するサービス「Middleman」の API を簡単に利用できるようにするためのクライアントコードを SDK として管理しています。

Middleman SDK は、以下の 3 種類の方法で Middleman の API へのアクセスを提供します。

- Python クライアント: Python コードから簡単に API 呼び出しができるクライアント(実装: [client.py](mdc:src/middleman_ai/client.py))
- CLI: コマンドラインから簡単に API 呼び出すことができる CLI(実装: [main.py](mdc:src/middleman_ai/cli/main.py))
- MCP(Model Context Protocol): AI エージェントが外部 API やツールを呼び出すためのプロトコル(実装: [server.py](mdc:src/middleman_ai/mcp/server.py))

※ Model Context Protocol 参考サイト: https://modelcontextprotocol.io/introduction

# 開発ルール

## テスト

### ルール

- ユーザーからの依頼に対応後、必ず単体テストを実行し実装が妥当かどうかを確認する
- 新しい引数が増えたなど、テストすべき新しい観点が発生した場合にはテストケースの追加・修正が必要である

### テスト実行

```bash
uv run pytest
uv run pytest -v
uv run pytest -v path/to/test
uv run pytest -k search_keyword
```

### リンター実行

```bash
uv run ruff check .
uv run mypy ./src
```
54 changes: 54 additions & 0 deletions .cursor/rules/vcr.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
description:
globs: tests/**/*.yaml,tests/**/*_vcr.py,vcr_utils.py,conftest.py
alwaysApply: false
---
# VCRテスト(Virtual Cassette Recorder)

VCRテストとは、外部APIとの通信をモック化するテスト手法です。実際のHTTPリクエストとレスポンスを「カセット」と呼ばれるファイルに記録し、以降のテスト実行時にはその記録を再生することで、外部サービスに依存せずテストを実行できます。

## VCRテストの目的と利点

1. **一貫性の確保**: 外部APIの応答変更に影響されず、一貫したテスト結果を得られます
2. **高速化**: 実際のネットワークリクエストが不要なため、テスト実行が高速化します
3. **オフライン対応**: インターネット接続がない環境でもテストが可能です
4. **API負荷軽減**: 外部サービスへの不必要なリクエストを減らせます

## VCRテストの仕組み

1. 初回テスト実行時に実際のHTTPリクエストを送信
2. リクエストとレスポンスの詳細(URL、ヘッダー、ボディなど)をYAMLファイルに記録
3. 2回目以降の実行時はYAMLファイルから応答を再生

## 重要な注意事項

1. **ローカル実行時の挙動**: ローカル環境での実行時には2回目以降もリクエスト照合が行われます。つまり、実際のリクエストの内容とカセットに記録されたリクエストの内容が一致するか確認され、一致する場合のみ記録された応答が返されます。

2. **カセット修正のルール**: カセットファイルを手動で修正する場合、必ず人間(チームメンバーまたは管理者)に修正許可を得てください。カセットの内容を不用意に変更すると、テストの信頼性が損なわれる可能性があります。

3. **機密情報の扱い**: APIキーなどの機密情報がカセットファイルに記録される場合があるため、それらが適切にフィルタリングされていることを確認してください。


## VCRテスト共通の実装ルール

1. **テスト関数の命名**: 関数名の末尾に `_vcr` を付けて、VCRテストであることを明示する
```python
def test_md_to_pdf_vcr(client: ToolsClient) -> None:
```

2. **pytest.mark.vcr() デコレータ**: 全てのVCRテスト関数に付与する
```python
@pytest.mark.vcr()
def test_md_to_pdf_vcr(client: ToolsClient) -> None:
```

3. **マルチパートリクエストの扱い**: ファイルアップロードを伴うテストでは、リクエストボディが環境によって変化するため、`match_on` パラメータを使用してマッチング条件を調整する
```python
@pytest.mark.vcr(match_on=["method", "scheme", "port", "path", "query"])
def test_pdf_to_page_images_vcr(client: ToolsClient) -> None:
```

4. **機密情報のカセット記録**: このリポジトリはpublicリポジトリのため、機密情報(APIキーや本番環境以外の環境のURLなど)がカセットに残ると悪用の可能性がある。そのため、 [vcr_utils.py](mdc:tests/vcr_utils.py) [conftest.py](mdc:tests/conftest.py) にあるように機密情報をフィルタリングしている。もし、機密情報がカセットに記録されていることに気づいた場合、フィルタリングを追加し、人間にもその旨を理由と共に報告すること。



4 changes: 2 additions & 2 deletions .env.test.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MIDDLEMAN_BASE_URL_VCR=https://middleman-ai.com
MIDDLEMAN_API_KEY_VCR=your_test_api_key
MIDDLEMAN_BASE_URL=https://middleman-ai.com
MIDDLEMAN_API_KEY=your_test_api_key
MIDDLEMAN_TEST_PDF_TEMPLATE_ID=your_test_pdf_template_id
MIDDLEMAN_TEST_PPTX_TEMPLATE_ID=your_test_pptx_template_id
47 changes: 47 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Run Tests

on:
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: "0.5.29"

- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ matrix.python-version }}-${{ hashFiles('**/uv.lock') }}

- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: |
uv sync --dev

- name: Run linting
run: |
uv run ruff check .

- name: Run type checking
run: |
uv run mypy ./src

- name: Run tests
run: uv run pytest -v
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,8 @@ spec.md
.env.production
.env.development.local
.env.production.local

# Claude Code
.claude/
.cursor/mcp.json

18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@

フォーマットは[Keep a Changelog](https://keepachangelog.com/ja/)に基づいています。

## [v0.2.0] - 2025-07-05

### 追加

- 「Mermaid ダイアグラムを画像変換」ツールとの連携を追加
- 「マークダウン → DOCX変換」にテンプレート ID 指定機能を追加

### 削除

- LangChain ツール実装はサポート対象外とし削除

## [v0.1.1] - 2025-05-09

### 追加

- ローカルの Markdown ファイルパスを指定して PDF に変換する MCP ツール (`md_file_to_pdf`) を追加
- ローカルの Markdown ファイルパスを指定して DOCX に変換する MCP ツール (`md_file_to_docx`) を追加

## [v0.1.0] - 2025-04-28

### 追加
Expand Down
Loading