[eudsl-llvmpy] Add an MCP server (persistent LLVM Python REPL), modeled on mlir-python-mcp
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 79
- Forks
- 14
- Avg merge
- 11h 43m
- Merged PRs (30d)
- 72
Description
## Summary
Add an MCP (Model Context Protocol) server **inside the `eudsl-llvmpy` package** (not a separate distribution), modeled on the existing `projects/mlir-python-mcp/`. It would give an LLM a **persistent LLVM Python REPL** so it can manipulate LLVM IR at the API level (build/inspect/transform via the bindings, run pass pipelines, JIT-execute) instead of doing textual `.ll` edits. This mirrors what `mlir-python-mcp` does for MLIR, reusing the same server shape but targeting the `llvm.*` API surface.
## Packaging (in-package, not a sibling project)
The server ships **as a submodule of the existing `llvm` package**, alongside `ast/` and `dsl/`:
- Code under `projects/eudsl-llvmpy/src/llvm/mcp/` (e.g. `server.py`, `session.py`, `helpers.py`), importable as `llvm.mcp`.
- Console script wired in `eudsl-llvmpy`'s own `pyproject.toml`, e.g.:
```toml
[project.scripts]
llvmpy-mcp = "llvm.mcp:main"
```
- The `mcp` runtime dependency is added as an **optional extra** so the core bindings stay dependency-light:
```toml
[project.optional-dependencies]
mcp = ["mcp>=1.1.2,<2"]
```
installed via `pip install eudsl-llvmpy[mcp]`. (Reuse the same `mcp<2` cap as `mlir-python-mcp` until the low-level decorator API is ported.)
- `.mcp.json` points at the `llvmpy-mcp` script; no separate wheel to publish — it rides the `eudsl-llvmpy` release.
## Motivation
- Textual IR edits are brittle; an API-level REPL lets the model construct/mutate IR with the actual bindings and immediately verify/execute it.
- `eudsl-llvmpy` already exposes everything a useful server needs: `llvm.ir` (Context/Module/parse_assembly/Value tree), `llvm.passmanager` (`run_passes`, `run_default_pipeline`, `run_python_pass_on_module/function`, `register_python_pass`), `llvm.jit` (`LLJIT`), `llvm.types`, `llvm.instructions`, `llvm.intrinsics`, and `llvm.mir`. The MCP server is mostly glue over these, so it belongs in the package rather than as an external consumer.
- It also becomes an integration exercise for the bindings (the object-level mutation APIs, the Python-pass registration, and JIT round-trips all get driven end to end).
## Proposed tools (mapping mlir-python-mcp -> llvmpy)
**Core REPL**
- `execute_python` — run arbitrary Python in a persistent, pre-loaded namespace.
- `list_variables`, `new_session` / `list_sessions` / `delete_session` — named sessions, each owning its own `llvm.ir.Context`.
**Pipeline workflow**
- `run_pipeline` / `chain_pipeline` — set IR then apply a textual pass pipeline via `llvm.passmanager.run_passes` (and `run_default_pipeline` for `-On`); incremental lowering.
- `get_current_ir`, `rewind`, `history` (with diffs), `reset`.
- `list_passes` — enumerate available pass names (from the PassBuilder registry).
- **llvmpy-specific:** `register_python_pass` + run it by name — a genuinely differentiating feature vs. MLIR (drive a Python-authored pass from the session).
**Discovery**
- `list_ir_apis` (classes/functions in `llvm.ir`), `list_type_apis` (`llvm.types`), `list_instruction_builders` (`llvm.instructions`), `list_intrinsics` (`llvm.intrinsics`).
**IR API tools**
- `parse_assembly` -> `ir.Module`, `get_module_asm`, `load_ll_file` / `save_ll_file`.
- `walk_instructions` (module -> functions -> blocks -> instructions, with an opcode-name filter), `get_function_info`, `get_instruction_info`.
- `verify_module`, `clone_module`.
- Object-level mutation surfaced as tools (already bound in #608): `set_operand`, `replace_all_uses`, `erase_instruction` (poison-safe), `move_before` / `insert_before` / `insert_after`, `split_basic_block`.
**Execution (llvmpy-specific)**
- `jit_execute` — build an `llvm.jit.LLJIT`, add the current module, look up a symbol, and call it (the example passes already show the ctypes round-trip). MLIR's server has no direct analogue; this is a strong reason the LLVM REPL is useful.
**MIR (optional, later)**
- `llvm.mir` tools (build/inspect MachineFunctions) once the core server lands.
## Pre-loaded namespace
`ir`, `passmanager`, `jit`, `types`, `instructions`, `intrinsics`, a current `ctx`, plus helpers (`new_module`, `parse_assembly`, `run_passes`, `find_instructions`, `print_function`, `get_module_asm`, ...). Same convenience shape as the MLIR server's namespace.
## Scope / non-goals
- Start with IR + passes + JIT; defer MIR tools and any web UI.
- Reuse `mlir-python-mcp`'s session/history/rewind design rather than reinventing it.
- Keep `mcp` an optional extra so importing `llvm` (the bindings) never pulls in the MCP stack.
- Same `mcp<2` cap until/unless the low-level decorator API is ported (mlir-python-mcp has the same note).
## References
- `projects/mlir-python-mcp/` — the server to mirror (README lists the full tool set; `server.py`, `session.py`, `helpers.py`).
- `projects/eudsl-llvmpy/src/llvm/` — the package the server lives in and the API surface it wraps (`ir.py`, `passmanager.py`, `jit.py`, `types.py`, `instructions.py`, `intrinsics.py`, `mir.py`); sits next to the existing `ast/` and `dsl/` submodules.
- Object-level mutation bindings: PR #608. Python passes / named registration: #602/#604/#605.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading projects/mlir-python-mcp/server.py, session.py, helpers.py and the eudsl-llvmpy package files under projects/eudsl-llvmpy/src/llvm/. Review the package's pyproject.toml and the referenced LLVM APIs in ir.py, passmanager.py, and jit.py. Done means an in-package llvm.mcp server with the optional mcp dependency, console script, persistent sessions, core IR/pass/JIT workflows, and matching configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100