# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview `spark-executor-mcp` is a Python 3.12+ service that wraps Spark-related operations as a **Model Context Protocol (MCP)** server, exposed via HTTP through FastAPI. The MCP layer is built on top of [`fastapi-mcp`](https://github.com/tadata-org/fastapi_mcp), which auto-discovers FastAPI routes and exposes them as MCP tools. ## Common Commands The project uses `uv` for dependency management. Dependencies are pinned in `pyproject.toml` and `uv.lock`. A virtualenv already exists at `.venv/`. PyPI index is configured to the Tsinghua mirror in `pyproject.toml`. ```bash # Install/sync dependencies uv sync # Run the server (binds 0.0.0.0:8000) uv run main.py # Or activate the venv and run directly source .venv/bin/activate python main.py ``` Once running, the MCP endpoint is mounted at `http://localhost:8000/spark-executor-mcp`. The `spark_executor` app's own routes (e.g. `/health`) remain available at the root. There is currently no test suite, linter configuration, or CI config in the repository. ## Architecture The codebase is small and intentionally layered — the goal is to add new "tool" FastAPI sub-apps and have them be auto-exposed as MCP. ``` main.py # Root FastAPI app; lifespan wires in the MCP server common/ factory.py # init_mcp_server(app) -> FastApiMCP wrapper logging.py # loguru logger, level=DEBUG to stderr spark_executor/ __init__.py # Re-exports `app` server.py # Spark Executor FastAPI app (the MCP tool surface) ``` **How a request flows:** 1. `main.py` creates the root `FastAPI(title="Main App")` and registers an `asynccontextmanager` `lifespan`. 2. At startup, the lifespan calls `init_mcp_server(spark_executor_app)` (`common/factory.py`) which returns a `FastApiMCP` instance bound to the spark executor's FastAPI app. 3. That `FastApiMCP` is mounted onto the root app at `/spark-executor-mcp` via `mount_http(...)`. `fastapi-mcp` inspects the spark executor's routes and registers each one as an MCP tool. 4. To add new MCP tools, define new routes on the `app` in `spark_executor/server.py` (or create a new sub-package and mount it the same way in `main.py`'s lifespan) — they will be picked up automatically. **Key conventions:** - All modules include the file header `# coding=utf-8` plus a `@Time` / `@Author` docstring. Match this when adding new files. - `common/logging.py` configures a single process-wide `loguru` logger and removes the default handler. Import `from common.logging import logger` rather than creating new loggers. - `spark_executor/__init__.py` re-exports `app` so callers can `from spark_executor import app` — keep this re-export when adding to the package. - The `FastApiMCP` instance is created per-app in the lifespan; do not cache it at module import time.