pyro-mcp/src/pyro_mcp/server.py

72 lines
2.2 KiB
Python

"""MCP server exposing ephemeral VM lifecycle tools."""
from __future__ import annotations
from typing import Any
from mcp.server.fastmcp import FastMCP
from pyro_mcp.vm_manager import VmManager
def create_server(manager: VmManager | None = None) -> FastMCP:
"""Create and return a configured MCP server instance."""
vm_manager = manager or VmManager()
server = FastMCP(name="pyro_mcp")
@server.tool()
async def vm_list_profiles() -> list[dict[str, object]]:
"""List standard environment profiles and package highlights."""
return vm_manager.list_profiles()
@server.tool()
async def vm_create(
profile: str,
vcpu_count: int,
mem_mib: int,
ttl_seconds: int = 600,
) -> dict[str, Any]:
"""Create an ephemeral VM record with profile and resource sizing."""
return vm_manager.create_vm(
profile=profile,
vcpu_count=vcpu_count,
mem_mib=mem_mib,
ttl_seconds=ttl_seconds,
)
@server.tool()
async def vm_start(vm_id: str) -> dict[str, Any]:
"""Start a created VM and transition it into a command-ready state."""
return vm_manager.start_vm(vm_id)
@server.tool()
async def vm_exec(vm_id: str, command: str, timeout_seconds: int = 30) -> dict[str, Any]:
"""Run one non-interactive command and auto-clean the VM."""
return vm_manager.exec_vm(vm_id, command=command, timeout_seconds=timeout_seconds)
@server.tool()
async def vm_stop(vm_id: str) -> dict[str, Any]:
"""Stop a running VM."""
return vm_manager.stop_vm(vm_id)
@server.tool()
async def vm_delete(vm_id: str) -> dict[str, Any]:
"""Delete a VM and its runtime artifacts."""
return vm_manager.delete_vm(vm_id)
@server.tool()
async def vm_status(vm_id: str) -> dict[str, Any]:
"""Get the current state and metadata for a VM."""
return vm_manager.status_vm(vm_id)
@server.tool()
async def vm_reap_expired() -> dict[str, Any]:
"""Delete VMs whose TTL has expired."""
return vm_manager.reap_expired()
return server
def main() -> None:
"""Run the MCP server over stdio."""
create_server().run(transport="stdio")