| |
| from __future__ import annotations |
|
|
| import argparse |
| import re |
| from pathlib import Path |
|
|
|
|
| PROJECT_ROOT = Path(__file__).resolve().parent |
| DEFAULT_MCP_ROOT = PROJECT_ROOT / "biomni_web" / "backend" / "data" / "mcp_generated" |
|
|
| SOURCE_RE = re.compile(r"SOURCE_SERVER\s*=\s*Path\((['\"])(.*?)\1\)") |
| SERVER_RE = re.compile(r"SERVER_NAME\s*=\s*(['\"])(.*?)\1") |
|
|
| SHIM_TEMPLATE = """#!/usr/bin/env python3 |
| from __future__ import annotations |
| |
| import ast |
| from pathlib import Path |
| |
| from mcp.server.fastmcp import FastMCP |
| |
| |
| SOURCE_SERVER = Path({source_server_path!r}) |
| LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name) |
| SERVER_NAME = {server_name!r} |
| |
| |
| class _ShimMCP: |
| @staticmethod |
| def tool(*args, **kwargs): |
| if args and callable(args[0]) and len(args) == 1 and not kwargs: |
| return args[0] |
| def _decorator(fn): |
| return fn |
| return _decorator |
| |
| |
| def _resolve_source_server(): |
| if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name: |
| return LOCAL_SERVER |
| return SOURCE_SERVER |
| |
| |
| def _load_functions(): |
| source_server = _resolve_source_server() |
| code = source_server.read_text(encoding="utf-8") |
| tree = ast.parse(code, filename=str(source_server)) |
| function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] |
| namespace = {{ |
| "__name__": "__mcp_source__", |
| "mcp": _ShimMCP(), |
| }} |
| exec(compile(code, str(source_server), "exec"), namespace, namespace) |
| loaded = [] |
| for name in function_names: |
| fn = namespace.get(name) |
| if callable(fn): |
| loaded.append(fn) |
| return loaded |
| |
| |
| mcp = FastMCP(SERVER_NAME) |
| for _fn in _load_functions(): |
| mcp.tool()(_fn) |
| |
| |
| if __name__ == "__main__": |
| mcp.run(transport="stdio") |
| """ |
|
|
|
|
| def extract_metadata(shim_path: Path) -> tuple[str, str] | None: |
| text = shim_path.read_text(encoding="utf-8") |
| source_match = SOURCE_RE.search(text) |
| server_match = SERVER_RE.search(text) |
| if not source_match or not server_match: |
| return None |
| return source_match.group(2), server_match.group(2) |
|
|
|
|
| def rewrite_shim(shim_path: Path, dry_run: bool = False) -> bool: |
| metadata = extract_metadata(shim_path) |
| if metadata is None: |
| return False |
| source_server_path, server_name = metadata |
| new_text = SHIM_TEMPLATE.format(source_server_path=source_server_path, server_name=server_name) |
| current = shim_path.read_text(encoding="utf-8") |
| if current == new_text: |
| return False |
| if not dry_run: |
| shim_path.write_text(new_text, encoding="utf-8") |
| return True |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser( |
| description="Rewrite generated MCP shim servers to prefer local patched raw servers." |
| ) |
| parser.add_argument( |
| "--mcp-root", |
| default=str(DEFAULT_MCP_ROOT), |
| help="Root directory containing mcp_* server dirs.", |
| ) |
| parser.add_argument("--dry-run", action="store_true") |
| args = parser.parse_args() |
|
|
| mcp_root = Path(args.mcp_root).resolve() |
| if not mcp_root.is_dir(): |
| raise SystemExit(f"MCP root does not exist or is not a directory: {mcp_root}") |
|
|
| scanned = 0 |
| changed = 0 |
| for shim_path in sorted(mcp_root.glob("mcp_*/app/*_shim_server.py")): |
| scanned += 1 |
| if rewrite_shim(shim_path, dry_run=args.dry_run): |
| changed += 1 |
|
|
| print(f"Scanned {scanned} shim files.") |
| print(f"Rewrote {changed} shim files.") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|