Skip to main content
Glama
zakkii-k
by zakkii-k
README.md
# mcp-compressor

GitHub Copilot の MCP レスポンスをインターセプトし、トークン消費を削減するプロキシ。

## 解決する問題

| 問題 | 対策 |
|------|------|
| MCP のレスポンスが大きくてトークンを食う | 圧縮パイプラインで削減 |
| ツール定義が多くて毎ターン固定コストがかかる | メタツール方式で常に2ツールだけ公開 |
| 内部・外部 MCP が混在していてインターセプトが難しい | wrap モードで一箇所に集約 |

---

## 仕組み

### 圧縮パイプライン

MCP のレスポンスを以下の順で処理する。

```
MCP レスポンス
  ↓ TOON 変換        JSON を 36〜64% 削減(LLM 可読のまま)
  ↓ ログ重複除去      繰り返しパターンを集約、最大 98% 削減
  ↓ ログ圧縮         大量ログを先頭 / エラー / 末尾に絞る
  ↓ LLM 要約        閾値超えのみ Ollama で要約(元データ保存)
  ↓
Copilot へ返却
```

### プロキシモード

#### stdio モード(デフォルト)

MCP サーバーを1つずつラップする。既存の設定に1行追加するだけ。

```
Copilot → mcp-compressor → 実際の MCP サーバー(子プロセス)
```

#### wrap モード

`mcp.servers.json` に書いた全サーバーに接続し、Copilot には1つのサーバーとして見せる。
内部(stdio)・外部(SSE/HTTP)問わず一箇所でインターセプトできる。

```
Copilot → mcp-compressor ┬→ filesystem サーバー(stdio)
                          ├→ atlassian サーバー(SSE)
                          └→ github サーバー(SSE)
```

**メタツール方式(デフォルト)**

Copilot に公開するのは常に2ツールだけ。

```
mcp__list_tools(query?)              ← ツール一覧を返す(TOON 圧縮対象)
mcp__invoke_tool(server, tool, args) ← ツールを実行する
```

ツール定義は LLM に毎ターン送られる。ツールが多いほど固定コストが増えるため、
常に2つに絞ることで削減する。

```
通常方式: ツール定義 × 30個 × 会話10ターン = 300回分の定義コスト
メタツール: ツール定義 × 2個 × 会話10ターン = 20回分
           + list_tools の結果(TOON 圧縮済み)が履歴に1回
```

---

## セットアップ

### 前提条件

- Windows 11
- Rancher Desktop(Docker 利用のため)
- Python 3.11 以上(インストール済みであれば pyenv 不要)

### 1. リポジトリをクローン(PowerShell)

```powershell
cd C:\Users\ユーザー名\projects   # 任意のディレクトリ
git clone https://github.com/zakkii-k/mcp-compressor.git
cd mcp-compressor
```

以降のパス例は `C:\Users\ユーザー名\projects\mcp-compressor` として記載する。実際のパスに読み替えること。

### 2. Ollama を起動

WSL・PowerShell どちらでも同じ(Rancher Desktop が起動していれば `docker` が使える)。
`docker compose up` はリポジトリ内で実行すること。

```powershell
# リポジトリ内で実行
docker compose up -d

# または docker run で起動(ディレクトリを問わない)
docker run -d `
  --name ollama `
  -p 11434:11434 `
  -v ollama_data:/root/.ollama `
  --restart unless-stopped `
  ollama/ollama:latest
