Pandas Excel Analytics MCP
README.md
# Pandas Excel Analytics MCP
A deterministic Model Context Protocol (MCP) server exposing Pandas, NumPy,
Excel/openpyxl, and automated EDA operations over uploaded tabular datasets.
This server does **not** contain an LLM, embeddings, RAG, or Langflow/OpenRouter
credentials. It is purely the data-execution layer, meant to be called by an
MCP client (e.g. Langflow's MCP Tool node) driven by an LLM.
Built on the current stable MCP Python SDK (`mcp` v2.x), where the server
class is `mcp.server.mcpserver.MCPServer` — the successor to the
pre-2.0 `mcp.server.fastmcp.FastMCP` name used in older tutorials. The public
API (`.tool()`, `.streamable_http_app()`) is unchanged.
## Architecture

## Install
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
```
## Run locally
```bash
uvicorn server:app --reload --host 127.0.0.1 --port 8000
```
- MCP endpoint: `http://127.0.0.1:8000/mcp`
- Health check: `http://127.0.0.1:8000/health`
## Test with MCP Inspector
```bash
npx @modelcontextprotocol/inspector
```
Then connect to `http://127.0.0.1:8000/mcp` using the "Streamable HTTP"
transport in the Inspector UI, and browse/call the 27 registered tools.
## Run the test suite
```bash
pytest tests/ -v
```
## Environment variables
| Variable | Purpose | Required |
|---|---|---|
| `PORT` | Port to bind (set automatically by Render) | No (default 8000) |
| `MCP_API_TOKEN` | Bearer token for authenticated requests | Recommended in production |
| `MCP_REQUIRE_AUTH` | Force auth even without inspecting `MCP_API_TOKEN` | No |
| `MCP_ALLOWED_HOSTS` | Comma-separated hostnames this server is reachable at, e.g. `your-service.onrender.com` | **Yes, in production** |
| `MCP_MAX_FILE_SIZE_MB` | Upload size limit (default 50) | No |
| `MCP_MAX_ROWS` / `MCP_MAX_COLUMNS` | Dataset shape limits | No |
| `MCP_MAX_EXCEL_SHEETS` | Excel workbook sheet limit | No |
| `MCP_MAX_OUTPUT_ROWS` | Max rows returned per tool call | No |
`OPENROUTER_API_KEY` and any LLM credentials are intentionally **not**
consumed by this server — keep them in Langflow.
## Deploy to Render
1. Push this repository to GitHub.
2. In Render, "New +" → "Blueprint", point it at the repo (uses `render.yaml`).
3. Render will set `MCP_API_TOKEN` automatically (via `generateValue: true`);
copy it from the Render dashboard's Environment tab for your MCP client.
4. Set `MCP_ALLOWED_HOSTS` to your actual `*.onrender.com` hostname (the
Blueprint pre-fills a guess — update it once Render assigns the final
service name).
5. Deploy. Render runs `pip install -r requirements.txt` then
`uvicorn server:app --host 0.0.0.0 --port $PORT`.
6. Verify: `curl https://YOUR-SERVICE.onrender.com/health` → `{"status":"ok"}`.
Production MCP URL:
```
https://YOUR-SERVICE.onrender.com/mcp
```
## Security notes
- No `eval`/`exec`/shell execution/arbitrary imports anywhere in the codebase.
- Every dataset is addressed by an opaque `dataset_id` — callers never supply
filesystem paths.
- Filenames are sanitised and path-joined under a fixed storage root
(`utils/security.py::safe_join`) — path traversal is structurally impossible.
- `TransportSecuritySettings` host allowlist is always configured; the
SDK's default localhost-only protection is never disabled.
- Bearer-token auth is opt-in via `MCP_API_TOKEN`; when unset the server
runs unauthenticated (fine for local dev, **not** for a public Render URL).
## Next step: connecting Langflow
1. In Langflow, add an **MCP Tools** / **MCP Client** component.
2. Point it at `https://YOUR-SERVICE.onrender.com/mcp` using the Streamable
HTTP transport, and add header `Authorization: Bearer <MCP_API_TOKEN>`.
3. Set the component to "Tool Mode" so all 27 tools populate as a Toolset.
4. Wire that Toolset into your Base LLM Agent (OpenRouter) node.
5. Test with a prompt like: *"Upload sales.csv and tell me which region has
the highest profit."*
Langflow + OpenRouter + embeddings/RAG are deliberately out of scope for this
backend and should be added only after the above is verified working.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues