Skip to main content
Glama
OuchiniKaeru

Genetic Optimization MCP Server

by OuchiniKaeru
README.md
# 遺伝的最適化 MCP サーバー

AI エージェントの代わりに単目的遺伝的アルゴリズム最適化を実行する、再利用可能な MCP サーバーです。エージェントが変数、目的関数、制約、計算予算を定義すると、サーバーが定義を検証し、pymoo を用いた混合変数 GA を隔離されたワーカープロセスで実行し、構造化された結果を返します。

> 得られた結果は予算内で見つかった最良の候補であり、**大域最適解を保証するものではありません。**

## 機能

- 混合変数型: `float`(線形/対数)、`integer`(ステップ付き)、`choice`、`boolean`。
- 目的関数と制約は、サンドボックス化された数式評価パーサー、または管理者が登録した評価関数から指定可能。
- 回帰テスト済みの評価予算: 最大評価回数、最大世代数、ウォールクロックタイムアウト、シード。
- 管理者管理の評価関数フォルダ。各フォルダが独自の `uv` プロジェクトと `.venv` を持ち、`uv run --locked` と永続的な JSON Lines ワーカープロセスで実行。
- 同期および非同期実行、SQLite バックアップの実行履歴、キャンセル、実行結果の比較。
- MCP 応答はサニタイズ済み。ログは stderr とローテーションする JSON Lines ファイルに出力され(stdout には出力されない)。

## 要件