```

モデルをダウンロード:

```powershell
docker exec ollama ollama pull qwen2.5:3b
```

### 3. mcp-compressor のインストール

2通りある。**Docker が一番シンプル**。

---

#### A. Docker(推奨・Python 環境不要)

```powershell
cd C:\Users\ユーザー名\projects\mcp-compressor
docker build -t mcp-compressor .
```

MCP 設定で `docker run` を指定するだけで動く。

---

#### B. Windows ネイティブ Python

Python が入っていれば pip だけでOK(pyenv 不要)。

```powershell
cd C:\Users\ユーザー名\projects\mcp-compressor
pip install httpx pyyaml python-toon
```

---

### 4. mcp.json を編集

VS Code のグローバル MCP 設定は以下にある:

```
C:\Users\ユーザー名\AppData\Roaming\Code\User\mcp.json
```

> グローバル設定なのでパスは**絶対パス**で書くこと。
> ワークスペースごとに設定する場合は `.vscode/mcp.json` を使う(相対パス可)。

#### stdio モード(サーバーを1つずつラップする場合)

**変更前:**
```json
{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\path\\to\\dir"]
    }
  }
}
```

**変更後(Python):**
```json
{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "python",
      "args": [
        "-m", "mcp_compressor",
        "--config", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\config.yaml",
        "--",
        "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\path\\to\\dir"
      ]
    }
  }
}
```

**変更後(Docker):**
```json
{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "mcp-compressor",
        "--",
        "npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"
      ]
    }
  }
}
```

#### wrap モード(全サーバーを1エントリに集約する場合)

**Step 1:** 既存の mcp.json の `servers` 部分を `mcp.servers.json` としてリポジトリ内に保存。

```
C:\Users\ユーザー名\projects\mcp-compressor\mcp.servers.json
```

```json
{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\path\\to\\dir"]
    },
    "atlassian": {
      "type": "sse",
      "url": "https://mcp.atlassian.com/v1/sse"
    }
  }
}
```

`mcp.servers.example.json` をコピーして編集してください。

**Step 2:** mcp.json を書き換え(Python):

```json
{
  "servers": {
    "mcp-compressor": {
      "type": "stdio",
      "command": "python",
      "args": [
        "-m", "mcp_compressor",
        "--mode", "wrap",
        "--config", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\config.yaml",
        "--mcp-config", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\mcp.servers.json"
      ]
    }
  }
}
```

**Step 2:** mcp.json を書き換え(Docker):

```json
{
  "servers": {
    "mcp-compressor": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-v", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\mcp.servers.json:/app/mcp.servers.json",
        "-v", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\config.yaml:/app/config.yaml",
        "-v", "C:\\Users\\ユーザー名\\projects\\mcp-compressor\\originals:/app/originals",
        "mcp-compressor",
        "--mode", "wrap"
      ]
    }
  }
}
```

**Copilot から見えるツール:**

```
mcp__list_tools   → query="atlassian" で Jira 関連ツールを検索できる
mcp__invoke_tool  → server="atlassian", tool="create_issue" で実行
```

プレフィックス方式に戻す場合は `--no-meta-tools` を追加。

---

## 設定

`config.yaml`:

```yaml
# 要約閾値(パイプライン処理後にこの文字数を超えたら LLM 要約)
threshold_chars: 5000

# 使用モデル(1行変更で切り替え)
model: "qwen2.5:3b"

# パイプラインステージ(実行順)
pipeline:
  - toon_converter      # JSON → TOON 形式(36〜64% 削減)
  - log_deduplicator    # 繰り返しパターンのログを集約
  - log_compressor      # ログの先頭/エラー/末尾を抽出
  - llm_summarizer      # LLM で要約(Ollama 必要)
```

### 推奨モデル(16GB RAM)

| 品質順 | モデル | RAM | 備考 |
|:------:|--------|-----|------|
| 1 | `qwen2.5:7b` | ~4.5GB | 要約タスク最高品質 |
| 2 | `qwen3:4b` | ~3GB | thinking mode を自動無効化して使用 |
| 2 | `gemma4:e4b` | ~3GB | Google 製、バランス良好 |
| 4 | `qwen2.5:3b` | ~2GB | **デフォルト**。安定・高速 |

### 環境変数

| 変数 | 内容 | デフォルト |
|------|------|-----------|
| `OLLAMA_URL` | Ollama の URL(Docker 内は自動設定済み) | `http://localhost:11434` |
| `MCP_MODEL` | 使用モデル | `qwen2.5:3b` |
| `MCP_THRESHOLD` | 要約閾値(文字数) | `5000` |

---

## 圧縮手法の詳細

[docs/compression-techniques.md](docs/compression-techniques.md) を参照。

| 手法 | 削減率 | LLM 不要 | 対象 |
|------|--------|---------|------|
| TOON 変換 | 36〜64% | ✅ | JSON 全般 |
| ログ重複除去 | 80〜98% | ✅ | 繰り返しパターンのログ |
| ログ先頭/エラー/末尾 | 60〜80% | ✅ | 大量ログ |
| LLM 要約 | 70〜90% | ❌ | 汎用テキスト |

---

## テスト

Ollama なしでパイプラインと wrap モードのテストが実行できる。

```powershell
pip install pytest
pytest tests/ -v
```

Ollama 起動後は LLM 要約テストも自動で有効になる。

---

## プロジェクト構成

```
mcp-compressor/
├── mcp_compressor/
│   ├── main.py              # エントリーポイント(--mode stdio/wrap/http)
│   ├── config.py            # 設定読み込み(環境変数対応)
│   ├── pipeline/            # 圧縮パイプライン
│   │   ├── toon_converter.py
│   │   ├── log_deduplicator.py
│   │   ├── log_compressor.py
│   │   ├── json_compressor.py
│   │   ├── json_table_converter.py
│   │   └── llm_summarizer.py
│   └── proxy/
│       ├── stdio_proxy.py        # stdio モード(ローカル MCP)
│       ├── wrap_proxy.py         # wrap モード(全 MCP を集約)
│       ├── server_connection.py  # stdio/SSE サーバー接続管理
│       └── http_proxy.py         # HTTP モード(未実装・スタブ)
├── tests/
├── docs/
│   ├── setup.md
│   └── compression-techniques.md
├── config.yaml
├── mcp.servers.example.json
├── Dockerfile
└── docker-compose.yml
```

Maintenance

ActivityInactive
ResponsivenessNo issues