#!/usr/bin/env python3 """把项目内 .cursor/mcp.json 同步到 Codex 的 MCP 配置。""" from __future__ import annotations import argparse import json import os import subprocess import sys from pathlib import Path def resolve_repo_root() -> Path: return Path(__file__).resolve().parents[3] def load_cursor_config(repo_root: Path) -> dict: config_path = repo_root / ".cursor" / "mcp.json" with config_path.open("r", encoding="utf-8") as f: return json.load(f) def apply_overrides(name: str, args: list[str], repo_root: Path) -> list[str]: new_args = list(args) if name == "filesystem": fs_root = os.environ.get("LQERP_MCP_FILESYSTEM_ROOT", str(repo_root)) new_args = [fs_root if arg == "." else arg for arg in new_args] if name == "my-sql-db": mysql_url = os.environ.get("LQERP_MCP_MYSQL_URL") if mysql_url: new_args = [mysql_url if arg.startswith("mysql://") else arg for arg in new_args] if name == "my-api-spec": openapi_spec = os.environ.get("LQERP_MCP_OPENAPI_SPEC_URL") api_base = os.environ.get("LQERP_MCP_OPENAPI_BASE_URL") for index, arg in enumerate(new_args): if openapi_spec and arg == "--openapi-spec" and index + 1 < len(new_args): new_args[index + 1] = openapi_spec if api_base and arg == "--api-base-url" and index + 1 < len(new_args): new_args[index + 1] = api_base return new_args def run_command(command: list[str], dry_run: bool) -> None: print("$", " ".join(command)) if not dry_run: subprocess.run(command, check=True) def sync_servers(repo_root: Path, dry_run: bool) -> None: config = load_cursor_config(repo_root) servers = config.get("mcpServers", {}) if not servers: raise SystemExit("未在 .cursor/mcp.json 中找到 mcpServers 配置。") for name, server in servers.items(): command = server.get("command") args = server.get("args", []) if not command: print(f"跳过 {name}: 缺少 command", file=sys.stderr) continue final_args = apply_overrides(name, args, repo_root) remove_cmd = ["codex", "mcp", "remove", name] add_cmd = ["codex", "mcp", "add", name, "--", command, *final_args] print(f"\n=== 同步 MCP: {name} ===") if dry_run: print("$", " ".join(remove_cmd), " # ignore failure if not exists") print("$", " ".join(add_cmd)) continue subprocess.run(remove_cmd, check=False) run_command(add_cmd, dry_run=False) def main() -> None: parser = argparse.ArgumentParser(description="把 .cursor/mcp.json 同步到 Codex MCP 配置") parser.add_argument("--dry-run", action="store_true", help="只打印将要执行的命令") args = parser.parse_args() repo_root = resolve_repo_root() sync_servers(repo_root, dry_run=args.dry_run) if __name__ == "__main__": main()