# manimgl-mcp

A Model Context Protocol (MCP) server that gives AI assistants the ability to create mathematical animations programmatically. Features RAG-powered code generation, multi-agent pipelines, and audio narration.

## What This Does

This MCP server exposes **25 tools** that allow AI models to:

1. **Generate Animation Code** - Write scene definitions with RAG-powered assistance
2. **Render Videos** - Produce MP4, GIF, or PNG outputs at various quality levels
3. **Interactive Development** - Headless IPython sessions for iterative code testing
4. **Multi-Agent Pipeline** - Concept analysis → scene planning → code generation → review
5. **Audio Narration** - Generate TTS narration synced to videos

## Key Features

- **RAG-Powered Code Generation** - Semantic search over indexed ManimGL API and examples
- **Multi-Provider LLM** - Supports Gemini, Claude, DeepSeek, GPT-4o via litellm
- **Parameter Validation** - Validates API calls against indexed signatures
- **Self-Learning** - Stores error patterns and fixes for continuous improvement
- **8 Animation Templates** - Riemann sums, matrix transforms, Fourier series, etc.

## System Requirements

- **Python 3.10–3.13** — Python 3.14+ is **not** supported. `manimlib` depends on `pydub`, which requires the `audioop` standard library module removed in Python 3.13. Use a Python ≤ 3.13 environment.
- **FFmpeg** — for video encoding
- **LaTeX** — for mathematical notation (optional)

No display server is required. Interactive sessions are fully headless — they run inside a plain IPython REPL with manimlib pre-loaded, no OpenGL window is ever opened.

## Installation

### Recommended: install into a Python 3.13 venv

```bash
# Create a Python 3.13 virtual environment
python3.13 -m venv ~/.venv

# Install from PyPI
uv pip install manimgl-mcp --python ~/.venv/bin/python

# Or from source
git clone https://github.com/pranavgundu/manimgl-mcp.git
cd manimgl-mcp
uv pip install -e . --python ~/.venv/bin/python
```

### System dependencies

**macOS:**
```bash
brew install ffmpeg
brew install --cask mactex  # For LaTeX support
```

**Ubuntu/Debian:**
```bash
sudo apt install ffmpeg libpango1.0-dev libcairo2-dev
sudo apt install texlive-latex-base texlive-latex-extra  # For LaTeX
```

## Configuration

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

```json
{
  "mcpServers": {
    "manimgl-mcp": {
      "command": "/Users/YOUR_USERNAME/.venv/bin/manimgl-mcp"
    }
  }
}
```

> **Important:** Use the absolute path to the binary inside your Python 3.13 venv. Do **not** use `uv run` — it may resolve a Python 3.14+ interpreter that is missing `audioop`, causing every tool call to fail with `ModuleNotFoundError: No module named 'pyaudioop'`.

Restart Claude Desktop after editing this file.

### Claude Code CLI

```bash
# Register for this project only
claude mcp add manimgl-mcp /Users/YOUR_USERNAME/.venv/bin/manimgl-mcp

# Register globally (available in every project)
claude mcp add --scope global manimgl-mcp /Users/YOUR_USERNAME/.venv/bin/manimgl-mcp
```

### Other MCP Clients

```json
{
  "command": "/path/to/python3.13-venv/bin/manimgl-mcp"
}
```

## Tools Reference

### Scene Management

| Tool | Purpose |
|------|---------|
| `write_scene` | Write animation code to a Python file |
| `render_scene` | Render a scene to video/image |
| `list_scenes` | Find all scene classes in a file |
| `get_scene_preview` | Capture the final frame as an image |

### Interactive Sessions

Interactive sessions start a **headless IPython REPL** with `from manimlib import *` pre-loaded. All manimlib classes (`Circle`, `Transform`, `VGroup`, …) are immediately available. No display or window is needed — sessions work on macOS, Linux, and headless servers alike.

