Skip to content

Troubleshooting

github-actions[bot] edited this page Apr 3, 2026 · 20 revisions

Troubleshooting

Common Issues

Installation & Setup

Python Installation Fails

Symptom: pip install matlab-mcp fails with permission or dependency errors

Likely Cause: Virtual environment not activated, or missing Python development headers

Solution:

  1. Verify Python 3.10+ is installed:

    python --version
  2. Create and activate a virtual environment:

    python -m venv venv
    source venv/bin/activate  # macOS/Linux
    # or
    venv\Scripts\activate  # Windows
  3. Upgrade pip:

    pip install --upgrade pip
  4. Install the package:

    pip install matlab-mcp

MATLAB Engine API Installation Fails

Symptom: ModuleNotFoundError: No module named 'matlab' after installation

Likely Cause: MATLAB Engine API for Python not installed, or MATLAB path not configured

Solution:

  1. Locate your MATLAB installation:

    • Windows: C:\Program Files\MATLAB\R2024a (or your version)
    • macOS: /Applications/MATLAB_R2024a.app (or your version)
    • Linux: /usr/local/MATLAB/R2024a (or your version)
  2. Install Engine API from MATLAB directory:

    cd "C:\Program Files\MATLAB\R2024a\extern\engines\python"  # Windows
    pip install .
    
    # or macOS/Linux:
    cd /Applications/MATLAB_R2024a.app/extern/engines/python
    pip install .
  3. Verify installation:

    python -c "import matlab.engine; print('Engine API OK')"
  4. If still failing, set MATLAB root in config:

    # config.yaml
    pool:
      matlab_root: "C:\\Program Files\\MATLAB\\R2024a"  # Windows
      # or /Applications/MATLAB_R2024a.app  # macOS

Runtime Issues

Server Won't Start

Symptom: matlab-mcp command fails to start, or exits immediately

Likely Cause: MATLAB engine pool initialization timeout, invalid config, or missing dependencies

Solution:

flowchart TD
    A["Server won't start"] --> B{Check error message}
    B -->|Engine timeout| C["Increase engine_start_timeout<br/>in config.yaml"]
    B -->|Config error| D["Validate config.yaml syntax<br/>with YAML linter"]
    B -->|Module not found| E["Reinstall package:<br/>pip install matlab-mcp"]
    B -->|Port in use| F["Change port in config<br/>or kill existing process"]
    C --> G["Retry server start"]
    D --> G
    E --> G
    F --> G
Loading

Debug Steps:

  1. Check for immediate errors:

    matlab-mcp --help

    Should show usage without errors.

  2. Enable debug logging:

    export MATLAB_MCP_SERVER_LOG_LEVEL=debug  # macOS/Linux
    # or setenv MATLAB_MCP_SERVER_LOG_LEVEL debug  # Windows PowerShell
    
    matlab-mcp --config config.yaml
  3. Check config syntax:

    python -c "from matlab_mcp.config import AppConfig; AppConfig.from_yaml('config.yaml')"

    If successful, prints config; otherwise shows YAML/validation errors.

  4. Test MATLAB engine independently:

    python -c "import matlab.engine; eng = matlab.engine.start_matlab(); print('Engine OK'); eng.quit()"
  5. Increase engine startup timeout:

    pool:
      engine_start_timeout: 60  # 60 seconds (default 30)
      min_engines: 1  # Start with only 1 engine to debug

MATLAB Engine Start Timeout

Symptom: Engine 1 start timeout after 30s in logs

Likely Cause: MATLAB is slow to start on this system, or licensing issue

Solution:

  1. Increase timeout:

    pool:
      engine_start_timeout: 120  # 2 minutes
  2. Test MATLAB directly:

    matlab -nosplash -nodesktop -r "disp('MATLAB OK'); exit"
  3. Check MATLAB license:

    matlab
    >> license
  4. Reduce initial pool size:

    pool:
      min_engines: 0  # Start with no engines, scale on demand
      max_engines: 2  # Limit total engines

