llvm / llvm/eudsl

[eudsl-llvmpy] Add an MCP server (persistent LLVM Python REPL), modeled on mlir-python-mcp

Open
#616 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.