| Tool | Purpose |
|------|---------|
| `start_interactive_session` | Launch a headless IPython + manimlib session |
| `run_in_session` | Execute code in the running session |
| `get_scene_state` | List Mobject variables defined in the session |
| `get_session_history` | Review all commands executed |
| `list_sessions` | Show all active sessions |
| `end_session` | Close a session |

> **Note:** `capture_screenshot` is not available in headless sessions — there is no live OpenGL scene to snapshot. To preview your work, use `write_scene` + `get_scene_preview` to render a PNG of the final frame.

### RAG-Powered Search

Run `index_manimgl` once after installation before using these tools.

| Tool | Purpose |
|------|---------|
| `index_manimgl` | Build/rebuild the RAG index from ManimGL source |
| `search_examples` | Semantic search for scene examples |
| `search_api` | Search API signatures by functionality |
| `search_patterns` | Find animation pattern templates |
| `validate_api_call` | Validate parameters against signatures |
| `get_rag_stats` | Get index statistics |

### Multi-Agent Code Generation

| Tool | Purpose |
|------|---------|
| `generate_animation` | Full pipeline: concept → plan → code → review |

### Audio Narration

| Tool | Purpose |
|------|---------|
| `generate_narration` | Generate TTS audio from text |
| `add_narration_to_video` | Sync audio to video |

### Self-Learning

| Tool | Purpose |
|------|---------|
| `store_error_fix` | Store error pattern and fix |
| `get_similar_errors` | Find similar errors and fixes |

### Documentation

| Tool | Purpose |
|------|---------|
| `get_manim_help` | Get help on specific topics |
| `get_example_code` | Get working code templates |
| `get_full_documentation` | Get the complete API reference |

## Interactive Sessions Deep Dive

### Starting a Session

```python
# AI calls start_interactive_session
{}
# Returns: {"session_id": "abc12345", "success": true}
```

No window opens. The session is a plain Python process — safe to run in any environment.

### Executing Commands

```python
# Create objects
run_in_session(session_id, "square = Square(color=RED)")

# Verify types
run_in_session(session_id, "str(type(square))")
# => "'<class 'manimlib.mobject.geometry.Square'>'"

# Animate (builds the animation object — does not render)
run_in_session(session_id, "anim = ReplacementTransform(square.copy(), Circle())")

# Multi-line input is fully supported
run_in_session(session_id, "a = Circle()\nb = Square()\nc = Triangle()")

# Complex multiline
run_in_session(session_id, """
row = VGroup(Circle(), Square(), Triangle()).arrange(RIGHT, buff=0.5)
print("width:", row.get_width())
""")
```

### Workflow: iterate in session, then render

```
1. start_interactive_session  — fast headless startup (~1 s)
2. run_in_session (loop)      — prototype objects, test transforms, check types
3. write_scene                — write the final scene class to a .py file
4. render_scene / get_scene_preview  — produce MP4 / PNG
5. end_session
```

### Available Manimlib Names in Sessions

Everything exported by `from manimlib import *` is available, including:

| Category | Examples |
|----------|---------|
| Shapes | `Circle`, `Square`, `Triangle`, `RegularPolygon`, `Dot`, `Arrow`, `Line` |
| Text | `Text`, `Tex`, `MathTex` |
| Groups | `VGroup`, `Group` |
| Animations | `Write`, `FadeIn`, `FadeOut`, `ReplacementTransform`, `Transform`, `ShowCreation` |
| Helpers | `ValueTracker`, `always_redraw`, `Rotating` |
| Constants | `UP`, `DOWN`, `LEFT`, `RIGHT`, `ORIGIN`, `TAU`, `PI` |
| Colors | `RED`, `BLUE`, `GREEN`, `YELLOW`, `PURPLE`, `TEAL`, `GOLD`, … |
| Math | `numpy` is importable as `np` |

### Session State Inspection