Connection Refused (Agent Can't Connect)

Symptom: Agent (Claude Code, Codex CLI, Cursor) reports connection refused or timeout

Likely Cause: Server not running on expected address/port, firewall blocking, or wrong transport

Solution:

flowchart TD
    A["Agent can't connect"] --> B{Check server status}
    B -->|Server not running| C["Start server:<br/>matlab-mcp"]
    B -->|Server running| D{Check transport}
    D -->|Using stdio| E["Agent must connect<br/>via same process<br/>check MCP config"]
    D -->|Using SSE/HTTP| F{Verify address}
    F -->|Wrong address| G["Update agent config<br/>to 127.0.0.1:8765"]
    F -->|Firewall blocks| H["Allow port 8765<br/>in firewall settings"]
    F -->|No token| I["Set MATLAB_MCP_AUTH_TOKEN<br/>for HTTP transports"]
    C --> J["Retry agent connection"]
    E --> J
    G --> J
    H --> J
    I --> J
Loading

Debug Steps:

  1. Verify server is running:

    ps aux | grep matlab-mcp
    # or Windows:
    tasklist | findstr matlab-mcp
  2. Check port is listening:

    netstat -an | grep 8765  # macOS/Linux
    # or Windows:
    netstat -ano | findstr 8765
  3. Test with curl (for HTTP/SSE transports):

    curl http://127.0.0.1:8765/health
    # Should return {"status": "healthy", ...}
  4. Verify agent configuration:

    • For Claude Code/Claude Desktop: Check config at ~/.config/claude/config.json (Linux/macOS) or %APPDATA%\Claude\config.json (Windows)
    • Ensure "transport" is correct: "stdio" for local, "sse" or "http" for remote
    • For HTTP: ensure bearer token matches MATLAB_MCP_AUTH_TOKEN env var
  5. Set auth token for HTTP transports:

    export MATLAB_MCP_AUTH_TOKEN="your-token-here"  # macOS/Linux
    # or Windows PowerShell:
    $env:MATLAB_MCP_AUTH_TOKEN="your-token-here"
    
    matlab-mcp --transport streamablehttp
  6. Check firewall (Windows):

    # Allow port 8765 in Windows Firewall
    New-NetFirewallRule -DisplayName "MATLAB MCP" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8765

Code Execution

"BlockedFunctionError: Function 'system' is blocked"

Symptom: Code execution fails with blocked function error

Likely Cause: Security validator blocks dangerous MATLAB functions by default

Solution:

flowchart TD
    A["Blocked function error"] --> B{What function is blocked?}
    B -->|system/unix/dos| C["Use MATLAB native alternatives:<br/>dir, mkdir, copyfile, movefile"]
    B -->|eval/evalc| D["Use feval with named function<br/>or avoid dynamic code"]
    B -->|eval/fevalc| E["Rewrite without eval"]
    B -->|Other| F{Can disable blocking?}
    F -->|Not shared server| G["Disable in config:<br/>security.blocked_functions_enabled: false"]
    F -->|Shared server| H["Contact admin<br/>to whitelist function"]
    C --> I["Retry execution"]
    D --> I
    E --> I
    G --> I
    H --> I
Loading

Blocked Functions (Default):

  • Shell execution: system, unix, dos, ! (shell escape)
  • Dynamic code: eval, evalc, feval (with string function name)
  • File I/O: fopen, fread, fwrite (use MATLAB-native readtable, writematrix)

Safe Alternatives:

Blocked Use Instead
system('ls') dir
system('mkdir x') mkdir('x')
system('cp a b') copyfile('a', 'b')
system('mv a b') movefile('a', 'b')
eval('x=5') x=5 (inline)
feval('func', args) func(args)
getenv('VAR') ✓ Safe (whitelisted)
cd /path ✓ Safe
pwd, ls, dir ✓ Safe

To disable blocking (not recommended):

security:
  blocked_functions_enabled: false

Job Stuck or Timeout

Symptom: Job never completes, remains in "running" state, or hits timeout

Likely Cause: Long-running code, infinite loop, or MATLAB hang

Solution:

  1. Cancel the job: Ask your agent to call cancel_job:

    Agent: "Cancel job <job-id>"
    
  2. Check execution timeout:

    execution:
      sync_timeout: 30  # Inline execution timeout
      max_execution_time: 86400  # Max total time (24h)
  3. Increase timeout if code is legitimately slow:

    execution:
      sync_timeout: 300  # 5 minutes
      max_execution_time: 3600  # 1 hour max
  4. Enable progress reporting for long-running code:

    % In your MATLAB code:
    for i = 1:1000
        % Do work
        mcp_progress(__mcp_job_id__, i/1000*100, sprintf('Iteration %d', i));
    end
  5. Check for infinite loops:

    while true
        % Missing break condition?
    end

Wrong Result or Unexpected Output

Symptom: Code executes but returns wrong values, missing variables, or truncated output

Likely Cause: Large results truncated, workspace not cleared between jobs, or format issue

Solution:

  1. Check for truncation:

    Output size: 125,000 chars (truncated, saved to file)
    

    Increase limits if needed:

    output:
      max_inline_text_length: 100000  # Default 50k chars
      large_result_threshold: 50000   # Default 10k elements
  2. Verify workspace isolation: Each job should start with a fresh workspace. If seeing leftover variables, the session may not be isolated. Check:

    whos  % See what variables are defined
  3. Check result format: Results are automatically converted:

    • Tables → JSON
    • Figures → Plotly JSON + PNG
    • Matrices → arrays
    • Text → string (truncated if >50k chars)

Plotting & Visualization

"Plotly Conversion Failed"

Symptom: Code produces plot but no interactive Plotly visualization, only static PNG

Likely Cause: Plot type not supported by converter, or mcp_extract_props.m failed

Solution:

flowchart TD
    A["Plotly conversion failed"] --> B{Check plot type}
    B -->|Simple line/scatter| C["Update plotly_style_mapper.py<br/>or file bug report"]
    B -->|Custom/complex plot| D["Supported: line, scatter, bar,<br/>histogram, surface, heatmap<br/>Simplify plot or use static PNG"]
    B -->|Multiple subplots| E["Check domain calculation<br/>for subplot layout"]
    D --> F["Use static PNG fallback"]
    C --> G["Test with simple plot"]
    E --> G
Loading

Supported Plot Types:

  • ✓ Line plots (plot)
  • ✓ Scatter plots (scatter)
  • ✓ Bar charts (bar)
  • ✓ Histograms (histogram)
  • ✓ Surface plots (surf)
  • ✓ Heatmaps (imagesc, heatmap)
  • ⚠️ Custom graphics objects (may not convert)

Solutions:

  1. Fallback to static PNG:

    output:
      plotly_conversion: false  # Use PNG only
  2. Simplify the plot:

    % Instead of complex customizations:
    plot(x, y);
    title('My Plot');
    xlabel('X');
    ylabel('Y');
    % Rather than:
    ax = gca;
    ax.XColor = [0.5 0.5 0.5];
    % ... many other properties
  3. Check supported subplots:

    % Good — standard subplot grid
    subplot(2, 2, 1); plot(x, y);
    subplot(2, 2, 2); plot(x, y);
    
    % Also supported — tiled layout
    tiledlayout(2, 2);
    nexttile; plot(x, y);
    nexttile; plot(x, y);
  4. Enable debug logging:

    server:
      log_level: debug

    Check logs for Plotly conversion errors.

Figure Upload/Download Issues

Symptom: Can't read/upload image files, or file operations fail

Likely Cause: File path traversal protection, or size limits

Solution:

  1. Check file size limit:

    security:
      max_upload_size_mb: 100
  2. Verify file is in temp directory: Files are restricted to the session's temp directory:

    /tmp/<session-id>/  (macOS/Linux)
    C:\Users\<user>\AppData\Local\Temp\matlab-mcp\<session-id>\  (Windows)
    
  3. Test upload:

    Agent: "Upload file data.txt with content 'hello'"
    

    File is saved to temp directory and can be accessed.


Configuration

"Env var override not working"

Symptom: Environment variable doesn't override config.yaml setting

Likely Cause: Wrong env var name or format

Solution:

Environment variables use MATLAB_MCP_* prefix with path notation:

# Set specific fields:
export MATLAB_MCP_SERVER_HOST=0.0.0.0
export MATLAB_MCP_SERVER_PORT=9000
export MATLAB_MCP_POOL_MIN_ENGINES=2
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=60
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false
export MATLAB_MCP_MONITORING_ENABLED=true

# Start server — these override config.yaml
matlab-mcp --config config.yaml

Env Var Naming Pattern:

  • MATLAB_MCP_ prefix
  • Nested keys with underscores: SERVER_HOST, POOL_MIN_ENGINES
  • Values coerced to config types (bool, int, float, string)

Config File Not Found

Symptom: Error: config.yaml not found

Solution:

  1. Create a default config:

    # Server creates a default config at startup
    matlab-mcp --config config.yaml --generate-defaults
    # or manually:
    cp examples/config_minimal.yaml config.yaml
  2. Use absolute path:

    matlab-mcp --config /full/path/to/config.yaml
  3. Check working directory:

    pwd  # Prints current directory
    ls -la config.yaml  # File exists here?

Authentication & Security

"401 Unauthorized" (HTTP/SSE transports)

Symptom: Agent receives HTTP 401 error when connecting

Likely Cause: Bearer token missing or incorrect, auth not configured

Solution:

flowchart TD
    A["HTTP 401 Unauthorized"] --> B{Is auth enabled?}
    B -->|Stdio transport| C["Auth bypassed for stdio<br/>no token needed"]
    B -->|HTTP/SSE transport| D["Generate and set token"]
    C --> E["Check transport:<br/>--transport stdio"]
    D --> F["Generate token:<br/>matlab-mcp --generate-token"]
    F --> G["Set env var:<br/>export MATLAB_MCP_AUTH_TOKEN=..."]
    G --> H["Agent uses Authorization header:<br/>Authorization: Bearer &lt;token&gt;"]
    E --> I["Retry agent connection"]
    H --> I
Loading

Steps:

  1. Generate a token:

    matlab-mcp --generate-token

    Output:

    Generated bearer token (64 hex chars):
    a1b2c3d4e5f6...
    
    Environment variable to set:
    export MATLAB_MCP_AUTH_TOKEN="a1b2c3d4e5f6..."
    
  2. Set environment variable:

    # macOS/Linux:
    export MATLAB_MCP_AUTH_TOKEN="a1b2c3d4e5f6..."
    
    # Windows PowerShell:
    $env:MATLAB_MCP_AUTH_TOKEN="a1b2c3d4e5f6..."
  3. Start server:

    matlab-mcp --transport streamablehttp
  4. Configure agent to use bearer token:

    {
      "mcpServers": {
        "matlab": {
          "command": "python",
          "args": ["-m", "matlab_mcp"],
          "env": {
            "MATLAB_MCP_AUTH_TOKEN": "a1b2c3d4e5f6..."
          }
        }
      }
    }

    Or for HTTP transports:

    {
      "mcpServers": {
        "matlab": {
          "type": "sse",
          "url": "http://127.0.0.1:8765",
          "headers": {
            "Authorization": "Bearer a1b2c3d4e5f6..."
          }
        }
      }
    }

Cannot Generate Token (Permission Error)

Symptom: --generate-token fails with permission denied

Solution:

  1. Run with explicit permissions:

    python -m matlab_mcp --generate-token
  2. Use Python directly:

    import secrets
    token = secrets.token_hex(32)
    print(f"MATLAB_MCP_AUTH_TOKEN={token}")
  3. Check file permissions: If config.yaml or log files have restrictive permissions, update:

    chmod 644 config.yaml
    chmod 755 logs/

Platform-Specific

macOS: "Too many open files"

Symptom: OSError: [Errno 24] Too many open files

Likely Cause: System file descriptor limit exceeded (MATLAB engines open many files)

Solution:

  1. Increase file descriptor limit:

    # Temporary (current session):
    ulimit -n 4096
    
    # Permanent (add to ~/.zshrc or ~/.bash_profile):
    ulimit -n 4096
  2. Verify limit:

    ulimit -n  # Shows current limit
  3. Reduce engine pool:

    pool:
      max_engines: 2  # Fewer engines = fewer files

Windows: "Access Denied" or Admin Required

Symptom: Server fails to start, or firewall/admin dialog appears

Likely Cause: Non-admin user trying to bind to privileged port or access restricted directory

Solution:

  1. Use loopback address (no admin needed):

    server:
      host: "127.0.0.1"  # Default — requires no admin
      # Not 0.0.0.0 — that requires admin on Windows without exception
  2. Use non-privileged port:

    server:
      port: 8765  # >1024 — no admin needed
      # Not 80, 443, 8080, etc.
  3. Run installer as admin (one-time):

    # Use the install.bat provided, or:
    python -m pip install --user matlab-mcp
  4. Check temp directory: Server creates session directories in:

    C:\Users\<user>\AppData\Local\Temp\matlab-mcp\
    

    Ensure directory exists and is writable:

    New-Item -Path "$env:APPDATA\..\Local\Temp\matlab-mcp" -ItemType Directory -Force

Linux: "ModuleNotFoundError: No module named 'matplotlib'"

Symptom: Plotting fails with matplotlib import error

Likely Cause: Plotting library not installed, or wrong Python environment

Solution:

  1. Install visualization dependencies:

    pip install matlab-mcp[monitoring]  # Includes plotting libs
  2. Or install separately:

    pip install matplotlib plotly pillow
  3. Verify environment:

    python -c "import matplotlib; print(matplotlib.__version__)"

Still Stuck?

Collect Diagnostic Information

If issues persist, collect this information for support:

# System info
python --version
matlab -version
uname -a  # macOS/Linux
wmic os get version  # Windows

# Package versions
pip show matlab-mcp
pip list | grep -E "matlab|fastmcp|pydantic|plotly"

# Config validation
python -c "from matlab_mcp.config import AppConfig; AppConfig.from_yaml('config.yaml')" 2>&1

# MATLAB engine test
python -c "import matlab.engine; eng = matlab.engine.start_matlab(); print(eng.version()); eng.quit()" 2>&1

# Server logs (enable debug)
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
matlab-mcp --config config.yaml 2>&1 | head -100

# Network (if connection issues)
netstat -an | grep 8765
curl -v http://127.0.0.1:8765/health 2>&1

Save all output to a file and share with the project.

Get Help

Enable Verbose Logging

# config.yaml
server:
  log_level: "debug"
  log_file: "./logs/server.debug.log"

monitoring:
  enabled: true  # Collect detailed metrics

Then check logs/server.debug.log for detailed error context:

tail -f logs/server.debug.log
# or search for errors:
grep -i "error\|exception" logs/server.debug.log

Common Workflows

Debug Mode (Inspect)

Run server without MATLAB, perfect for testing transport/auth:

matlab-mcp --inspect --transport streamablehttp

This starts the server with:

  • No MATLAB engine pool (instant startup)
  • All tools return mock responses
  • Auth/transport fully functional
  • Useful for agent configuration testing

Test Local Connection

# Terminal 1: Start server
matlab-mcp

# Terminal 2: Test with curl (stdio transport)
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "test", "version": "1.0"}}}' | python -m matlab_mcp

# Or for HTTP:
curl -H "Authorization: Bearer $MATLAB_MCP_AUTH_TOKEN" \
  http://127.0.0.1:8765/health

Performance Tuning

If the server is slow:

pool:
  min_engines: 0  # Don't start engines until needed
  max_engines: 4  # Limit total engines
  health_check_interval: 60  # Check less frequently

execution:
  sync_timeout: 10  # Promote to async sooner

monitoring:
  enabled: false  # Disable metrics if not needed
  
output:
  plotly_conversion: false  # Skip Plotly, use PNG only

Clone this wiki locally