Skip to content

Troubleshooting

github-actions[bot] edited this page Mar 22, 2026 · 20 revisions

Troubleshooting

MATLAB Engine Connection Failures

Symptom: Engine start timeout, matlab.engine not found, or Failed to start MATLAB engine

Solutions:

  1. Verify MATLAB Engine API is installed:

    python -c "import matlab.engine; print('OK')"

    If this fails, install the Engine API:

    cd /Applications/MATLAB_R2024a.app/extern/engines/python  # macOS
    # cd "C:\Program Files\MATLAB\R2024a\extern\engines\python"  # Windows
    pip install .
  2. Check MATLAB version: Must be R2022b or later.

  3. Verify MATLAB is on PATH or set matlab_root explicitly:

    pool:
      matlab_root: "/Applications/MATLAB_R2024a.app"  # macOS
      # matlab_root: "C:\\Program Files\\MATLAB\\R2024a"  # Windows
  4. Increase engine start timeout if MATLAB is slow to initialize:

    pool:
      engine_start_timeout: 240  # increase from default 120 seconds
  5. Check system resources: Ensure sufficient disk space and RAM. MATLAB engine startup requires ~500MB per instance.

  6. Verify no MATLAB processes are hung: Kill stray MATLAB processes:

    killall matlab  # macOS/Linux
    taskkill /IM MATLAB.exe  # Windows

Pool Startup and Scaling Problems

Symptom: Pool fails to initialize, engines won't scale up, or queue_max_size exceeded

Solutions:

  1. Check min/max engine configuration:

    pool:
      min_engines: 2      # server starts this many at launch
      max_engines: 10     # capped at 4 on macOS by default

    On macOS, MATLAB has a hard limit of ~4 concurrent engine instances. Set accordingly:

    pool:
      max_engines: 4  # macOS limit
  2. Increase queue size if jobs are rejected during high demand:

    pool:
      queue_max_size: 100  # increase from default 50
  3. Check proactive warmup threshold:

    pool:
      proactive_warmup_threshold: 0.8  # triggers new engine when pool >80% busy
  4. Monitor pool health: Call get_pool_status to see available/busy/max engines. If all engines are stuck "busy", check for hung jobs.

  5. Scale down idle engines:

    pool:
      scale_down_idle_timeout: 900  # idle engines removed after 15 minutes

Timeout Tuning

Symptom: Jobs timeout prematurely, or sync operations block for too long

Solutions:

  1. Tune sync timeout (promotes long jobs to async automatically):

    execution:
      sync_timeout: 30  # seconds before becoming async (default: 30)

    Increase if you want more operations to complete synchronously:

    execution:
      sync_timeout: 60  # allow up to 60 seconds for sync operations
  2. Set absolute max execution time per job:

    execution:
      max_execution_time: 86400  # 24 hours (hard limit)
  3. Configure graceful shutdown drain timeout:

    server:
      drain_timeout_seconds: 300  # wait up to 5 minutes for running jobs to finish
  4. Session timeout for inactive sessions:

    sessions:
      session_timeout: 3600  # cleanup after 1 hour of inactivity
  5. Health check interval (detects hung engines):

    pool:
      health_check_interval: 60  # ping engines every 60 seconds

Logging Configuration

Enable debug logging to troubleshoot issues:

  1. In config.yaml:

    server:
      log_level: "debug"  # debug | info | warning | error
      log_file: "./logs/server.log"
  2. Via environment variable:

    export MATLAB_MCP_SERVER_LOG_LEVEL=debug
    matlab-mcp
  3. View logs:

    tail -f ./logs/server.log  # real-time log tail
  4. Structured logging includes:

    • Engine lifecycle events (start, crash, recovery)
    • Job execution (queue, start, progress, completion)
    • Pool scaling decisions
    • Security violations (blocked functions)
    • Performance metrics
  5. Log rotation: Logs are stored in ./logs/server.log. For production, configure external log aggregation.

Docker Networking Issues

