Ryan Malloy 0e7942f510 docs: add Starlight documentation site
- Set up Astro + Starlight for documentation
- Create comprehensive docs covering:
  - Getting started (introduction, installation, quickstart)
  - Configuration (environment variables, vCenter connection)
  - Deployment (Docker, OAuth multi-user)
  - Reference (94 tools, RBAC permissions, architecture)
- VMware-inspired blue color scheme
- Custom logo and styling
- Search enabled via Pagefind
2026-01-16 12:39:00 -07:00

9.8 KiB

title description
Architecture Technical overview of mcvsphere internals

import { Aside } from '@astrojs/starlight/components';

System Architecture

┌─────────────────────────────────────────────────────────────┐
│                    MCP Client (Claude Code)                 │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           │ MCP Protocol
                           │ (stdio or streamable-http)
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                        mcvsphere                            │
│                                                             │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                     FastMCP                           │  │
│  │  - Protocol handling (JSON-RPC 2.0)                   │  │
│  │  - Tool registration and dispatch                     │  │
│  │  - Resource serving                                   │  │
│  │  - OAuth integration (OIDCProxy)                      │  │
│  └───────────────────────────────────────────────────────┘  │
│                           │                                 │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                  RBACMiddleware                       │  │
│  │  - Intercepts all tool calls                          │  │
│  │  - Extracts user from OAuth token                     │  │
│  │  - Enforces permission checks                         │  │
│  │  - Audit logging                                      │  │
│  └───────────────────────────────────────────────────────┘  │
│                           │                                 │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                  Tool Implementations                 │  │
│  │  - vm_lifecycle.py (7 tools)                          │  │
│  │  - power_ops.py (6 tools)                             │  │
│  │  - snapshots.py (5 tools)                             │  │
│  │  - guest_ops.py (7 tools)                             │  │
│  │  - ... (94 tools total)                               │  │
│  └───────────────────────────────────────────────────────┘  │
│                           │                                 │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                  Connection Manager                   │  │
│  │  - pyvmomi ServiceInstance                            │  │
│  │  - Connection pooling                                 │  │
│  │  - Reconnection handling                              │  │
│  └───────────────────────────────────────────────────────┘  │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           │ vSphere API (SOAP/REST)
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                  VMware vCenter / ESXi                      │
└─────────────────────────────────────────────────────────────┘

Source Layout

src/mcvsphere/
├── __init__.py        # Package entry point, version
├── server.py          # FastMCP server setup
├── config.py          # Pydantic Settings configuration
├── connection.py      # vSphere connection manager
├── auth.py            # OIDCProxy configuration
├── middleware.py      # RBAC middleware
├── permissions.py     # Permission levels and mappings
├── audit.py           # Audit logging
└── tools/             # MCP tool implementations
    ├── __init__.py
    ├── vm_lifecycle.py
    ├── power_ops.py
    ├── snapshots.py
    ├── guest_ops.py
    ├── serial_console.py
    ├── disk_mgmt.py
    ├── nic_mgmt.py
    ├── ovf_ops.py
    ├── host_mgmt.py
    ├── datastore_ops.py
    └── vcenter_ops.py

Key Components

FastMCP Server (server.py)

The core MCP server built on FastMCP:

from fastmcp import FastMCP

mcp = FastMCP(
    name="mcvsphere",
    instructions="VMware vSphere management server..."
)

# Tools are registered via decorators
@mcp.tool()
def list_vms() -> list[dict]:
    """List all virtual machines."""
    return connection.list_vms()

Configuration (config.py)

Pydantic Settings model for type-safe configuration:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    vcenter_host: str
    vcenter_user: str
    vcenter_password: str
    vcenter_insecure: bool = False
    mcp_transport: Literal["stdio", "streamable-http"] = "stdio"
    oauth_enabled: bool = False
    # ...

Connection Manager (connection.py)

Manages the pyvmomi ServiceInstance connection:

class VSphereConnection:
    def __init__(self, settings: Settings):
        self.si = SmartConnect(
            host=settings.vcenter_host,
            user=settings.vcenter_user,
            pwd=settings.vcenter_password,
            sslContext=self._get_ssl_context()
        )

    def list_vms(self) -> list[dict]:
        content = self.si.RetrieveContent()
        # ... pyvmomi operations

RBAC Middleware (middleware.py)

Intercepts all tool calls for permission checking:

from fastmcp import Middleware

class RBACMiddleware(Middleware):
    async def on_call_tool(self, context, call_next):
        # 1. Extract user from OAuth token
        claims = self._extract_user_from_context(context.fastmcp_context)
        groups = claims.get("groups", [])

        # 2. Check permission
        tool_name = context.message.name
        if not check_permission(tool_name, groups):
            raise PermissionDeniedError(...)

        # 3. Execute with audit logging
        result = await call_next(context)
        audit_log(tool_name, claims, result)
        return result

OAuth Configuration (auth.py)

Configures FastMCP's OIDCProxy for token validation:

from fastmcp.server.auth import OIDCProxy

def create_auth_provider(settings: Settings) -> OIDCProxy | None:
    if not settings.oauth_enabled:
        return None

    return OIDCProxy(
        issuer_url=settings.oauth_issuer_url,
        client_id=settings.oauth_client_id,
        client_secret=settings.oauth_client_secret,
        redirect_uri=f"{settings.oauth_base_url}/auth/callback",
        required_scopes=[],  # Authentik uses opaque tokens
    )

Data Flow

Tool Invocation (STDIO mode)

  1. Claude Code sends JSON-RPC request via stdin
  2. FastMCP parses and validates request
  3. Tool function executes
  4. pyvmomi calls vSphere API
  5. Result serialized and returned via stdout

Tool Invocation (HTTP + OAuth mode)

  1. Client sends HTTP POST with Bearer token
  2. OIDCProxy validates JWT via JWKS
  3. RBACMiddleware extracts claims, checks permissions
  4. Tool function executes
  5. Audit log written
  6. Result returned as HTTP response

Performance Considerations

Connection Reuse

A single pyvmomi connection is shared across all requests. This avoids the overhead of establishing new connections for each tool call.

Lazy Loading

vCenter inventory is fetched on-demand rather than cached. This ensures data freshness but means each tool call queries vCenter directly.

Resource Pooling

For high-volume deployments, consider running multiple mcvsphere instances behind a load balancer. Each instance maintains its own vCenter connection.

Security Model

STDIO Mode

  • No authentication (trusts the parent process)
  • Single-user by design
  • Credentials passed via environment variables

HTTP + OAuth Mode

  • JWT validation via OIDC provider
  • Group-based RBAC
  • Audit trail with user identity
  • Service account connection to vCenter (user identity tracked in audit logs, not vCenter permissions)