```python
get_scene_state(session_id)
# Returns: {"mobject_count": 3, "mobject_vars": [["circle", "Circle"], ...]}
```

## First-Run Setup: Build the RAG Index

After installation, run `index_manimgl` once to enable semantic search:

```
Use index_manimgl to build the search index
```

This crawls the ManimGL source and indexes ~460 API signatures, scene examples, and animation patterns into `~/.manimgl-mcp/rag.db`. The index persists across server restarts.

## Quality Settings

| Quality | Resolution | Use Case |
|---------|------------|----------|
| `low` | 480p | Quick previews |
| `medium` | 720p | Development |
| `hd` | 1080p | Production |
| `4k` | 2160p | High-quality output |

## Help Topics

Use `get_manim_help` with: `scene`, `mobjects`, `animations`, `transforms`, `text`, `graphs`, `3d`, `interactive`, `colors`, `coordinates`.

## Example Code Templates

Use `get_example_code` with: `basic_shapes`, `transform_demo`, `text_latex`, `graph_animation`, `value_tracker`, `3d_demo`, `updater_pattern`, `interactive_session`.

Legacy aliases still supported: `basic_circle`, `shape_transform`, `text_animation`, `graph_plot`, `3d_scene`.

## Development

```bash
git clone https://github.com/pranavgundu/manimgl-mcp.git
cd manimgl-mcp
uv sync --dev  # requires Python ≤ 3.13

uv run pytest
uv run ruff check src/ tests/
uv run ruff format src/ tests/
uv run mypy src/manimgl_mcp
```

## Architecture

```
manimgl-mcp/
├── src/manimgl_mcp/
│   ├── server.py          # MCP server with 25 tools
│   ├── scene_manager.py   # File I/O, subprocess rendering (5 min timeout)
│   ├── interactive.py     # pexpect-based headless IPython session manager
│   ├── docs.py            # Static help text and code templates
│   ├── rag/               # RAG-powered search
│   │   ├── store.py       # LanceDB + sentence-transformers vector store
│   │   ├── indexer.py     # ManimGL source indexer
│   │   └── search.py      # Semantic search functions
│   ├── llm/               # Multi-provider LLM
│   │   ├── providers.py   # litellm integration
│   │   └── agents.py      # Multi-agent pipeline
│   └── audio/             # Audio narration
│       ├── tts.py         # edge-tts integration
│       └── sync.py        # ffmpeg audio-video sync
├── tests/
└── references/manim/      # ManimGL source submodule (RAG corpus)
```

## Environment Variables

For multi-agent features (`generate_animation`), set one of:
- `GOOGLE_API_KEY` or `GEMINI_API_KEY` — Google Gemini
- `ANTHROPIC_API_KEY` — Anthropic Claude
- `DEEPSEEK_API_KEY` — DeepSeek
- `OPENAI_API_KEY` — OpenAI GPT-4o

## Troubleshooting

**`No module named 'pyaudioop'` or `No module named 'audioop'`**
You are running Python 3.14+. Switch to Python ≤ 3.13 and reinstall. See [Installation](#installation).

**`render_scene` fails with `manimgl not found`**
The `manimgl` binary from your Python 3.13 venv must be reachable. Ensure the server is launched from that venv (see [Configuration](#configuration)).

**`start_interactive_session` times out**
IPython failed to start. Check that the venv at the server's `command` path contains both `manimgl` and a working Python interpreter. Run `~/.venv/bin/python -m IPython --version` to verify.

**`index_manimgl` returns `No module named 'pyaudioop'`**
Same root cause as the first issue — the server is running under Python 3.14+. Fix the launch command to point at the Python 3.13 venv binary.

**RAG search returns "not indexed"**
Run `index_manimgl` first. The index persists at `~/.manimgl-mcp/rag.db` between restarts.

## License

MIT License - see LICENSE file.

## Acknowledgments

Built on the [Model Context Protocol](https://modelcontextprotocol.io/) specification.