- Python >= 3.12
- [uv](https://docs.astral.sh/uv/)(登録済み評価関数に必要)

## インストール

```bash
uv sync --extra dev
```

これによりサーバー用の `.venv` が作成されます。登録済み評価関数はこの `.venv` にはインストールされません。各評価関数は独自の環境を持ちます。

## 実行

```bash
uv run optimization-mcp --config config/default.toml
```

デフォルトのトランスポートは stdio です。診断と設定確認:

```bash
uv run optimization-mcp --config config/default.toml --diagnose
```

### MCP ホスト設定(stdio)

```json
{
  "mcpServers": {
    "genetic-optimization": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/絶対パス/to/genetic-optimization-mcp",
        "optimization-mcp",
        "--config",
        "/絶対パス/to/genetic-optimization-mcp/config/default.toml"
      ]
    }
  }
}
```

## ツール

| ツール | 目的 |
|---|---|
| `optimization.list_evaluators` | 許可リスト入り評価関数、そのスキーマ、準備状態を一覧表示 |
| `optimization.validate_problem` | 評価を行わずに問題を検証 |
| `optimization.solve` | `sync` または `async` で最適化を実行 |
| `optimization.get_result` | 実行のステータスと結果サマリーを取得 |
| `optimization.list_runs` | 実行履歴を検索しページング |
| `optimization.cancel` | 実行中/キューイング中のジョブのキャンセルを要求 |
| `optimization.compare_results` | 2–10 件の実行を比較し、明示的な非比較性の注記を付与 |

### エージェントワークフロー(フェーズ 3)

1. `optimization.list_evaluators` を呼び出し、`available`、`deterministic`、パラメータスキーマを確認する。
2. 問題を定義し、`optimization.validate_problem` を `validation_level="strict"` で呼び出す。
3. 小さい予算から始める: `optimization.solve`。
4. 目的値を信用する前に、`constraints.feasible`、`termination_reason`、`warnings`、`variables_at_bounds` を確認する。
5. 必要に応じて範囲や予算を変更し、再実行する。`optimization.compare_results` で比較する。目的関数、評価関数バージョン、パラメータ、制約が異なる場合、単一の改善率を報告することは拒否される。
6. 最大 5 回の反復(上限 20 回)で終了し、結果を「探索により見つかった最良の候補」として、条件と残りの不確実性とともに報告する。

サーバーは LLM を呼び出さず、制約を勝手に緩和することもありません。

## サンプル問題

球関数を最小化:

```json
{
  "problem_name": "sphere_example",
  "variables": {
    "x": {"type": "float", "min": -5.0, "max": 5.0},
    "y": {"type": "float", "min": -5.0, "max": 5.0}
  },
  "objective": {
    "kind": "expression",
    "expression": "(x - 1) ** 2 + (y + 2) ** 2",
    "direction": "minimize"
  },
  "algorithm": {"population_size": 40, "generations": 60, "seed": 42},
  "budget": {"max_evaluations": 2000, "timeout_seconds": 30}
}
```

混合変数と制約:

```json
{
  "problem_name": "mixed_example",
  "variables": {
    "lr": {"type": "float", "min": 0.0001, "max": 0.1, "scale": "log"},
    "depth": {"type": "integer", "min": 2, "max": 10, "step": 2},
    "optimizer": {"type": "choice", "options": ["adam", "sgd"]},
    "augment": {"type": "boolean"}
  },
  "objective": {
    "kind": "expression",
    "expression": "depth + 0.2 * augment",
    "direction": "minimize"
  },
  "constraints": [
    {"constraint_id": "lr_depth", "kind": "expression", "expression": "lr * depth", "operator": "<=", "limit": 0.5}
  ]
}
```

## 登録済み評価関数

`evaluator_root`(デフォルト `./evaluators`)直下の各子フォルダが 1 つの評価関数です:

```
evaluators/
└── model_quality_v1/
    ├── evaluator.toml
    ├── params.schema.json
    ├── pyproject.toml
    ├── uv.lock
    ├── evaluator.py
    └── .venv/            # `uv sync --locked` で作成、コミット対象外
```

`evaluator.toml`:

```toml
evaluator_id = "model_quality_v1"
version = "1.0.0"
description = "Evaluates a deterministic toy model quality score"
module = "evaluator.py"
function = "evaluate"
deterministic = true
timeout_seconds = 30
params_schema_file = "params.schema.json"
```

`evaluator.py` は次のように公開します:

```python
def evaluate(candidate: dict, params: dict, context: dict) -> float:
    ...
```

サーバーが強制する規則:

- ID はスラッグ(`^[a-z0-9][a-z0-9_-]{0,63}$`)であり、フォルダ名と一致しなければならない。
- フォルダは設定されたルートの直接の子でなければならない。ルートを抜けるシンボリックリンク、重複 ID、メタデータ/ロックファイルの欠落により評価関数は利用不可になる。
- `uv lock` は MCP リクエストに応答して**決して実行されない**。ロックの欠落/不整合はエラーとなる。
- `uv sync --project <dir> --locked` は初回使用時、またはロックのフィンガープリントが変更されたときに遅延実行される。
- 評価ワーカーは JSON Lines を stdout で送信する。評価関数の `print()` 出力は stderr にリダイレクトされ、プロトコルを汚染しない。
- 評価結果は有限の JSON 数値でなければならない(ブール値、NaN、Infinity は拒否される)。

サンプル評価関数の準備:

```bash
cd evaluators/model_quality_v1
uv lock
uv sync --locked
```

## 設定

`config/default.toml` を参照してください。パスは設定ファイルを基準として解決されます。環境変数のオーバーライドは `OPTIMIZATION_MCP_` プレフィックスと `__` でネストを表現します。例: `OPTIMIZATION_MCP_LIMITS__MAX_VARIABLES=20`。

管理者による上限値は MCP リクエストから引き上げることはできません。予算を超えるリクエストは `BUDGET_EXCEEDED` で拒否され、値は黙ってクランプされることはありません。

## データとログ

- SQLite データベース: `data/optimization.db`(WAL モード、トランザクション)。
- JSON Lines ログ: `logs/optimization-mcp.log`(ローテーション、保持期間は設定済み)。
- 標準出力は MCP stdio トランスポートに専用。ログは stderr/ファイルを使用。
- フル人口ではなく、サマリーと上位候補のみが永続化される。

### 保持期間とバックアップ

`persistence.log_retention_days` と `persistence.log_max_bytes` / `backup_count` を設定してください。データベースを安全にバックアップするには:

```bash
sqlite3 data/optimization.db ".backup 'backup-optimization.db'"
```

復元はサーバーを停止し、`data/optimization.db` をバックアップと置き換えて行います。旧データベース取得時に `running` だった実行は、次回の起動時に `failed`(キャンセルが要求されていれば `cancelled`)として復旧します。完了済みの実行は引き続き問い合わせ可能です。

## セキュリティに関する注意事項

- 数式は Python `ast` で解析され、許可リストに基づいて評価される。`eval`、`exec`、属性アクセス、添字アクセス、内包表記、ラムダ、インポートは拒否される。
- MCP 入力からコード、パス、モジュール名、コマンドを提供することはできない。管理者が登録した評価関数 ID のみがコードを実行できる。
- `uv` 環境は依存関係の分離であり、**OS サンドボックスではない**。信頼できる評価関数コードのみを評価関数ルートに配置する。信頼できないコードには OS ユーザー/コンテナ/リソース制限を使用する。
- エラー応答はサニタイズされる。トレースバック、絶対パス、環境変数は含まれない。
- 認証、TLS、レート制限なしで Streamable HTTP を有効にしないこと(デフォルトでは無効)。

## テスト

```bash
uv run pytest
uv run ruff check src tests
```

`uv` 環境を必要とするテストは、`uv` が利用できない場合や `OPTIMIZATION_MCP_SKIP_UV_TESTS=1` が設定されている場合はスキップされます。

TDQS

A3.7/5.0

Scored across 7 tools

Disambiguation5/5

Each tool maps to a distinct stage of the optimization lifecycle: validate, submit, poll, list history, cancel, compare, and enumerate evaluators. The only potentially adjacent pair (solve vs. validate_problem) is clearly separated by the descriptions, since validation explicitly evaluates nothing. No two tools could plausibly be mistaken for one another.

Naming Consistency5/5

All tools share a uniform 'optimization.' namespace and use snake_case verb_noun naming (get_result, validate_problem, list_evaluators, list_runs, compare_results). The bare 'solve' is the sole noun-less verb but reads naturally as the primary action and does not break the pattern.

Tool Count5/5

Seven tools is well within the sweet spot and every tool earns its place: submission, polling, validation, enumeration, history, cancellation, and comparison are all genuinely needed. There is no filler or redundant surface.

Completeness4/5

The run lifecycle is fully covered end-to-end, including idempotency, async polling, cancellation, and cross-run comparison, which is unusually thorough. Minor gaps remain: no way to delete/prune run history or manage stored problems, and no streaming/partial-progress retrieval beyond status polling.

Maintenance

ActivityMaintained
ResponsivenessNo issues