Introducing MCP for Fenics

Hi!
This all started because I wanted to be able to talk to Claude about a problem set and it evolved from there. So introducing a MCP for Dolfinx! I also made a Claude CoWork plugin so you can install that have access to specialized skills and agents to design (or have help troubleshoot) what ever you would like. I personally have liked using Claude CoWork as it will do the full workflow and create a report in word or PDF, but since it is set up as a MCP you can use whatever AI assistant you want! So many choices. If you have an issue or spot an error submit it on GitHub and I will do my best to answer.

dolfinx-mcp

ekstanley/ccFenics-plugin (on GitHub)

Talk to your PDE solver. An MCP server that gives AI assistants direct access to the FEniCSx/DOLFINx finite element framework. Describe a PDE in natural language and the tools handle the rest - mesh generation, function spaces, assembly, solving, and post-processing - all inside a sandboxed Docker container.

38
MCP Tools
37
FEM Skills
514
Tests
9
Invariants
20
Lean 4 Theorems
              MCP Client                              Docker Container
         (Claude, Cursor, ...)                      (dolfinx/dolfinx:stable)
        +---------------------+                    +-----------------------+
        |                     |    JSON-RPC         |  FastMCP Server       |
        |  "Solve the 3D      | ── stdio/http ───> |    38 Tool Handlers   |
        |   Poisson equation" |                     |    SessionState       |
        |                     | <─────────────────  |    /workspace output  |
        +---------------------+                    +-----------------------+

Quick Start

1. Build

git clone https://github.com/ekstanley/ccFenics-plugin.git
cd ccFenics-plugin
docker build -t dolfinx-mcp .

2. Configure Your MCP Client

Add to your client configuration (Claude Desktop, Cursor, VS Code, etc.).
Set /path/to/workspace to the directory for simulation output (VTK, XDMF):

{
  "mcpServers": {
    "dolfinx": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i", "--network", "none",
        "-v", "/path/to/workspace:/workspace",
        "dolfinx-mcp"
      ]
    }
  }
}
Claude Code — zero-config setup

This repo includes .mcp.json for automatic MCP server discovery:

  1. docker build -t dolfinx-mcp .
  2. claude (from the repo root)
  3. Start asking FEM questions — the server auto-connects

For the full FEM-aware experience (37 skills, 6 agents, 6 commands):

claude --plugin-dir ./ccfenics
Claude Cowork (Desktop App)
  1. Build the Docker image: docker build -t dolfinx-mcp .
  2. Zip the dolfinx-assistant/ folder
  3. In Claude Desktop, go to Customize > Add Plugin > upload the zip

The 38 MCP tools become available in your Cowork session.

3. Use

Ask your AI assistant to solve a PDE:

“Create a 16x16 unit square mesh and solve the Poisson equation
with f = 2pi^2 sin(pi x) sin(pi y), then compute the L2 error.”


Example: 3D Poisson on Unit Cube

A Jupyter notebook demonstrating a full 3D workflow is at
examples/3d_poisson_demo.ipynb.

Problem: -\nabla^2 u = 3\pi^2 \sin(\pi x)\sin(\pi y)\sin(\pi z) on [0,1]^3, u=0 on boundary.

Metric Result
Mesh 16x16x16 tetrahedra (24,576 cells, 4,913 vertices)
Space P2 Lagrange (35,937 DOFs)
Solver CG + Hypre AMG
max(u_h) 1.000056 (expected 1.0)
L2 error 1.21e-05
H1 error 1.15e-03

Supported Problems

Category PDE Types
Elliptic Poisson, Helmholtz, mixed Poisson (RT elements), singular Poisson (nullspace), complex-valued
Parabolic Heat equation, Cahn-Hilliard, Allen-Cahn
Flow Stokes (Taylor-Hood), Navier-Stokes (IPCS)
Solid Mechanics Linear elasticity, hyperelasticity (neo-Hookean), membrane deflection
Electromagnetics H(curl) formulations with Nedelec edge elements
Special Biharmonic (C/IP-DG), discontinuous Galerkin, eigenvalue (SLEPc), axisymmetric

Boundary conditions: Dirichlet, Neumann, Robin, Nitsche (weak), component-wise, multi-region.
Elements: Lagrange (P1-P5), DG, Nedelec, Raviart-Thomas, BDM, Crouzeix-Raviart, mixed.
Solvers: Direct (LU, MUMPS), iterative (CG, GMRES, BiCGSTAB) with preconditioners (ILU, Hypre AMG, Jacobi), Newton (SNES), time-stepping (Euler, Crank-Nicolson).


Tools (38)

Mesh Operations (9)

