Skip to content
github-actions[bot] edited this page Mar 23, 2026 · 20 revisions
# FAQ

## General / Overview

### What is the MATLAB MCP Server?

The MATLAB MCP Server connects AI agents (like Claude, Cursor, or GitHub Copilot) to MATLAB via the Model Context Protocol (MCP). It lets agents execute MATLAB code, discover toolboxes and functions, generate plots, manage files, and track long-running jobs—all through a standardized protocol.

### What MATLAB versions are supported?

**MATLAB 2020b and later**. The MATLAB Engine API for Python must be installed separately from your MATLAB installation. See [[Installation]] for setup instructions.

### What programming languages does the server support?

The server itself is written in **Python**. It controls MATLAB engines and exposes tools via MCP. MATLAB code executed through the server can use any MATLAB syntax, including calls to toolboxes like Signal Processing, Statistics, Deep Learning, and more.

### Does it work without MATLAB installed?

**No.** The server requires a local MATLAB installation with the Engine API. It connects to real MATLAB engines, not a simulator. For testing without MATLAB, the project includes a mock engine for CI (see `tests/mocks/matlab_engine_mock.py`).

### What license do I need?

You must have a valid MATLAB license (individual, team, or concurrent). The server does not provide licensing — it uses your existing MATLAB installation.

### What AI agents work with this?

Any agent that supports the **Model Context Protocol (MCP)**:
- **Claude Desktop** (Mac/Windows with MCP support)
- **Cursor** (with MCP integration)
- **GitHub Copilot** (when MCP support is available)
- **Custom agents** built with MCP SDKs (Python, JavaScript, etc.)

See [[Installation]] for integration steps.

### Can I install it from PyPI?

**Yes.** The package is available on PyPI as `matlab-mcp-python`:

