oclaw/runtime/operations/scripts/seed_mcp_registry.py
oliver f6f129931f Ship Cursor-only MCP admin and modular Admin/Chat UI.
Plugins/Skills install and edit via mcpServers JSON, with clearer row actions, soft reloads, and instant loading placeholders; also drop MCP market and harden related scheduler/logging/exec guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 19:38:26 +08:00

96 lines
4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""将 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))