PixelWeaver v0.5.0 /server.src.pixelweaver.mcp_server
On this page

MCP tool server for PixelWeaver.

#server.src.pixelweaver.mcp_server

#server.src.pixelweaver.mcp_server

MCP tool server for PixelWeaver.

Exposes PixelWeaver operations as MCP tools so that LLMs (via Claude Code, Claude Desktop, etc.) can programmatically create and edit pixel art.

Runs as a separate process using stdio transport. Start with: pixelweaver mcp [--data-dir ./projects]

Architecture ------------ The MCP server does NOT own its own state. Before each tool execution it pulls the latest state from the collaboration server (HTTP on port 7779), runs the tool logic locally, then pushes the modified state back. The collab server broadcasts a full-state patch to all WebSocket clients so the frontend sees every MCP mutation in real time.

The collaboration server must be running for MCP to work. If it is unreachable the MCP server returns a clear error to the LLM.

#_ensure_initialized

python
def _ensure_initialized() -> MCPCommandRegistry

Lazily initialize the local state/registry on first tool call.

Unlike the old architecture, we do NOT load projects from disk here. State is synced from the collab server before each tool execution (see _sync_from_collab / _push_to_collab in the handler wrapper).

#_sync_from_collab

python
async def _sync_from_collab() -> None

Pull the latest state from the collab server into _state.

Raises CollabServerUnreachableError if the server cannot be reached.

#_push_to_collab

python
async def _push_to_collab() -> None

Push the current _state to the collab server (triggers WS broadcast).

Raises CollabServerUnreachableError if the server cannot be reached.

#mcp_lifespan

python
async def mcp_lifespan(server: FastMCP)

Initialize state when the MCP server starts.

#_format_result

python
def _format_result(result: dict[str, Any]) -> list[TextContent | ImageContent]

Convert a registry result dict into MCP content blocks.

Mutation results include a thumbnail as an ImageContent block. All results include a TextContent block with the JSON data.

#_error_result

python
def _error_result(message: str) -> CallToolResult

Build an isError CallToolResult carrying an error payload.

#_dispatch_tool_call

python
async def _dispatch_tool_call(tool_name: str, arguments: dict[str, Any]) -> CallToolResult

Execute one MCP tool through the pull -> execute -> push flow.

  1. Pull the latest state from the collab server.
  2. Execute the tool locally via the registry with the FLAT arguments.
  3. Push modified state back (mutating tools that succeeded).

A tool-level {"success": false} result maps to isError=True so clients see logical failures as MCP errors, not transport successes.

#_register_tool_handlers

python
def _register_tool_handlers(registry: MCPCommandRegistry) -> None

Register list_tools/call_tool on the low-level MCP server.

The handlers close over registry for the tool definitions but resolve the live registry inside _dispatch_tool_call so state stays consistent.

#init_mcp_tools

python
def init_mcp_tools() -> None

Register all tools/resources onto the MCP server.

Call this explicitly from the server startup path. Importing this module no longer has side effects; this keeps tests and tooling from paying the cost of initializing the MCP registry unless they actually need it.

#run_mcp_server

python
def run_mcp_server() -> None

Run the MCP server on stdio transport (blocking).

Search