-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Symptom: Engine start timeout, matlab.engine not found, or MATLAB failed to start
Solutions:
-
Verify MATLAB Engine API is installed:
python -c "import matlab.engine; print('OK')"If this fails, the Engine API is not installed or not on your Python path.
-
Install the Engine API:
# macOS cd /Applications/MATLAB_R2024a.app/extern/engines/python pip install . # Windows cd "C:\Program Files\MATLAB\R2024a\extern\engines\python" pip install .
-
Check MATLAB version: Must be 2020b or later.
-
Set MATLAB root explicitly: If auto-detection fails, configure the path in
config.yaml:pool: matlab_root: "/Applications/MATLAB_R2024a.app" # macOS # matlab_root: "C:\\Program Files\\MATLAB\\R2024a" # Windows
Or via environment variable:
export MATLAB_MCP_POOL_MATLAB_ROOT=/Applications/MATLAB_R2024a.app -
Increase engine start timeout: If MATLAB is slow to start on your system:
pool: engine_start_timeout: 300 # 5 minutes (default: 120)
Or:
export MATLAB_MCP_POOL_ENGINE_START_TIMEOUT=300 -
Check MATLAB license: Ensure your MATLAB license allows headless execution. Run
matlab -batch "disp('OK')"to verify.
Symptom: Pool fails to initialize, or engines die shortly after starting
Solutions:
-
Check pool configuration:
pool: min_engines: 2 # start with 2 warm engines max_engines: 10 # hard ceiling health_check_interval: 60 # seconds between pings
-
Enable debug logging to see engine startup details:
server: log_level: "debug" log_file: "./logs/server.log"
Check the log file for engine startup errors.
-
Check system resources: Each MATLAB engine uses ~500MB–1GB RAM. Ensure you have enough memory:
free -h # Linux/macOS wmic OS get TotalVisibleMemorySize,FreePhysicalMemory # Windows
-
Increase health check timeout: If engines fail health checks due to system load:
pool: health_check_interval: 120 # 2 minutes instead of 1
-
macOS-specific: MATLAB has a limit of ~4 concurrent engine instances on macOS. Configure:
pool: max_engines: 4
Symptom: Jobs are timing out, or operations that should be async are promoted too early
By default, jobs run synchronously (blocking) for up to 30 seconds. If they exceed this time, they are promoted to asynchronous (job ID returned, agent polls for results).
To increase sync timeout (for operations that should complete quickly but need more time):
execution:
sync_timeout: 60 # 60 seconds instead of 30Or:
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=60Symptom: Long-running jobs are killed after 24 hours
The max_execution_time is a hard ceiling. Increase if your jobs legitimately need more time:
execution:
max_execution_time: 259200 # 72 hours instead of 24Or:
export MATLAB_MCP_EXECUTION_MAX_EXECUTION_TIME=259200If you need workspace persistence across calls (to share variables), disable isolation:
execution:
workspace_isolation: true # default: sessions get fresh workspaces
engine_affinity: true # pin session to same engineThis pins the session to the same engine and skips workspace reset between calls.
server:
log_level: "debug"
log_file: "./logs/server.log"Or via environment variable:
export MATLAB_MCP_SERVER_LOG_LEVEL=debugLogs are written to ./logs/server.log (relative to working directory) or the path specified in config.
-
debug— Detailed engine lifecycle, code execution, result conversion -
info— Job status, pool events, health checks (default) -
warning— Timeouts, blocked functions, conversion failures -
error— Exceptions, startup failures
[DEBUG] Engine 1 started (PID 12345)
[DEBUG] Job job_abc123 executing: execute_code
[DEBUG] Result size: 1.2 MB, saving to file
[ERROR] BlockedFunctionError: Function 'system' is blocked
[WARNING] Plotly conversion failed for figure, falling back to PNG
Symptom: Cannot connect to server from Docker container, or MATLAB engine fails to start in Docker
-
SSE Transport (multi-user):
docker run -p 8765:8765 -p 8766:8766 \ -v /path/to/MATLAB:/opt/matlab:ro \ -e MATLAB_MCP_POOL_MATLAB_ROOT=/opt/matlab \ -e MATLAB_MCP_SERVER_TRANSPORT=sse \ -e MATLAB_MCP_SERVER_HOST=0.0.0.0 \ matlab-mcp
Connect to
http://localhost:8765/ssefrom the host. -
MATLAB Root Path: MATLAB must be mounted into the container and configured:
docker run \ -v /usr/local/MATLAB/R2024a:/opt/matlab:ro \ -e MATLAB_MCP_POOL_MATLAB_ROOT=/opt/matlab \ matlab-mcp
Ensure the mount path matches the
MATLAB_MCP_POOL_MATLAB_ROOTenvironment variable. -
Docker Compose: Edit
docker-compose.ymlto mount your MATLAB path:services: matlab-mcp: build: . ports: - "8765:8765" - "8766:8766" volumes: - /usr/local/MATLAB/R2024a:/opt/matlab:ro environment: MATLAB_MCP_POOL_MATLAB_ROOT: /opt/matlab MATLAB_MCP_SERVER_TRANSPORT: sse
Then:
docker compose up
-
Check MATLAB is accessible:
docker exec matlab-mcp ls /opt/matlab/binIf this fails, the mount path is wrong.
| Symptom | Cause | Solution |
|---|---|---|
matlab.engine not found |
Engine API not installed in container | Install Engine API in Dockerfile before running |
MATLAB failed to start |
MATLAB path not mounted | Check -v mount and MATLAB_MCP_POOL_MATLAB_ROOT
|
Connection refused |
Server not binding to 0.0.0.0
|
Set MATLAB_MCP_SERVER_HOST=0.0.0.0
|
| Container exits immediately | MATLAB license failure | Check license server is accessible, or use license server URL |
Option 1: Via config.yaml
server:
log_level: "debug"
log_file: "./logs/server.log"Option 2: Via environment variable
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
matlab-mcpOption 3: Both config and environment (environment takes precedence)
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
export MATLAB_MCP_SERVER_LOG_FILE=/var/log/matlab-mcp.log
matlab-mcp# Follow logs in real-time
tail -f ./logs/server.log
# Search for errors
grep ERROR ./logs/server.log
# Last 50 lines
tail -50 ./logs/server.logEnable debug logging to troubleshoot:
-
Engine lifecycle:
Engine X started,Engine X health check,Engine X shutdown -
Code execution:
Job Y executing: execute_code,Result size,Conversion time -
Pool management:
Queue depth,Scaling decision,Engine allocation -
Plot conversion:
Plotly conversion,Axes found,Line data extracted -
Security:
BlockedFunctionError,Function validation
Symptom: BlockedFunctionError: Function 'system' is blocked
Explanation: The security validator blocks dangerous functions by default to prevent shell injection and file system abuse.
Solutions:
-
Use MATLAB-native alternatives instead of blocked functions:
-
Instead of
system()orunix(): Usedir(),mkdir(),copyfile(),movefile(),delete()for file ops -
Instead of
eval()orfeval(): Use named function calls orstr2func() -
Instead of
perl()orpython(): Use MATLAB native libraries or file I/O
-
Instead of
-
Remove specific functions from blocklist (for trusted environments):
security: blocked_functions: - "eval" - "feval" # Remove 'system' to allow shell commands
-
Disable blocklist entirely (not recommended for shared servers):
security: blocked_functions_enabled: false
Symptom: Job never completes, progress stops updating
Solutions:
-
Check job status: Ask the agent to call
get_job_statuswith the job ID. Look forstate: "running"and check the progress percentage. -
Cancel the job:
# Agent calls this: cancel_job(job_id="job_abc123")
-
Check max execution time: If the job has been running longer than
max_execution_time, it will be killed:execution: max_execution_time: 86400 # 24h hard limit
-
Check MATLAB code: Is there an infinite loop or blocking operation? Add progress reporting to debug:
for i = 1:n % ... computation ... mcp_progress(__mcp_job_id__, i/n*100, sprintf('Iteration %d/%d', i, n)); end
-
Check pool health: Call
get_pool_statusto see if engines are stuck or unhealthy. Restart the server if needed.
Symptom: No interactive plot returned, only text output or static PNG
Explanation: The Plotly converter (mcp_extract_props.m) supports common plot types. Some complex or custom plot types may not convert.
Solutions:
-
Check supported types:
- ✅ Supported: line, scatter, bar, area, histogram, surface, image, subplots (
subplot/tiledlayout) - ❌ Limited: custom graphics objects, 3D surface with complex lighting, contour plots with custom rendering
- ✅ Supported: line, scatter, bar, area, histogram, surface, image, subplots (
-
Simplify the plot: Complex multi-axis plots or heavy use of graphics properties may not convert. Try breaking into simpler subplots.
-
Static fallback: A PNG image is always generated as fallback, even if Plotly conversion fails. The agent will see both.
-
Disable Plotly conversion: Fall back to static images only:
output: plotly_conversion: false
Or:
export MATLAB_MCP_OUTPUT_PLOTLY_CONVERSION=false -
Check logs for conversion errors: Enable debug logging to see why conversion failed:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug # Look for: "Plotly conversion failed"
Symptom: Output is cut off, saved to file, or matrix data is not returned inline
Explanation: Results exceeding max_inline_text_length (text) or large_result_threshold (tabular/matrix data) are saved to file instead of returned inline to keep responses manageable.
Solutions:
-
Increase limits:
output: max_inline_text_length: 100000 # default: 50000 large_result_threshold: 50000 # default: 10000
Or:
export MATLAB_MCP_OUTPUT_MAX_INLINE_TEXT_LENGTH=100000 export MATLAB_MCP_OUTPUT_LARGE_RESULT_THRESHOLD=50000
-
Access the full result: If data is saved to file, the agent gets a message like
Result saved to file: results/job_abc123_output.csv. Use:# Agent calls: read_data(filename="results/job_abc123_output.csv", format="raw")
-
Use
list_files+get_job_result:# Agent calls: list_files() # see available files get_job_result(job_id="job_abc123") # get full result metadata with file paths
Symptom: Client can't connect to http://localhost:8765/sse
Solutions:
-
Check the server is running:
matlab-mcp --transport sse # Should print: "Server running on http://0.0.0.0:8765" -
Check port binding: Verify port 8765 is open and no other service is using it:
# macOS/Linux lsof -i :8765 # Windows netstat -ano | findstr :8765
If in use, change the port in
config.yaml:server: port: 8766
-
Check host binding: For remote access, use
0.0.0.0:server: host: "0.0.0.0" # accessible from anywhere
For local-only access, use
127.0.0.1:server: host: "127.0.0.1"
-
Check firewall: Ensure port 8765 (and 8766 for dashboard) is open:
# macOS sudo lsof -i :8765 # Linux (iptables) sudo iptables -A INPUT -p tcp --dport 8765 -j ACCEPT # Windows Firewall netsh advfirewall firewall add rule name="MATLAB MCP" dir=in action=allow protocol=tcp localport=8765
-
Check logs: Enable debug logging to see connection errors:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
Symptom: Warning about max engines, or only 4 engines start
Explanation: MATLAB on macOS has a system-level limit of approximately 4 concurrent engine instances. The server respects this limit by default.
Solution: Configure max_engines: 4 on macOS in config.yaml:
pool:
max_engines: 4Or:
export MATLAB_MCP_POOL_MAX_ENGINES=4The server will not attempt to exceed this limit. If you need more concurrent MATLAB sessions on macOS, consider running multiple server instances or using a Linux/Windows machine.
Symptom: Variables from previous calls are not available, or workspace is cleared unexpectedly
Explanation: By default, each job gets a fresh workspace for isolation. To persist variables across calls:
Solutions:
-
Enable workspace persistence:
execution: workspace_isolation: false engine_affinity: true # pin to same engine
-
Access workspace between calls: Use
get_workspace()to see current variables, or have the agent save/load variables:% Save to file save('my_vars.mat', 'x', 'y', 'z'); % Load in next call load('my_vars.mat');
-
Add startup commands: Commands in
workspace.startup_commandsrun on engine start and after reset:workspace: startup_commands: - "format long" - "addpath('/shared/custom_libs')"