Genetic Optimization MCP Server
# 遺伝的最適化 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
Scored across 7 tools
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.
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.
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.
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.