Tool Description
create_unit_square Unit square mesh with triangular or quadrilateral elements
create_mesh Rectangle or box meshes with custom dimensions
create_custom_mesh Import mesh from Gmsh (.msh) file
get_mesh_info Inspect mesh properties (cells, vertices, bounding box)
compute_mesh_quality Mesh quality metrics (aspect ratio, volume)
mark_boundaries Tag boundary facets using coordinate expressions
manage_mesh_tags Create and manage cell/facet region markers
refine_mesh Uniformly refine an existing mesh
create_submesh Extract submesh from tagged regions

Function Spaces (2)

Tool Description
create_function_space Lagrange, DG, Nedelec, RT, BDM, or CR elements (degree 1-5)
create_mixed_space Mixed function space from component subspaces

Problem Definition (3)

Tool Description
set_material_properties Define material coefficients and source terms
define_variational_form Bilinear and linear forms via UFL expressions
apply_boundary_condition Dirichlet boundary conditions (value + locator)

Solvers (5)

Tool Description
solve Direct (LU, MUMPS) or iterative (CG, GMRES) with preconditioners
solve_time_dependent Time stepping: backward/forward Euler, Crank-Nicolson
solve_nonlinear Newton solver (SNES) for nonlinear PDEs
solve_eigenvalue Generalized eigenvalue problems via SLEPc
get_solver_diagnostics Convergence info, iterations, residual norms

Post-processing (6)

Tool Description
compute_error L2 or H1 error against an exact solution
evaluate_solution Evaluate solution at specified coordinates
query_point_values Point queries with geometric cell info
compute_functionals Integrate UFL expressions over the domain
export_solution Export to XDMF or VTK format
plot_solution Contour or warp plots (PNG via PyVista)

Interpolation (4)

Tool Description
create_function Create a function in a space, optionally initialized with an expression
interpolate Interpolate UFL expression into a function space
project L2-project an expression onto a function space
create_discrete_operator Build a discrete operator matrix

Session Management (9)

Tool Description
get_session_state List all registered meshes, spaces, functions, solutions
reset_session Clear all session state
run_custom_code Execute Python code with persistent namespace across calls
assemble Assemble UFL forms into scalars, vectors, or matrices
remove_object Remove an object with cascade deletion of dependents
read_workspace_file Read files from /workspace/ as base64 (images) or text (VTK, CSV)
list_workspace_files List files in /workspace/ matching glob patterns
bundle_workspace_files Package workspace files into a ZIP archive
generate_report Generate an HTML simulation report with plots and diagnostics

Claude Code Plugin

The ccfenics/ directory adds FEM domain intelligence on top of the 38 MCP tools.
Load it with claude --plugin-dir ./ccfenics.

Agents (6)

Agent What it does
fem-solver End-to-end PDE solve pipeline (mesh to post-processing)
convergence-study Automated mesh refinement with convergence rate fitting
nonlinear-solver Newton method with load stepping and convergence diagnostics
time-dependent-solver Transient PDE workflows (initial conditions, time stepping, output)
boundary-condition-setup Complex BC configuration (Dirichlet, Neumann, Robin, Nitsche)
mesh-quality Mesh quality analysis and refinement recommendations

Skills (37)

Guided workflows for every supported PDE type, plus solver selection, element selection,
and debugging. Triggered automatically when you describe a problem:

“Solve a Stokes flow problem” → fem-workflow-stokes
“My solver diverged” → fem-debugging

Commands (6)

Command Description
/solve-poisson End-to-end Poisson solve with manufactured solution
/tutorial-chapter Walk through a DOLFINx tutorial chapter step-by-step
/run-tests Run the test suite with coverage
/check-contracts Audit Design-by-Contract compliance
/add-tool Scaffold a new MCP tool
/verify-installation Check Docker, container, and server status

MCP Protocol

Prompt Templates (6)

Prompt Description
setup_poisson Guided Poisson equation setup
setup_elasticity Linear elasticity problem workflow
setup_stokes Stokes flow with mixed elements
setup_navier_stokes Navier-Stokes with time stepping
debug_convergence Diagnose solver convergence failures
convergence_study h-refinement convergence rate study

Resources (6)

URI Content
dolfinx://capabilities Element families, solvers, export formats
dolfinx://mesh/schema JSON schema for mesh objects
dolfinx://space/schema JSON schema for function space objects
dolfinx://solution/schema JSON schema for solution objects
dolfinx://session/overview Current session state summary
dolfinx://solver/options Available solver and preconditioner options

Transport Modes

Mode Command Use Case
stdio (default) docker run --rm -i dolfinx-mcp CLI clients, Claude Desktop
streamable-http docker run -p 8000:8000 dolfinx-mcp --transport streamable-http --host 0.0.0.0 Web clients, JupyterLab
sse docker run -p 8000:8000 dolfinx-mcp --transport sse --host 0.0.0.0 Legacy SSE clients

