"""将 Cursor ``mcpServers`` JSON 写入本地 SQLite(与管理台 Install 等价)。 库表被清空、换库或新环境时:在项目根执行 python -m runtime.operations.scripts.seed_mcp_registry 可选:python -m runtime.operations.scripts.seed_mcp_registry path/to/mcp.json 随后在各 MCP 上点 Health → Sync Tools;密钥放在 oclaw/_local/mcp_local.env。 """ from __future__ import annotations import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(ROOT)) from svc.config.paths import PROJECT_ROOT # noqa: E402 from svc.persistence.assistant_store import get_assistant_store # noqa: E402 from runtime.tools.mcp.cursor_config import parse_cursor_mcp_document # noqa: E402 from runtime.tools.mcp.installer import install_mcp_server # noqa: E402 from runtime.tools.mcp.manifest import McpServerManifest # noqa: E402 from runtime.operations.mcp_registry_export import persist_mcp_migrated_file # noqa: E402 def _subst_repo(path_str: str) -> str: s = str(path_str or "").strip() if s.startswith("__REPO_ROOT__/"): return str((PROJECT_ROOT / s.replace("__REPO_ROOT__/", "", 1)).resolve()) return s def main(argv: list[str]) -> int: seed_path = Path(argv[1]).resolve() if len(argv) > 1 else (ROOT / "data" / "mcp_registry.seed.json") if not seed_path.is_file(): print(f"seed file not found: {seed_path}", file=sys.stderr) return 2 raw = json.loads(seed_path.read_text(encoding="utf-8")) try: items = parse_cursor_mcp_document(raw) except ValueError as exc: print(f"invalid Cursor mcpServers document: {exc}", file=sys.stderr) return 2 store = get_assistant_store() ok_n = 0 for payload in items: entry_args = [_subst_repo(x) for x in (payload.get("entry_args") or []) if str(x).strip()] dry_run = bool(payload.get("dry_run", False)) manifest = McpServerManifest( server_id=str(payload.get("server_id") or ""), source_type=str(payload.get("source_type") or "local"), source_ref=str(payload.get("source_ref") or ""), version=str(payload.get("version") or "").strip(), entry_command=str(payload.get("entry_command") or "").strip(), entry_args=entry_args, env_schema=payload.get("env_schema") if isinstance(payload.get("env_schema"), dict) else {}, permissions=[str(x) for x in (payload.get("required_permissions") or [])], risk_level=str(payload.get("risk_level") or "high"), enabled=bool(payload.get("enabled", True)), timeout_s=float(payload.get("timeout_s") or 30.0), ) inst = install_mcp_server(manifest, dry_run=dry_run) store.upsert_mcp_server( server_id=manifest.server_id, source_type=manifest.source_type, source_ref=manifest.source_ref, version=manifest.version, entry_command=manifest.entry_command, entry_args=manifest.entry_args, env_schema=manifest.env_schema, required_permissions=manifest.permissions, risk_level=manifest.risk_level, timeout_s=manifest.timeout_s, enabled=manifest.enabled if inst.ok else False, ) store.add_mcp_installation_log( server_id=manifest.server_id, status="ok" if inst.ok else "error", error_code=inst.error_code, detail={"error": inst.error, **(inst.details or {}), "seed": True}, install_command=inst.install_command, ) print( f"{manifest.server_id}: install_ok={inst.ok} " f"enabled={manifest.enabled if inst.ok else False} cmd={inst.install_command[:120]!r}" ) if inst.ok: ok_n += 1 persist_mcp_migrated_file(store) print(f"done: {ok_n}/{len(items)} install steps succeeded; rows upserted for all valid entries.") return 0 if __name__ == "__main__": raise SystemExit(main(sys.argv))