Symptom: Docker container fails to connect to MATLAB, or port binding errors

Solutions:

  1. Mount MATLAB correctly:

    docker run -p 8765:8765 -p 8766:8766 \
      -v /path/to/MATLAB:/opt/matlab:ro \
      -e MATLAB_MCP_POOL_MATLAB_ROOT=/opt/matlab \
      matlab-mcp

    Verify the mount exists on your host:

    ls /path/to/MATLAB/bin/matlab  # should exist
  2. Check port bindings:

    # SSE mode (multi-user) — port 8765 for MCP, 8766 for dashboard
    docker run -p 8765:8765 -p 8766:8766 ...
    
    # Verify port is accessible
    curl http://localhost:8765/sse
  3. Use docker-compose for easier configuration:

    version: '3'
    services:
      matlab-mcp:
        build: .
        ports:
          - "8765:8765"
          - "8766:8766"
        volumes:
          - /path/to/MATLAB:/opt/matlab:ro
        environment:
          MATLAB_MCP_POOL_MATLAB_ROOT: /opt/matlab
          MATLAB_MCP_SERVER_TRANSPORT: sse

    Then: docker compose up

  4. Debug container logs:

    docker logs <container_id>  # see startup errors
    docker exec <container_id> cat /logs/server.log  # access log file
  5. Network mode for advanced setups:

    # Use host network (Linux only)
    docker run --network host ...
  6. MATLAB license in Docker: If using network licensing:

    docker run -e MLM_LICENSE_FILE=<license_server> ...

Blocked Function Error

Symptom: BlockedFunctionError: Function 'system' is blocked

Explanation: The security validator blocks dangerous functions by default to prevent code injection and unauthorized system access.

Solutions:

  1. Use MATLAB-native alternatives (recommended):

    • File operations: dir, mkdir, copyfile, movefile, delete
    • Environment: getenv, setenv
    • Shell execution: Use MATLAB functions instead of system()
  2. Remove specific functions from blocklist:

    security:
      blocked_functions:
        - "system"
        - "unix"
        - "dos"
        - "!"
        - "eval"
        # Remove entries you trust
  3. Disable blocklist entirely (not recommended for shared/untrusted servers):

    security:
      blocked_functions_enabled: false
  4. Default blocked functions:

    system, unix, dos, !, eval, feval, evalc, evalin, assignin, perl, python
    

    These are blocked because they allow shell command execution or dynamic code evaluation.

Job Stuck in "Running" State

Symptom: Job never completes, progress stops updating, or workspace locks

Solutions:

  1. Cancel the job:

    Call cancel_job with the job ID
    

    Or via monitoring:

    curl http://localhost:8766/health  # see active jobs
  2. Check max execution time:

    execution:
      max_execution_time: 86400  # 24h hard limit

    Jobs are automatically terminated after this duration.

  3. Add progress reporting to long jobs:

    for i = 1:n
        % do work...
        if mod(i, 100) == 0
            mcp_progress(__mcp_job_id__, i/n*100, sprintf('Iteration %d/%d', i, n));
        end
    end
  4. Check for infinite loops or blocking I/O:

    • Infinite loops (while true without exit condition)
    • Waiting for user input (input(), pause())
    • Blocking network/file operations
  5. Engine affinity may lock workspace: If engine_affinity: true, the same engine is reused and job state persists. Check if previous job left workspace in bad state:

    execution:
      engine_affinity: false  # disable to use fresh engine each time
  6. Workspace isolation:

    execution:
      workspace_isolation: true  # clear workspace between jobs

Large Result Truncated or Saved to File

Symptom: Output is cut off, saved to file instead of returned inline, or matrix data missing

Explanation: Results exceeding max_inline_text_length (50,000 chars) or large_result_threshold (10,000 elements) are automatically saved to file to avoid oversized responses.

