-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Symptom: Engine start timeout or matlab.engine not found
Solutions:
-
Verify MATLAB Engine API is installed:
python -c "import matlab.engine; print('OK')" -
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 .
-
Check MATLAB version: Must be 2020b or later.
-
Check PATH and matlab_root: MATLAB must be on your system PATH, or set
matlab_rootexplicitly in config:pool: matlab_root: "/Applications/MATLAB_R2024a.app"
Or via environment variable:
export MATLAB_MCP_POOL_MATLAB_ROOT="/Applications/MATLAB_R2024a.app"
-
Increase timeout: If MATLAB is slow to start:
pool: engine_start_timeout: 300 # 5 minutes
Or:
export MATLAB_MCP_POOL_ENGINE_START_TIMEOUT=300 -
Check engine pool health: Use
get_pool_statustool to verify pool is running:% In your MCP client get_pool_status()
Symptom: min_engines not reaching desired count, or all engines fail to start
Solutions:
-
Verify minimum configuration:
pool: min_engines: 2 max_engines: 10
The server attempts to warm
min_engineson startup. Check logs for failures. -
Check logs for startup errors:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug matlab-mcp 2>&1 | tee startup.log
Look for
Engine startup failedmessages and the underlying error. -
Verify MATLAB installation integrity:
matlab -r "quit" # Can MATLAB start at all?
-
On macOS, verify engine limit: MATLAB on macOS has a hard limit of ~4 concurrent engines. The server caps
max_enginesat 4 on macOS automatically, but if you override it, engines beyond 4 will fail:pool: max_engines: 4 # recommended on macOS
-
Check queue isn't full: If
queue_max_sizeis exceeded, new requests are rejected:pool: queue_max_size: 50
Symptom: ConnectionError, OSError, or matlab.engine.EngineError during execution
Solutions:
-
Engine crashed or disconnected: Check server logs for crash indicators:
tail -f logs/server.log | grep -i "engine\|crash\|error"
-
Workspace corruption: If engine_affinity is enabled and workspace isolation fails, reset the workspace:
execution: workspace_isolation: true engine_affinity: false # disable affinity if seeing persistent errors
-
Too many engines for system resources: Reduce
max_enginesif you see memory/resource exhaustion:pool: max_engines: 4
-
Network issue (SSE transport only): Verify host and port are correct and reachable:
curl http://localhost:8765/health
Symptom: Jobs timeout unexpectedly, or jobs run synchronously when they should be async
Tuning Guide:
-
Sync vs Async Promotion: By default, fast jobs (<30s) return inline. Slower jobs get a job ID and run async:
execution: sync_timeout: 30 # seconds
To make promotions more aggressive:
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=10 -
Hard execution limit per job:
execution: max_execution_time: 86400 # 24h hard limit
Jobs exceeding this are forcibly cancelled.
-
Engine startup timeout:
pool: engine_start_timeout: 120 # 2 minutes
If engines take longer to start, increase this.
-
Session timeout (inactivity):
sessions: session_timeout: 3600 # 1 hour
Sessions are cleaned up after this much inactivity.
-
Scale-down idle timeout:
pool: scale_down_idle_timeout: 900 # 15 minutes
Idle engines above
min_enginesare shut down after this duration. -
Server shutdown drain timeout:
server: drain_timeout_seconds: 300 # 5 minutes
Max wait for running jobs to complete during graceful shutdown.
Enable Debug Logging:
-
Via config file:
server: log_level: "debug" log_file: "./logs/server.log"
-
Via environment variable:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug matlab-mcp -
View logs in real-time:
tail -f logs/server.log
-
Log levels:
debug|info|warning|error-
debug: Detailed execution trace, all API calls, pool state changes -
info: Server startup, job status, pool scaling events -
warning: Non-fatal issues, timeouts, recovery attempts -
error: Failures, exceptions, crash details
-
-
Error log tool: Use
get_error_logtool to retrieve recent errors programmatically:get_error_log(limit=50) % last 50 errors
Symptom: Client can't connect to server in Docker, or server can't find MATLAB
Solutions:
-
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 --transport sse
Verify the host path exists and contains MATLAB binaries.
-
Expose ports: For SSE transport, ensure both ports are exposed:
-p 8765:8765 # SSE endpoint -p 8766:8766 # dashboard/health endpoint
-
Host binding: By default, the server binds to
0.0.0.0(all interfaces) inside the container. To restrict:server: host: "127.0.0.1" # localhost only
-
Network mode: For local access to other services, use host network (Linux only):
docker run --network host \ -v /path/to/MATLAB:/opt/matlab:ro \ matlab-mcp --transport sse
-
Check container logs:
docker logs <container_id>
-
Verify MATLAB in container:
docker exec <container_id> /opt/matlab/bin/matlab -r "quit"
-
Use docker-compose: Edit
docker-compose.ymlto set your MATLAB path:services: matlab-mcp: build: . ports: - "8765:8765" - "8766:8766" volumes: - /path/to/MATLAB:/opt/matlab:ro environment: MATLAB_MCP_POOL_MATLAB_ROOT: /opt/matlab
Symptom: Warning about max engines on macOS
Explanation: MATLAB on macOS has a hard limit of ~4 concurrent engine instances. The server automatically caps max_engines at 4 on macOS, but warns if you try to override it.
Solution: Accept the macOS limit:
pool:
max_engines: 4Or verify your macOS version supports more (newer versions may allow more).
Symptom: Client can't connect to http://localhost:8765/sse
Solutions:
-
Check the server is running:
matlab-mcp --transport sse
-
Check port: Default is 8765. Verify in config or change:
server: port: 8765
Or:
export MATLAB_MCP_SERVER_PORT=8765 -
Check host binding:
server: host: "0.0.0.0" # all interfaces
Use
127.0.0.1for local-only access,0.0.0.0for remote. -
Firewall: Ensure port 8765 (and 8766 for dashboard) is open:
netstat -an | grep 8765 -
Verify server is healthy:
curl http://localhost:8765/health
Symptom: BlockedFunctionError: Function 'system' is blocked
Explanation: The security validator blocks dangerous functions by default to prevent code injection and system compromise.
Solutions:
-
Use MATLAB-native alternatives instead of
system():- File operations:
dir,mkdir,copyfile,movefile,fileattrib - Environment:
getenv,setenv - Shell commands: use MATLAB equivalents (e.g.,
pwd,cd)
- File operations:
-
Disable blocklist (only for trusted/isolated servers):
security: blocked_functions_enabled: false
Or:
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false -
Remove specific functions from blocklist:
security: blocked_functions: - "unix" - "dos" - "!" - "eval" # "system" removed
-
Default blocklist includes:
system,unix,dos,!,eval,feval,evalc,evalin,assignin,perl,python
Symptom: Job never completes, progress stops updating
Solutions:
-
Cancel the job: Use
cancel_jobtool:cancel_job(job_id="abc123")
-
Check max execution time:
execution: max_execution_time: 86400 # 24h hard limit
Jobs exceeding this are forcibly cancelled.
-
Monitor job status:
get_job_status(job_id="abc123")
Returns current status and progress percentage.
-
Check MATLAB code: Is there an infinite loop? Add progress reporting to debug:
for i = 1:n mcp_progress(__mcp_job_id__, i/n*100, sprintf('Iteration %d', i)); % ... work ... end
-
Check engine health:
get_pool_status()
Verify the engine running this job is healthy.
Symptom: No interactive plot returned, only text output or static PNG
Explanation: The Plotly converter (mcp_extract_props.m) supports common plot types. Complex, custom, or unsupported plot types may not convert, but a static PNG fallback is always generated.
Solutions:
-
Check supported types:
- Line, scatter, bar, histogram, surface, contour, image
- Multi-axis plots with proper labeling
- Standard MATLAB plot functions (
plot,scatter,bar,surf, etc.)
-
Simplify the plot: Complex multi-axis layouts, custom graphics objects, or specialized toolbox plots may not convert. Simplify if possible.
-
Static fallback: A PNG image is always generated even if Plotly conversion fails. Check the result for the static image.
-
Disable Plotly conversion: Fall back to static images only:
output: plotly_conversion: false
Or:
export MATLAB_MCP_OUTPUT_PLOTLY_CONVERSION=false -
Check image format:
output: static_image_format: "png" # png | jpg | svg static_image_dpi: 150
Symptom: Output is cut off, saved to file, or missing from result
Explanation: Results exceeding max_inline_text_length (50,000 chars) or large_result_threshold (10,000 elements) are saved to file instead of returned inline to avoid overwhelming clients.
Solutions:
-
Increase limits:
output: max_inline_text_length: 100000 large_result_threshold: 50000
Or:
export MATLAB_MCP_OUTPUT_MAX_INLINE_TEXT_LENGTH=100000 export MATLAB_MCP_OUTPUT_LARGE_RESULT_THRESHOLD=50000
-
Use file-based access:
get_job_result(job_id="abc123") % retrieves saved file reference list_files() # see all output files read_data(filename="result.mat") # read file contents
-
Summarize results before returning: In your MATLAB code, use
summary()orheight()/size()to get statistics instead of full data.
Symptom: Variables leak between jobs, or workspace not reset
Solutions:
-
Verify workspace isolation is enabled:
execution: workspace_isolation: true
-
Disable engine affinity if seeing issues: Engine affinity pins sessions to engines for persistence, but can cause workspace corruption:
execution: engine_affinity: false # recommended
-
Check startup commands: These run on every engine start and workspace reset:
workspace: startup_commands: - "format long" - "addpath('/shared/libs')"
-
Verify custom paths are added:
workspace: default_paths: - "/shared/custom_libs" - "/shared/data"
These are added to MATLAB path on engine start.
Symptom: check_code tool returns no warnings, or code issues not caught
Solutions:
-
Verify code checker is enabled:
code_checker: enabled: true auto_check_before_execute: false # manual only by default
-
Enable auto-check before execution:
code_checker: auto_check_before_execute: true
-
Configure severity levels:
code_checker: severity_levels: ["error", "warning"]
-
Manually check code:
check_code(code="x = 1\ny = x+1")
Symptom: Dashboard not accessible, or health status unclear
Solutions:
-
Verify monitoring is enabled:
monitoring: enabled: true dashboard_enabled: true http_port: 8766
-
Access dashboard:
- Stdio transport:
http://localhost:8766/dashboard - SSE transport:
http://localhost:8765/dashboard
- Stdio transport:
-
Check health endpoint:
curl http://localhost:8766/health # stdio curl http://localhost:8765/health # sse
-
Use health tool:
get_server_health() get_server_metrics()
-
Check retention and database:
monitoring: sample_interval: 10 # seconds retention_days: 7 # historical data retention db_path: "./monitoring/metrics.db"