-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
It's a Python-based bridge between AI coding agents (Claude, Codex CLI, Cursor) and MATLAB via the Model Context Protocol (MCP). It enables agents to execute MATLAB code, manage workspaces, discover toolboxes, and retrieve results—all within a secure, multi-user environment.
Key capabilities:
- Execute arbitrary MATLAB code with async job support for long-running tasks
- Elastic engine pooling with automatic scale-up/down
- Session isolation (separate workspaces per user)
- Security validation (blocked functions, upload limits, filename sanitization)
- Custom tools (expose your own MATLAB functions as first-class MCP tools)
- Interactive Plotly-based figure conversion
- Multi-user access via HTTP/SSE with bearer token authentication
- Real-time metrics and health monitoring dashboard
MATLAB: R2022b and later (earlier versions may work but are not tested)
Python: 3.10 or later
OS: Windows 10+, macOS, Linux (x86_64 / ARM64)
AI Agents: Any MCP-compatible agent—Claude Desktop, Claude Code, Codex CLI, Cursor, custom agents built with MCP SDKs
Yes. The server connects to locally-installed MATLAB engines via the MATLAB Engine API for Python. It does not work with MATLAB Online.
See SECURITY.md and the repository's LICENSE file for details. The project follows standard open-source licensing guidelines.
Yes. Tests use a mock MATLAB engine (MockMatlabEngine in tests/mocks/) so you can run the full test suite without a MATLAB installation:
pytest tests/ -v-
Locate your MATLAB installation:
-
Windows:
C:\Program Files\MATLAB\R2024a -
macOS:
/Applications/MATLAB_R2024a.app -
Linux:
/usr/local/MATLAB/R2024a
-
Windows:
-
Install the Engine API from the Python subdirectory:
cd /path/to/MATLAB/extern/engines/python pip install .
For detailed platform-specific steps, see Installation.
From PyPI (recommended):
pip install matlab-mcp-pythonFrom source:
git clone https://github.com/HanSur94/matlab-mcp-server-python.git
cd matlab-mcp-server-python
pip install -e ".[dev,monitoring]"graph TB
subgraph stdio["Stdio (Single-user)"]
A["Agent<br/>launches<br/>server"] -->|stdin/stdout| B["MCP Server<br/>MATLAB engines"]
end
subgraph http["Streamable HTTP<br/>(Multi-user)"]
C["Agent 1<br/>HTTP"]
D["Agent 2<br/>HTTP"]
E["Agent 3<br/>HTTP"]
C -->|Bearer Token| F["Reverse Proxy<br/>optional"]
D -->|Bearer Token| F
E -->|Bearer Token| F
F -->|/mcp endpoint| G["MCP Server<br/>Session routing<br/>MATLAB engines"]
end
| Feature | Stdio | Streamable HTTP |
|---|---|---|
| Setup | Simple (no network) | Requires HTTP endpoint |
| Users | One at a time | Concurrent |
| Auth | Inherited from agent | Bearer token or proxy |
| Default port | N/A | 8765 |
| Session isolation | Per process | Per HTTP session |
Choose stdio for single-user or testing. Choose HTTP for shared servers, integration with teams, or remote access (behind a reverse proxy).
Configuration uses a config.yaml file:
server:
transport: "streamablehttp" # or "stdio", "sse" (deprecated)
host: "127.0.0.1" # Bind address (loopback by default)
port: 8765 # HTTP port
log_level: "INFO"
pool:
min_engines: 2
max_engines: 10
health_check_interval_s: 30
execution:
sync_timeout: 30 # Promote to async if longer
workspace_isolation: true # Clear workspace between sessions
security:
blocked_functions_enabled: true
blocked_functions:
- "system"
- "unix"
- "eval"
monitoring:
enabled: true
metrics_retention_days: 7Environment variables override config file values with the MATLAB_MCP_ prefix. For example:
export MATLAB_MCP_POOL_MIN_ENGINES=4
export MATLAB_MCP_POOL_MAX_ENGINES=16
matlab-mcp --config config.yamlSee Configuration for all available options.
For stdio transport: No authentication needed (agent controls the process).
For HTTP transport: Use bearer tokens:
# Generate a token
matlab-mcp --generate-token
# Output: MATLAB_MCP_AUTH_TOKEN=a7f8c9e2d3b4a1f6e9c7d8b2a3f4e5c6
# Set the token in your environment
export MATLAB_MCP_AUTH_TOKEN="a7f8c9e2d3b4a1f6e9c7d8b2a3f4e5c6"
# Start the server
matlab-mcp --transport streamablehttpAgents connecting via HTTP must include the token in the Authorization header:
Authorization: Bearer a7f8c9e2d3b4a1f6e9c7d8b2a3f4e5c6
See Agent Onboarding for copy-paste configs for Claude Code, Codex CLI, and Cursor.
Yes. The project includes Dockerfile and docker-compose.yml:
# Build the image
docker build -t matlab-mcp:latest .
# Run with mounted MATLAB installation
docker run -v /path/to/MATLAB:/matlab matlab-mcp:latest \
--transport streamablehttp \
--config /etc/matlab_mcp/config.yamlFor a full multi-container setup (server + shared data volumes), see docker-compose.yml.
| Scenario | min_engines | max_engines | Notes |
|---|---|---|---|
| Development/testing | 1 | 2 | Fast startup, minimal memory |
| Single user | 2 | 4 | Parallelism for async jobs |
| Small team (2-5 users) | 2 | 8 | Balance concurrency & memory |
| Large team (10+ users) | 4 | 16+ | Scale based on license limits |
| macOS (hardware constraint) | 1 | 4 | MATLAB limits ~4 concurrent engines |
Each engine consumes ~500MB–2GB depending on loaded toolboxes.
Requests queue up (configurable execution.queue_max_size, default 50). If the pool hasn't reached max_engines, a new engine is automatically started. Requests are served FIFO as engines become available.
-
Increase
pool.min_engines— more engines ready = faster responses -
Lower
execution.sync_timeout— code that runs longer automatically becomes async (good for scalability) - Use custom tools for frequently-called code (pre-compiled at startup, faster invocation)
-
Enable workspace_isolation: false only if it's safe (skips expensive
clear all, but shares state)
Yes. The monitoring dashboard is available at:
http://127.0.0.1:8765/dashboard
It shows:
- Pool utilization (engines busy/total)
- Job throughput (completed, failed, average execution time)
- Active sessions and workspace memory
- Error rates and health status
- Event log (blocked functions, scaling events, crashes)
Requires monitoring.enabled: true in config.
-
Generate a token:
matlab-mcp --generate-token
-
Add to Claude Code settings (
.claude/claude.jsonor via UI):{ "mcpServers": { "matlab": { "command": "http://127.0.0.1:8765/mcp", "args": [], "env": { "MATLAB_MCP_AUTH_TOKEN": "your-token-here" } } } } -
Start the server:
matlab-mcp --transport streamablehttp
# 1. Start server
MATLAB_MCP_AUTH_TOKEN=$(matlab-mcp --generate-token | grep -o '[a-f0-9]*$') \
matlab-mcp --transport streamablehttp &
# 2. Configure Codex
codex config set mcp-servers.matlab.url http://127.0.0.1:8765/mcp
codex config set mcp-servers.matlab.auth-token "$MATLAB_MCP_AUTH_TOKEN"
# 3. Use it
codex chat "Write MATLAB code to plot sin(x)"See Agent Onboarding for detailed configs for all agents.
Not yet. Copilot requires MCP support from GitHub, which is under development.
Yes! Define them in custom_tools.yaml:
tools:
- name: "signal_analysis"
description: "Analyze signal frequency and power"
function: "my_functions.signal_analysis"
parameters:
- name: "data"
type: "array"
description: "Signal samples (1D array)"
- name: "sampling_rate"
type: "number"
description: "Sampling frequency in Hz"Then call them directly as MCP tools:
Agent: Use signal_analysis on this data...
Server: Calls my_functions.signal_analysis(data, sampling_rate) in MATLAB
See Custom Tools for full syntax and examples.
Yes. Common patterns:
GitHub Actions:
- name: Run MATLAB via MCP
env:
MATLAB_MCP_AUTH_TOKEN: ${{ secrets.MATLAB_MCP_TOKEN }}
run: |
matlab-mcp --inspect # --inspect mode, no MATLAB needed for validationGitLab CI:
matlab_tests:
script:
- MATLAB_MCP_POOL_MIN_ENGINES=1 matlab-mcp --execute "tests/run_tests.m"For examples, see Examples.
Default (loopback-only): Yes. The server binds to 127.0.0.1 by default, accessible only from the local machine.
Exposing to a network: Only if:
- You put it behind a reverse proxy (nginx, Apache) with TLS and authentication
- You set
MATLAB_MCP_AUTH_TOKENto a strong random token - You bind to a specific interface (not
0.0.0.0), or userequire_proxy_auth: truein config
Example nginx config:
upstream matlab_mcp {
server 127.0.0.1:8765;
}
server {
listen 443 ssl;
server_name matlab-api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /mcp {
auth_request /auth;
proxy_pass http://matlab_mcp/mcp;
proxy_set_header Authorization $http_authorization;
}
}The security validator prevents execution of:
-
system(),unix(),dos()— shell execution -
!operator — shell escapes -
eval(),evalc(),evalin()— dynamic code execution -
feval()— indirect function calls -
assignin(),evalin()— workspace manipulation -
perl(),python()— external code execution
You can customize the blocklist:
security:
blocked_functions_enabled: true
blocked_functions:
- "system"
- "eval"
- "my_internal_function" # Add your ownOr disable blocking entirely (not recommended for untrusted agents):
security:
blocked_functions_enabled: falseNo (if workspace_isolation: true, the default). Each session gets:
- A unique temporary directory
- A cleared MATLAB workspace (
clear all; clear global; clear functions; fclose all; restoredefaultpath) - No access to other sessions' files or variables
Files are validated:
-
Size limit:
security.max_upload_size_mb(default 100 MB) -
Filename sanitization: Only
[a-zA-Z0-9._-]allowed (prevents path traversal) - Location: Uploaded to session temp directory only, inaccessible to other sessions
Set hitl.enabled: true in config if you want prompts for sensitive operations:
hitl:
enabled: true
protected_functions: ["save", "delete_file"] # Functions requiring approval
protect_file_ops: true # Require approval for uploads/deletes
all_execute: false # Or true for every execute_code callWhen enabled, agents must wait for human approval before executing protected code. Useful for production access to sensitive systems.
Error: RuntimeError: Cannot find MATLAB installation
Fix: Install the MATLAB Engine API:
cd /path/to/MATLAB/extern/engines/python
pip install .Error: OSError: [Errno 2] No such file or directory: '/usr/local/MATLAB/...
Fix: The auto-detected path is wrong. Set it explicitly:
MATLAB_ROOT=/path/to/MATLAB matlab-mcpOn Windows: Windows Firewall may be blocking the port. The server defaults to 127.0.0.1 (loopback) to avoid this. If you bind to 0.0.0.0:
- Open PowerShell as Administrator and run:
New-NetFirewallRule -DisplayName "MATLAB MCP" -Direction Inbound -Program "C:\Path\To\python.exe" -Action Allow
- Or bind to
127.0.0.1and access only locally or through a reverse proxy.
On macOS/Linux: Check that the server is running:
curl -H "Authorization: Bearer $MATLAB_MCP_AUTH_TOKEN" http://127.0.0.1:8765/healthYour function might internally call a blocked function, or the function name matches a partial pattern. Check:
matlab-mcp --config config.yaml # See which functions are blockedTo unblock specific functions safely:
security:
blocked_functions:
- "eval"
- "system"
# Remove entries you trustBy default, code that runs longer than execution.sync_timeout (30 seconds) is automatically promoted to an async job. The agent can poll for progress:
% This runs in async mode
pause(60); % Sleeps 60 seconds
result = randn(1000, 1000) * randn(1000, 1000); % Large computationAgent receives a job_id and can use:
-
get_job_status(job_id)— check progress -
get_job_result(job_id)— retrieve results once complete
For real-time progress, use mcp_progress():
for i = 1:100
mcp_progress(__mcp_job_id__, i, sprintf('Iteration %d/100', i));
pause(1);
endStatic PNG fallback is used if:
- Plot uses custom graphics objects (not standard line/bar/scatter/surface)
- Plotly conversion encounters an error (logged in server logs)
- Client doesn't support Plotly JSON rendering
Check logs:
tail -f logs/matlab_mcp.log | grep -i plotlyThe static PNG is always available as a fallback.
MATLAB caches figures in memory. The server automatically closes figures after extracting their properties, but if you're generating many plots in quick succession, the limit may be hit. Close figures explicitly:
execute_code("close all"); % Clear all figuresOr reduce the number of concurrent jobs via pool.max_engines.
See Installation, Configuration, Custom Tools, and Security for deeper dives into specific topics.