```bash
pip install matlab-mcp-python
matlab-mcp  # Start the server

You still need the MATLAB Engine API installed separately. See Installation.

What's the license?

The MATLAB MCP Server is licensed under the MIT License. MATLAB and its toolboxes are proprietary and subject to MathWorks licensing.

Where can I report bugs or contribute?

Open an issue or pull request on GitHub. See the README for contribution guidelines.


Setup

How do I install the MATLAB Engine API?

macOS:

cd /Applications/MATLAB_R2024a.app/extern/engines/python
pip install .

Windows (Command Prompt):

cd "C:\Program Files\MATLAB\R2024a\extern\engines\python"
pip install .

Adjust the path for your MATLAB version. If installation fails, ensure Python 3.10+ is in your PATH and matches your MATLAB Engine API requirements.

See Installation for detailed step-by-step instructions.

Can I use a virtual environment?

Yes. The Engine API must be installed into the same virtual environment where matlab-mcp-python is installed:

python -m venv venv
source venv/bin/activate  # macOS/Linux
# or
venv\Scripts\activate  # Windows

pip install matlab-mcp-python
cd /path/to/matlab/extern/engines/python
pip install .

stdio vs SSE — which should I use?

Transport Use Case Users
stdio Single user, agent launches server directly 1
SSE (HTTP) Multi-user, shared server, persistent connection Many

stdio is simpler for personal use. SSE is better for team deployments where multiple agents connect to a single server instance.

See Configuration for how to switch transports.

How do I connect the server to Claude Desktop?

  1. Start the server (it will print stdio port info):
    matlab-mcp
  2. On macOS, edit ~/Library/Application Support/Claude/claude_desktop_config.json:
    {
      "mcpServers": {
        "matlab": {
          "command": "matlab-mcp",
          "args": []
        }
      }
    }
  3. Restart Claude Desktop.

See Installation for Cursor, Code, and Docker setups.

How do I run the server remotely?

Use SSE transport on a remote machine:

# On remote server
matlab-mcp --config config.yaml
# (config has server.transport: "sse", server.port: 8765)

Important: Always put the server behind an authenticating reverse proxy (nginx, Caddy, etc.) for production. See Security.

How do I install offline (no internet)?

Use the provided install.bat (Windows) or manually download wheels via:

pip download -r requirements.txt -d vendor/

Then install from the local directory:

pip install --no-index --find-links vendor/ matlab-mcp-python

See the project's install.bat script for a complete offline setup example.

How do I troubleshoot installation errors?

Common issues and fixes:

Error Cause Fix
ModuleNotFoundError: No module named 'matlab' Engine API not installed Install Engine API from MATLAB directory
python --version shows wrong Python Multiple Python versions installed Use full path to correct Python (e.g., /usr/bin/python3.11)
macOS: Library not in rpath MATLAB dylib path issue See Troubleshooting
Windows: 'matlab-mcp' is not recognized Scripts not in PATH Add Python\Scripts\ to PATH or use python -m matlab_mcp.cli

See Troubleshooting for more detailed debugging steps.


Performance

How many engines should I run?

Scenario Recommended Notes
Personal use 1–2 One per agent or workload type
Small team (2–5) 2–4 One per concurrent user, with queuing
Larger team 4–16 Scale based on concurrent usage & license limit
macOS ≤ 4 OS/MATLAB limitation on concurrent engines

Each engine is an independent MATLAB process consuming ~500MB–2GB memory.

What's the memory overhead?

  • Per engine: ~500MB–2GB (depending on loaded toolboxes)
  • Server process: ~50–100MB
  • Monitoring (optional): ~10–50MB for metrics database

Example: 4 engines + server ≈ 2–10GB memory.

How does the pool scale dynamically?

The EnginePoolManager maintains between min_engines and max_engines:

  • Startup: Starts min_engines in parallel
  • Under load: If all engines are busy and total < max_engines, a new engine is started
  • Idle: Engines idle longer than scale_down_idle_timeout (default 900s) are stopped
  • Proactive warmup: When utilization exceeds proactive_warmup_threshold (default 80%), a new engine is pre-warmed

See Configuration for tuning these parameters.

What happens when all engines are busy?

Requests queue up (default queue_max_size: 50). The pool attempts to scale up. If the queue fills, new requests are rejected with a 503 error.

To reduce queueing:

  • Increase max_engines
  • Reduce sync_timeout to promote long jobs to async faster
  • Split large computations across multiple jobs

How do I optimize for large datasets?

execution:
  sync_timeout: 10      # Fast timeout promotes to async
  max_execution_time: 3600  # 1 hour max per job

pool:
  min_engines: 2
  max_engines: 8        # Scale to handle concurrency

output:
  large_result_threshold: 50000  # Save large results to temp files
  max_inline_text_length: 100000

Use async execution for long computations and read results back via read_data.

Can I profile execution time?

Enable the monitoring dashboard:

monitoring:
  enabled: true
  sample_interval: 10   # Seconds between samples

Access /dashboard to see:

  • Average execution latency
  • p95 execution latency (95th percentile)
  • Pool utilization over time
  • Job throughput (jobs/minute)

See Configuration for more monitoring options.


Integration

How do I use custom MATLAB functions with the server?

Option 1: Custom Tools (recommended)

Define functions in custom_tools.yaml:

custom_tools:
  - name: "analyze_signal"
    description: "FFT analysis of a signal"
    function: "signal_processing.analyze"  # my_package.m_function
    parameters:
      - name: "signal"
        type: "list"
        description: "Signal array"
      - name: "fs"
        type: "float"
        description: "Sampling frequency"
        default: 1000.0
    return_type: "dict"
    return_description: "FFT magnitude and frequency"

The function becomes a first-class MCP tool. See Custom Tools.

Option 2: Path Configuration

Add function directories to config:

execution:
  workspace:
    default_paths:
      - "/path/to/my_functions"
      - "/path/to/my_package"

Then call functions via execute_code:

result = my_analyze_signal(signal, fs);

How do I integrate with CI/CD pipelines?

The server can be called from CI/CD via the stdio transport:

# GitHub Actions example
- name: Run MATLAB job
  env:
    MATLAB_CODE: |
      result = run_optimization();
      save('result.mat', 'result');
  run: |
    matlab-mcp << 'EOF'
    ${{ env.MATLAB_CODE }}
    EOF

Or via SSE if the server is always running:

curl -X POST http://localhost:8765/execute \
  -d '{"code": "result = compute();"}'

How do I integrate with Jupyter notebooks?

Use the stdio transport to send MATLAB commands from Python:

import subprocess
import json

code = "x = linspace(0,2*pi,100); y = sin(x); disp(max(y));"
result = subprocess.run(["matlab-mcp"], input=code, capture_output=True, text=True)
print(result.stdout)

Or set up a persistent SSE connection for repeated calls.

Can I use this with GitHub Copilot?

GitHub Copilot Chat (with MCP support): Yes, once GitHub enables MCP in Copilot. Follow the same setup as Claude Desktop.

GitHub Copilot for Individuals: Currently uses Codex, not MCP. This may change in future releases.

Check GitHub's MCP roadmap for updates.

How do I build a custom agent?

Use the MCP SDKs:

Python:

import asyncio
from mcp import ClientSession, StdioTransport

async def main():
    async with StdioTransport("matlab-mcp") as transport:
        async with ClientSession(transport) as session:
            tools = await session.list_tools()
            for tool in tools:
                print(tool.name)

asyncio.run(main())

JavaScript:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({ command: "matlab-mcp" });
const client = new Client({ name: "my-agent", version: "1.0.0" }, {
  capabilities: {}
});
await client.connect(transport);
const tools = await client.listTools();

See MCP documentation for more.


Async Jobs & Progress

How does async execution work?

The server uses hybrid sync/async execution:

  1. Sync path (fast): Code finishes within sync_timeout (default 30s) → result returned immediately
  2. Async path (slow): Code exceeds timeout → job promoted to background, returns job_id immediately
graph LR
    A["execute_code(code)"] --> B{"Finishes<br/>within timeout?"}
    B -->|Yes| C["Return result<br/>status: completed"]
    B -->|No| D["Promote to async<br/>Return job_id"]
    D --> E["Poll get_job_status<br/>or get_job_result"]
    E --> F["Job completes<br/>in background"]
Loading

How do I report progress?

Use the mcp_progress() MATLAB helper in your code:

for trial = 1:1000000
    % ... computation ...
    if mod(trial, 100000) == 0
        % Report 30% progress with message
        mcp_progress(__mcp_job_id__, 30, sprintf('Trial %d/1000000', trial));
    end
end

The agent can poll get_job_status to see progress:

{
  "job_id": "abc123",
  "status": "running",
  "progress": 30.0,
  "message": "Trial 300000/1000000",
  "elapsed_seconds": 45.2
}

See Async Jobs for detailed examples.

What's the maximum job execution time?

Configured by execution.max_execution_time (default 86400s = 24 hours). Jobs exceeding this are cancelled.

Can I cancel a running job?

Yes, use cancel_job:

await client.call_tool("cancel_job", {"job_id": "abc123"})

The job transitions to CANCELLED status. If it's running in MATLAB, the engine is interrupted (best-effort).

How long are job results retained?

Jobs are kept for sessions.job_retention_seconds (default 86400 = 24 hours) after completion. Older jobs are pruned. To keep results longer, read them and save to a file.


Custom Tools & Toolboxes

How do I expose a .m function as an MCP tool?

Define it in custom_tools.yaml:

custom_tools:
  - name: "fit_model"
    description: "Fit a linear regression model"
    function: "my_package.fit_linear"  # my_package/fit_linear.m
    parameters:
      - name: "X"
        type: "list"
        description: "Feature matrix"
      - name: "y"
        type: "list"
        description: "Target vector"
    return_type: "dict"
    return_description: "Model coefficients and R²"

The function becomes a tool. When called, X and y are passed as arguments, and the return value is serialized to JSON.

See Custom Tools for full schema and examples.

Can I use MEX functions?

Yes, as long as they're on the MATLAB path. Add their directory to workspace.default_paths:

execution:
  workspace:
    default_paths:
      - "/path/to/mex_compiled_bin"

Then call them via execute_code or define a custom tool wrapper.

How do I discover available toolboxes?

Use the list_toolboxes tool:

toolboxes = await client.call_tool("list_toolboxes", {})
# Returns: ["Signal Processing", "Statistics and Machine Learning", ...]

Filtered by security.allowed_toolboxes (if configured).

Can I restrict which toolboxes are available?

Yes. In config:

security:
  allowed_toolboxes:
    - "Signal Processing Toolbox"
    - "Statistics and Machine Learning Toolbox"

Only these toolboxes appear in list_toolboxes. Functions from restricted toolboxes cannot be called.

Can I add function documentation?

Yes, via the description and return_description fields in custom_tools.yaml. The agent sees this documentation when inspecting the tool schema.


File & Plot Handling

What happens to files I create in MATLAB?

Files are written to the session's temp directory (temp_dir in config, default /tmp/matlab-mcp-<session-id>/). You can:

  1. List files: list_files tool
  2. Read files: read_data (for data files), read_script (for .m files), read_image (for images)
  3. Download results: Read the file and save it locally

When the session ends, temp files are deleted (configurable via execution.temp_cleanup_on_disconnect).

Are MATLAB plots interactive?

Yes! MATLAB figures are automatically converted to interactive Plotly JSON. Agents and web-based clients see fully zoomable, pannable, interactive charts.

A static PNG fallback is also generated (configurable DPI via output.static_image_dpi).

What plot types convert to Plotly?

  • Line plots
  • Scatter plots
  • Bar charts
  • Histograms
  • Surface (3D)
  • Heatmaps
  • Images

Complex custom graphics or specialty plots may fall back to static PNG.

Can I change plot styling?

The server auto-converts MATLAB styling (colors, line styles, markers, legends, grid) to Plotly equivalents. Some MATLAB-specific styles may not have Plotly equivalents and are approximated.

To customize, either:

  1. Style in MATLAB: Use standard MATLAB plot properties
  2. Post-process in Python: Extract Plotly JSON and modify

Can I export plots?

Via the Plotly UI in web clients (download as PNG, SVG, etc.). Programmatically, request the Plotly JSON and process it.

How do I read data files (.mat, .csv, .json)?

Use read_data:

# Summary mode (default) — shows variable info
result = await client.call_tool("read_data", {"filename": "data.mat"})
# Returns: variables list, sizes, types

# Raw mode — returns base64-encoded file content
result = await client.call_tool("read_data", {
    "filename": "data.mat",
    "format": "raw"
})
# Decode and process locally

For .csv, .txt, .json: returns text content directly.

Can I upload large files?

The upload_data tool accepts base64-encoded files up to security.max_upload_size_mb (default 100MB). For very large files:

  1. Split into chunks and upload separately
  2. Use shared network drives (if available) and reference paths
  3. Stream data via repeated MATLAB calls

Security & Multi-User

Is it safe to expose over the network?

For SSE transport:

  • Always put behind an authenticating reverse proxy (nginx, Caddy, etc.)
  • Set require_proxy_auth: true in config
  • Bind to 127.0.0.1 (localhost) if proxy is on same machine
  • Use HTTPS/TLS for remote connections

Without these precautions, users can execute arbitrary MATLAB code on your server.

For stdio transport:

Stdio is inherently single-user and process-spawned. Not exposed over network.

See Security for detailed SSE setup.

What MATLAB functions are blocked?

By default:

Blocked Reason
system(), unix(), dos() Execute OS commands
! (shell escape) Execute OS commands
eval(), feval(), evalc(), evalin() Execute arbitrary code strings
assignin() Modify caller's workspace
perl(), python() Execute external scripts

The validator uses smart scanning—it strips string literals and comments to avoid false positives:

disp("The system is down")  % "system" in string — SAFE ✓
system("ls")                % Actual system() — BLOCKED ✗

Can I customize the blocklist?

Yes:

security:
  blocked_functions_enabled: true
  blocked_functions:
    - "system"
    - "eval"
    - "web"  # Add as needed
    # Remove entries to allow them

Or disable entirely (not recommended):

security:
  blocked_functions_enabled: false  # Dangerous!

Are user sessions isolated?

Yes. When execution.workspace_isolation: true (default), the workspace is fully cleared between sessions:

clear all
clear global
clear functions
fclose all
restoredefaultpath

Variables, functions, and file handles from one user don't leak to another.

How do I enforce authentication?

For stdio: The agent launcher handles auth (Claude Desktop, Cursor, etc.).

For SSE:

  1. Put behind reverse proxy with auth (OAuth, LDAP, Basic Auth, etc.)
  2. Set require_proxy_auth: true in config
  3. Server logs warning if SSE enabled without this flag

Example (nginx):

location / {
  auth_basic "MATLAB MCP";
  auth_basic_user_file /etc/nginx/.htpasswd;
  proxy_pass http://localhost:8765;
}

Troubleshooting & Development

How do I enable debug logging?

server:
  log_level: "debug"  # "info", "debug", "warning", "error"

Logs appear in console or configured log file.

How do I run tests?

pip install -e ".[dev]"
pytest tests/ -v

Tests use a mock MATLAB engine—no MATLAB installation required. To run only integration tests (requires MATLAB):

pytest tests/ -v -m matlab

How do I add a new MCP tool?

  1. Implement in src/matlab_mcp/tools/
  2. Register in src/matlab_mcp/server.py with @mcp.tool decorator
  3. Test in tests/

Example:

@mcp.tool
async def my_tool(param1: str, param2: int = 10) -> dict:
    """Tool description."""
    # Implementation
    return {"result": value}

Can I contribute?

Yes! Open an issue or PR on GitHub. See the README for guidelines.

How are CI/CD tests run?

The project uses GitHub Actions:

  • .github/workflows/ci.yml: Runs on every push/PR — linting, pytest, code coverage, Windows/macOS tests
  • .github/workflows/docs.yml: Auto-generates wiki on successful CI
  • .github/workflows/release.yml: Creates draft release with changelog on git version tag
  • .github/workflows/publish.yml: Publishes to PyPI on GitHub release

See the workflow files for details.

Where is the architecture documented?

See Architecture. It includes diagrams showing:

  • Top-level system flow (agent → MCP server → engines → MATLAB)
  • Engine pool manager lifecycle
  • Job executor sync/async behavior
  • Result formatting and Plotly conversion

Configuration Reference

Quick links to common config options:

Use Case Config
Single user examples/config_minimal.yaml
Multi-user, team server examples/config_multiuser.yaml
Max performance Increase pool.max_engines, reduce execution.sync_timeout
Monitoring/metrics Enable monitoring.enabled: true
Custom tools Define in custom_tools.yaml
Remote deployment Use server.transport: "sse" + reverse proxy

See Configuration for full reference.


Common Error Messages

Error Cause Solution
ModuleNotFoundError: No module named 'matlab' Engine API not installed Install Engine API from MATLAB directory
MATLAB Engine is not alive Engine crashed or timed out Check logs, restart server
Blocked function detected: system Security violation Remove function or customize blocklist
Job timeout after 30s Code too slow Increase execution.sync_timeout or optimize code
All engines busy, queue full High concurrency Increase pool.max_engines or add server instances
FileNotFoundError: data.mat File not found in session temp dir Use upload_data to upload file first

See Troubleshooting for more.

graph TB
    A["Agent<br/>(Claude, Cursor)"] -->|MCP Protocol| B["MATLAB MCP Server"]
    B -->|Create Job| C["Job Tracker"]
    B -->|Acquire Engine| D["Engine Pool Manager"]
    D -->|Execute Code| E["MATLAB Engine"]
    E -->|Workspace I/O| F["Session Temp Dir"]
    B -->|Format Results| G["Result Formatter"]
    G -->|Convert Figures| H["Plotly Converter"]
    B -->|Track Metrics| I["Metrics Collector"]
    I -->|Store| J["Metrics DB"]
    B -->|Validate Code| K["Security Validator"]
Loading

For more details, see:

Clone this wiki locally