-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
# 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:**
```bash
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 R2022b 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 on Windows: # matlab_root: "C:\\Program Files\\MATLAB\\R2024a"
-
Increase engine startup timeout: If MATLAB is slow to start on your system:
pool: engine_start_timeout: 300 # 5 minutes (default 120 seconds)
-
Check engine health: Use the health check tool to diagnose engine issues:
# Call get_server_health to see detailed engine diagnostics -
Enable debug logging (see section below) to see exactly where the connection fails.
Symptom: Server starts but engines fail to initialize, or pool never reaches min_engines
Solutions:
-
Check minimum engines setting:
pool: min_engines: 2 # default max_engines: 10
Ensure
min_engines ≤ max_engines. -
Check queue size: If many jobs are queued immediately, increase:
pool: queue_max_size: 50 # default
-
Monitor pool startup: Call
get_pool_statusafter starting the server to see:- Available engines
- Busy engines
- Engines being started
- Queue length
-
Verify workspace isolation:
execution: workspace_isolation: true # each session gets its own workspace
-
Check for startup command errors: If
workspace.startup_commandshave syntax errors, engines may fail to initialize:workspace: startup_commands: - "format long" - "warning('off', 'MATLAB:mir_warning_maybe_uninitialized_temporary')"
Symptom: Warning about max engines on macOS, or engines fail to start beyond ~4
Explanation: MATLAB on macOS has a hard limit of ~4 concurrent engine instances due to licensing constraints.
Solution: Cap max_engines at 4 on macOS:
pool:
max_engines: 4Symptom: Fast operations are being promoted to async jobs unnecessarily
Tuning:
execution:
sync_timeout: 30 # seconds before promoting to async (default 30)Increase this if your network is slow or MATLAB operations commonly take 20-30 seconds:
execution:
sync_timeout: 60 # wait up to 60 seconds for sync responseSymptom: Engine start timeout errors, or slow MATLAB startup
Tuning:
pool:
engine_start_timeout: 120 # seconds (default 120)Increase on slow systems or with large startup_commands:
pool:
engine_start_timeout: 300 # 5 minutes for heavily customized MATLABSymptom: Dead engines not detected promptly
Tuning:
pool:
health_check_interval: 60 # seconds between pings (default 60)Decrease for faster failure detection:
pool:
health_check_interval: 30Symptom: Idle engines staying alive too long
Tuning:
pool:
scale_down_idle_timeout: 900 # seconds (default 15 minutes)Decrease to free resources faster:
pool:
scale_down_idle_timeout: 300 # 5 minutesSymptom: Sessions being cleaned up while agent is still using them
Tuning:
sessions:
session_timeout: 3600 # seconds of inactivity (default 1 hour)Increase for long-running interactive sessions:
sessions:
session_timeout: 86400 # 24 hoursSymptom: Completed job results disappearing too quickly
Tuning:
sessions:
job_retention_seconds: 86400 # how long to keep metadata (default 24h)Increase to retain results longer:
sessions:
job_retention_seconds: 604800 # 7 daysSymptom: Long-running jobs killed unexpectedly
Tuning:
execution:
max_execution_time: 86400 # seconds (default 24 hours)Increase for very long simulations:
execution:
max_execution_time: 604800 # 7 daysDebug logging shows detailed server activity, MATLAB communication, and error traces.
In config.yaml:
server:
log_level: "debug"
log_file: "./logs/server.log"Via environment variable:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
matlab-mcpCheck the log file:
tail -f ./logs/server.log| Level | Use Case |
|---|---|
debug |
Detailed MATLAB communication, pool state changes, every API call — very verbose |
info |
Normal operation, job starts/completions, pool scaling events |
warning |
Recoverable issues, blocklist violations, conversion failures |
error |
Engine crashes, code execution failures, critical issues |
The server doesn't rotate logs automatically. For long-running servers, manage log size:
# On Linux/macOS
tail -f ./logs/server.log | tee -a ./logs/archived.log > /dev/null &
# Or use logrotate (Linux)
cat > /etc/logrotate.d/matlab-mcp << EOF
./logs/server.log {
daily
rotate 7
compress
delaycompress
}
EOFLogs include timestamps, levels, and module names:
2024-01-15 10:23:45,123 - matlab_mcp.pool - DEBUG - Engine-1 health check: OK
2024-01-15 10:24:12,456 - matlab_mcp.executor - INFO - Job j_abc123 completed in 15.2s
2024-01-15 10:25:33,789 - matlab_mcp.security - WARNING - Blocked function 'system' attempted
By default, the SSE transport runs on ports 8765 (MCP) and 8766 (HTTP dashboard).
Expose ports for docker run:
docker run -p 8765:8765 -p 8766:8766 matlab-mcpOr in docker-compose.yml:
services:
matlab-mcp:
ports:
- "8765:8765"
- "8766:8766"For local-only access (docker host only):
docker run -p 127.0.0.1:8765:8765 matlab-mcpFor remote access (external clients):
docker run -p 0.0.0.0:8765:8765 matlab-mcpOr in config.yaml inside the container:
server:
host: "0.0.0.0" # bind to all interfaces
port: 8765Mount your MATLAB installation to a known path:
docker run -v /path/to/MATLAB:/opt/matlab:ro \
-e MATLAB_MCP_POOL_MATLAB_ROOT=/opt/matlab \
matlab-mcpOr mount your config.yaml:
docker run -v /path/to/config.yaml:/app/config.yaml \
matlab-mcpSymptom: Client can't connect to http://localhost:8765 from outside the container
Solutions:
-
Use container IP instead of localhost:
docker inspect <container-id> | grep IPAddress # Connect to that IP address
-
Use
hostnetwork mode (Linux only):docker run --network host matlab-mcp
-
Check firewall: Ensure ports 8765/8766 are open on your host.
-
Use docker-compose with named services:
services: matlab: image: matlab-mcp ports: - "8765:8765"
Then connect to
matlab:8765from other containers.
If using floating license servers, ensure MATLAB can reach the license server from inside the container:
# Pass through network
docker run --network bridge \
-e MLM_LICENSE_FILE=port@licenseserver.local \
matlab-mcpOr mount your license file:
docker run -v /path/to/license.dat:/opt/matlab/licenses/license.dat:ro \
matlab-mcpSymptom: Client can't connect to http://localhost:8765/sse or http://localhost:8766
Solutions:
-
Check the server is running:
matlab-mcp --transport sse
Look for output like:
Starting SSE server on http://0.0.0.0:8765 -
Check port availability:
# macOS/Linux lsof -i :8765 # Windows netstat -ano | findstr :8765
If the port is in use, either kill the process or change the port in config.yaml:
server: port: 8767 # use a different port
-
Check host binding: By default, the server binds to
0.0.0.0(all interfaces). For local-only access:server: host: "127.0.0.1"
For remote access:
host: "0.0.0.0"
-
Check firewall: Ensure port 8765 (and 8766 for dashboard) are open:
# macOS sudo lsof -i :8765 # Linux sudo ufw allow 8765
-
Test endpoint directly:
curl http://localhost:8765/sse
Should return a stream or connection. If refused, check logs.
-
Check logs for binding errors:
tail -f ./logs/server.log | grep -i "bind\|port\|listen"
Symptom: BlockedFunctionError: Function 'system' is blocked
Explanation: The security validator blocks dangerous functions by default to prevent shell injection and unauthorized file operations.
Solutions:
-
Use MATLAB-native alternatives instead of blocked functions:
- File operations:
dir,mkdir,copyfile,movefile,delete - Environment variables:
getenv,setenv - Avoid:
system,unix,dos,!(shell escape)
- File operations:
-
View the blocked list:
security: blocked_functions: - "system" - "unix" - "dos" - "!" - "eval" - "feval" - "evalc" - "evalin" - "assignin" - "perl" - "python"
-
Disable blocklist (only for trusted, air-gapped servers):
security: blocked_functions_enabled: false
-
Remove specific functions from blocklist:
security: blocked_functions: - "unix" - "dos" # "system" removed — now allowed
-
Check code before execution: Use
check_codeto detect blocked functions before running:# Agent calls check_code with the code first
Symptom: Job never completes, progress stops updating, or job appears to hang
Solutions:
-
Cancel the job: Ask your agent to call
cancel_jobwith the job ID. This interrupts execution:cancel_job job_id=j_abc123
-
Check maximum execution time:
execution: max_execution_time: 86400 # 24h hard limit
If your job legitimately takes longer, increase this value.
-
Check MATLAB code for infinite loops: Add progress reporting to debug stuck jobs:
for i = 1:n result(i) = compute(data(i)); if mod(i, 100) == 0 mcp_progress(__mcp_job_id__, i/n*100, sprintf('Iteration %d/%d', i, n)); end end
-
Monitor engine health: Call
get_pool_statusto check if the engine is still responsive. If an engine is hung:- It will eventually be detected as unhealthy
- A new engine will be spun up
- The hung engine will be recycled
-
Check for blocking I/O: Some MATLAB operations (network calls, file I/O on slow drives) may appear hung. Verify the MATLAB code isn't waiting on external resources.
-
View error log: Call
get_error_logto see if the engine reported any warnings or errors during execution.
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 properly.
Solutions:
-
Check supported plot types:
- Line plots
- Scatter plots
- Bar charts
- Area plots
- Histograms
- Surface/mesh plots
- Image displays
- Subplots (with
subplotortiledlayout) - Multiple axes with linked legends
-
Simplify the plot: Complex multi-axis, custom graphics objects, or specialized toolbox plots may not convert:
% Instead of complex custom graphics: plot(x, y); % Use standard MATLAB plotting
-
Static fallback: A PNG image is always generated even if Plotly conversion fails. The agent will receive the static image.
-
Disable Plotly: Fall back to static images only (faster if you don't need interactivity):
output: plotly_conversion: false
-
Check figure properties: Ensure the figure has properly set axes, labels, and data:
plot(x, y); xlabel('X-axis Label'); ylabel('Y-axis Label'); title('Plot Title'); legend('Data 1', 'Data 2');
-
Enable debug logging to see Plotly conversion errors:
server: log_level: "debug"
Then check the log for
plotlyconversion messages.
Symptom: Output is cut off, saved to file, or marked as "result too large"
Explanation: Results exceeding max_inline_text_length (50,000 chars) or large_result_threshold (10,000 elements) are automatically saved to a file to avoid overwhelming the agent.
Solutions:
-
Increase inline limits:
output: max_inline_text_length: 100000 # allow larger text results inline large_result_threshold: 50000 # allow larger matrices inline
-
Use
list_files+get_job_result+read_datato access the full output:# Agent calls: list_files # see output files read_data filename=result.csv # read the CSV directly
-
Summarize large results in MATLAB before returning:
% Instead of returning all 1M rows: summary_stats = struct(... 'mean', mean(data), 'std', std(data), 'min', min(data), 'max', max(data), 'median', median(data) ); disp(summary_stats); % Return only summary
-
Save large data to MAT file for later retrieval:
large_matrix = randn(10000, 10000); save('large_result.mat', 'large_matrix'); disp('Saved to large_result.mat');
-
Check the file directly: Files are saved to the session result directory. Call
list_filesto see them, thenread_datato retrieve them.
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
matlab-mcpOr in config.yaml:
server:
log_level: "debug"
log_file: "./logs/server.log"- MATLAB communication: Every command sent to/from MATLAB engines
- Pool state: Engine startup, shutdown, scaling events
- Job lifecycle: Submission, async promotion, progress updates, completion
- API calls: Every MCP tool invocation with parameters and results
- Security: Blocklist checks, function validation
- Performance: Execution times, timeouts, retries
# Follow logs
tail -f ./logs/server.log
# Filter for specific keywords
tail -f ./logs/server.log | grep -i "error\|warning"
tail -f ./logs/server.log | grep -i "engine"
tail -f ./logs/server.log | grep -i "plotly"The server doesn't rotate logs automatically. For production, use a log rotation tool:
Linux (logrotate):
cat > /etc/logrotate.d/matlab-mcp << 'EOF'
./logs/server.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
EOFmacOS (manual):
# Compress and archive logs weekly
mv ./logs/server.log ./logs/server.log.$(date +%Y%m%d)
gzip ./logs/server.log.*Linux:
export MATLAB_MCP_SERVER_LOG_FILE=/dev/stderr
matlab-mcp 2>&1 | logger -t matlab-mcpDebug logs use color by default. For cleaner file output:
server:
log_file: "./logs/server.log" # logs to file with reduced colorsSymptom: Variables from one session affecting another, or workspace not clearing between jobs
Solutions:
-
Enable workspace isolation (default is ON):
execution: workspace_isolation: true
Each session gets its own MATLAB workspace.
-
Disable engine affinity if you want true isolation across jobs:
execution: engine_affinity: false # jobs can run on different engines
With affinity OFF, each job gets a fresh workspace. With affinity ON, the same session's jobs reuse the same engine (faster, but workspace persists).
-
Clear workspace between commands:
clear % clear all variables
Symptom: Function not found or File not found errors for custom code
Solutions:
-
Add paths to startup configuration:
workspace: default_paths: - "/path/to/my/libraries" - "/shared/toolboxes"
These paths are added to MATLAB's path on every engine start.
-
Verify path permissions: Ensure the MATLAB process can read the directories:
ls -la /path/to/my/libraries
-
Add path dynamically in code:
addpath('/path/to/my/libraries'); my_function(); -
Check current working directory:
pwd % print working directory ls % list files
The session's working directory is the result directory.