Solutions:

  1. Increase inline limits:

    output:
      max_inline_text_length: 100000  # chars
      large_result_threshold: 50000   # elements for matrices/tables
  2. Use list_files + read_data to access full output:

    1. Call list_files to find the result file
    2. Call read_data(filename, format: 'raw') to get full data
    
  3. Summarize large data in MATLAB:

    large_matrix = randn(10000, 1000);
    % Return summary instead of full matrix
    summary = struct('size', size(large_matrix), 'mean', mean(large_matrix, 1), 'saved_to', 'data.mat');
    disp(summary);
    save data.mat large_matrix
  4. Check output format config:

    output:
      static_image_format: "png"  # png | jpg | svg
      thumbnail_enabled: true

Plotly Conversion Failed

Symptom: No interactive plot returned, only static PNG, or plot appears blank

Explanation: The Plotly converter (mcp_extract_props.m) supports common plot types. Complex multi-axis plots, custom graphics, or unsupported chart types may not convert.

Solutions:

  1. Check supported types:

    • line, scatter, bar, histogram, surface, image
    • Subplots (subplot, tiledlayout)
    • Multiple axes with legends
  2. Simplify complex plots:

    • Split multi-axis plots into separate figures
    • Use standard MATLAB plotting functions (plot, scatter, bar)
    • Avoid custom graphics objects
  3. Verify Plotly conversion is enabled:

    output:
      plotly_conversion: true  # default: true
  4. Static fallback is always available: Even if Plotly conversion fails, a PNG image is generated and returned.

  5. Disable Plotly for static-only output:

    output:
      plotly_conversion: false  # use PNG only
      static_image_format: "png"

"Max Engines Exceeded" Warning on macOS

Symptom: Warning about max engines on macOS, server crashes with too many engines

Explanation: MATLAB on macOS has a hard limit of ~4 concurrent engine instances due to licensing constraints.

Solution: Cap max_engines on macOS:

pool:
  max_engines: 4  # macOS limit

Connection Refused (SSE)

Symptom: Client can't connect to http://localhost:8765/sse

Solutions:

  1. Verify server is running in SSE mode:

    matlab-mcp --transport sse
    # or in config.yaml:
    # server:
    #   transport: "sse"
  2. Check port configuration:

    server:
      port: 8765  # default SSE port
  3. Verify port is listening:

    netstat -an | grep 8765  # macOS/Linux
    netstat -ano | findstr :8765  # Windows
  4. Check host binding for remote access:

    server:
      host: "0.0.0.0"  # listen on all interfaces (remote)
      # or
      host: "127.0.0.1"  # localhost only (local)
  5. Firewall: Ensure port 8765 is open:

    # macOS
    sudo lsof -i :8765
    
    # Linux
    sudo ufw allow 8765
  6. Check dashboard/monitoring port (8766):

    curl http://localhost:8766/health  # should return health JSON

Enable Debug Logging

To troubleshoot complex issues, enable debug logging:

  1. Set log level to debug:

    server:
      log_level: "debug"
      log_file: "./logs/server.log"
  2. Or use environment variable:

    export MATLAB_MCP_SERVER_LOG_LEVEL=debug
    matlab-mcp
  3. Watch logs in real-time:

    tail -f ./logs/server.log
  4. Debug log includes:

    • Full request/response bodies for MCP tools
    • MATLAB engine lifecycle (start, crash, recovery)
    • Job queue operations
    • Pool scaling decisions
    • Security checks (blocked functions)
    • Performance metrics
    • Network events
  5. For Docker, capture logs:

    docker logs -f <container_id>
  6. Performance profiling: Call get_server_metrics to see detailed timing:

    {
      "pool": {"total_engines": 10, "busy_engines": 3},
      "jobs": {"total": 42, "running": 3, "completed": 39},
      "sessions": {"active": 5},
      "system": {"cpu_percent": 45.2, "memory_mb": 2048}
    }
  7. Health checks:

    curl http://localhost:8766/health

    Returns detailed health status (healthy/degraded/unhealthy) with issue detection.

Clone this wiki locally