JupyterLab Integration

Start with Docker Compose:

docker-compose -f docker-compose.lab.yml up --build
# Open http://localhost:8888

Or install directly:

pip install dolfinx-mcp[jupyter]

Use IPython magics inside JupyterLab:

%load_ext dolfinx_mcp_jupyter

%mcp_config url=http://localhost:8000/mcp

%mcp create_unit_square name=mesh nx=16 ny=16
%mcp create_function_space name=V family=Lagrange degree=1
%mcp solve solver_type=direct
%mcp compute_error exact="sin(pi*x[0])*sin(pi*x[1])" norm_type=L2

Design-by-Contract

All 38 tools enforce runtime contracts:

  • Preconditions: Input validation (parameter types, ranges, existence checks)
  • Postconditions: Output validation (return structure, value constraints)
  • Invariants: 9 referential integrity invariants on SessionState

Contract violations return structured error responses:

{
  "error": "PRECONDITION_VIOLATED",
  "message": "Mesh 'box' not found in session",
  "suggestion": "Create a mesh first with create_unit_square or create_mesh"
}

Error codes: NO_ACTIVE_MESH, MESH_NOT_FOUND, FUNCTION_SPACE_NOT_FOUND,
FUNCTION_NOT_FOUND, INVALID_UFL_EXPRESSION, SOLVER_ERROR, DUPLICATE_NAME,
DOLFINX_API_ERROR, FILE_IO_ERROR, PRECONDITION_VIOLATED,
POSTCONDITION_VIOLATED, INVARIANT_VIOLATED.


Formal Verification (Lean 4)

8 of the 9 referential integrity invariants are formally verified in Lean 4
with machine-checked proofs. INV-9 (FormInfo.trial_space_name) is specified
in Quint and enforced at runtime.

20 theorems, 4 helper lemmas, zero sorry placeholders.

Theorem What it proves
freshState_valid Empty session satisfies all 8 invariants
registerMesh_valid Adding a mesh preserves invariants
registerFunctionSpace_valid Adding a function space preserves invariants
removeMesh_valid Cascade deletion of mesh + dependents preserves invariants
removeSpaceDeps_valid Removing space dependents preserves invariants
cleanup_valid Session reset produces a valid state
validateOutputPath_safe Output path validation is a containment check
errorCodeString_injective All 13 error codes are pairwise distinct

Verify locally (requires [Lean 4]):

cd .outline/proofs/DolfinxProofs
lake build    # exits 0, zero warnings

Security

Three-layer defense for UFL expression evaluation:

  1. Token blocklist_check_forbidden() rejects import, __, exec, eval, open, os., subprocess, and 12 more tokens at parse time
  2. Empty __builtins__ — expression namespaces have no access to Python internals
  3. Docker isolation — container runs with --network none, non-root user, --rm

run_custom_code intentionally bypasses the blocklist (full __builtins__).
Docker isolation is the sole boundary for custom code execution.

See SECURITY.md for vulnerability reporting.


Development

pip install -e ".[dev]"
# Unit tests (no Docker, ~417 tests)
pytest tests/ \
  --ignore=tests/test_runtime_contracts.py \
  --ignore=tests/test_tutorial_workflows.py \
  --ignore=tests/test_edge_case_contracts.py \
  --ignore=tests/test_poisson_workflow.py

# Docker integration tests (514 tests across 6 suites)
docker build -t dolfinx-mcp .
./scripts/run-docker-tests.sh

# Lint & type check
ruff check src/
pyright src/dolfinx_mcp/

Project Structure

src/dolfinx_mcp/
    server.py              Entry point
    _app.py                FastMCP instance + lifespan
    session.py             SessionState (8 registries, 9 invariants)
    errors.py              13 error classes + decorator
    ufl_context.py         Restricted UFL expression evaluation
    tools/
        mesh.py            9 mesh tools
        spaces.py          2 function space tools
        problem.py         3 problem definition tools
        solver.py          5 solver tools
        postprocess.py     6 post-processing tools
        interpolation.py   4 interpolation tools
        session_mgmt.py    9 session management tools
    prompts/templates.py   6 workflow prompts
    resources/providers.py 6 URI resources

src/dolfinx_mcp_jupyter/   JupyterLab extension (5 IPython magics)

tests/                     18 test files, ~514 tests (417 unit + 97 Docker-only)
examples/                  3D Poisson notebook + production readiness suite
.outline/proofs/           Lean 4 formal verification (20 theorems)
ccfenics/                  Claude Code plugin (37 skills, 6 agents, 6 commands)

Contributing

See CONTRIBUTING.md for development setup, code style, and the new tool checklist.

License

MIT