CSV MCP Server
by cledupe
README.md
# CSV MCP Server
A Python MCP (Model Context Protocol) server that enables AI assistants to answer natural language questions about company processes and operational data stored in CSV files. Built with [FastMCP](https://github.com/jlowin/fastmcp) and [Polars](https://github.com/pola-rs/polars) for efficient CSV processing with server-side filter expressions.
## Technologies
| Technology | Purpose |
|---|---|
| **Python 3.10+** | Runtime |
| **[FastMCP](https://github.com/jlowin/fastmcp)** | MCP server framework |
| **[Polars](https://github.com/pola-rs/polars)** | High-performance CSV loading and filtering |
| **[Docker](https://www.docker.com/)** | Containerized deployment |
| **[pytest](https://docs.pytest.org/)** | Testing framework |
## Available Tools
| Tool | Description |
|---|---|
| `list_csv_files` | Lists all CSV files in the configured directory |
| `get_csv_schema` | Shows column names, data types, and sample rows for a CSV file |
| `ask_csv_question` | Queries a CSV file using a Polars filter expression |
## Quick Start
### Without Docker
1. **Install dependencies:**
```bash
pip install mcp polars
```
2. **Place your CSV files** in the `./data/` directory (or set `CSV_DIR` to a custom path).
3. **Run the server:**
```bash
python server.py
```
The server starts in `stdio` mode by default, which is what AI clients like Claude Desktop and Cursor expect.
### With Docker
1. **Place your CSV files** in the `./data/` directory.
2. **Build and start the container:**
```bash
docker compose up -d
```
The server runs in HTTP mode on `http://localhost:8000/mcp`.
3. **Verify connectivity:**
```bash
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}},"id":1}'
```
## Configuration
### Environment Variables
| Variable | Default | Description |
|---|---|---|
| `CSV_DIR` | `./data` | Path to the directory containing CSV files |
| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
| `FASTMCP_HOST` | `127.0.0.1` | Host address for HTTP mode |
| `FASTMCP_PORT` | `8000` | Port for HTTP mode |
## AI Client Integration
### OpenCode
Add to your `opencode.json`:
**Local (stdio):**
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"csv-mcp": {
"type": "local",
"command": ["python", "server.py"],
"environment": {
"CSV_DIR": "./data"
},
"enabled": true
}
}
}
```
**Docker (HTTP):**
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"csv-mcp": {
"type": "remote",
"url": "http://localhost:8000/mcp",
"enabled": true
}
}
}
```
### Claude Desktop / Cursor
For `stdio` mode:
```json
{
"mcpServers": {
"csv-mcp": {
"command": "python",
"args": ["/path/to/server.py"],
"env": {
"CSV_DIR": "/path/to/data"
}
}
}
}
```
For Docker (HTTP):
```json
{
"mcpServers": {
"csv-mcp": {
"url": "http://localhost:8000/mcp"
}
}
}
```
## Usage Examples
Once connected, ask your AI assistant questions like:
- "List all available CSV files"
- "Show the schema of processes.csv"
- "Find all rows where status equals 'active' in processes.csv"
The `ask_csv_question` tool accepts Polars filter expressions:
| Expression | Description |
|---|---|
| `pl.col("status") == "active"` | Filter by exact match |
| `pl.col("prazo") > 10` | Filter by numeric comparison |
| `pl.col("processo").str.contains("aprov")` | Filter by substring match |
## Testing
```bash
# Run all tests
python -m pytest tests/ -v
# Run with coverage
COVERAGE_FILE=/tmp/.coverage python -m pytest tests/ --cov=server --cov-report=term-missing
```
## Security
- **Path traversal protection**: All file paths are resolved and validated to stay within `CSV_DIR`
- **Expression sanitization**: Filter expressions are checked against dangerous patterns (`import`, `exec`, `eval`, etc.) before evaluation
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues