-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Symptom: pip install matlab-mcp-python fails with dependency errors or permission denied
Likely Cause:
- Python version < 3.10
- Virtual environment not activated
- Insufficient permissions
- Incompatible OS/architecture
Solutions:
-
Verify Python version (3.10+):
python --version
If < 3.10, upgrade Python or use a newer version.
-
Use a virtual environment:
python -m venv venv source venv/bin/activate # macOS/Linux venv\Scripts\activate.bat # Windows pip install matlab-mcp-python
-
Install with
--userflag if system-wide fails:pip install --user matlab-mcp-python
-
Check pip is up-to-date:
pip install --upgrade pip
-
For offline Windows installation, use the batch script:
install.bat
Symptom: ImportError: No module named 'matlab' or No module named 'matlab.engine'
Likely Cause:
- MATLAB Engine API not installed
- MATLAB not found on system
- Wrong Python interpreter being used
Solutions:
-
Install MATLAB 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 .
Linux:
cd /usr/local/MATLAB/R2024a/extern/engines/python pip install .
-
Verify MATLAB is installed:
which matlab # macOS/Linux where matlab.exe # Windows
-
Check Python interpreter matches MATLAB:
- If MATLAB is 64-bit, use 64-bit Python
- If MATLAB is 32-bit (rare), use 32-bit Python
python -c "import struct; print(struct.calcsize('P') * 8, 'bit')" -
Try importing manually:
python -c "import matlab.engine; print('Success')"If this fails, the Engine API installation had an issue—reinstall it.
Symptom: Engine start timeout after 120 seconds, or engines stuck in STARTING state
Likely Cause:
- MATLAB installation broken or incomplete
- Licensing issue (license server unreachable)
- System resources exhausted (RAM, disk space)
- macOS notarization/gatekeeper blocking MATLAB
Solutions:
-
Test MATLAB starts manually:
python -c "import matlab.engine; eng = matlab.engine.start_matlab(); print('OK'); eng.quit()"If this hangs or fails, the MATLAB installation is the problem.
-
Check MATLAB license:
# Inside MATLAB interactive session licenseIf using a license server, verify network connectivity to the server.
-
Increase engine start timeout:
pool: engine_start_timeout: 300 # 5 minutes (default: 120s)
-
Reduce
min_enginesfor testing:pool: min_engines: 1 max_engines: 2
Start with a smaller pool to isolate the problem.
-
Check system resources:
- Disk space:
df -h - Available RAM:
free -h(Linux) or Activity Monitor (macOS) - Each MATLAB engine requires ~500MB–1GB RAM
- Disk space:
-
macOS users: Check gatekeeper:
spctl status # Should show "assessments disabled" or in developer modeIf MATLAB is blocked, allow it in System Preferences > Security & Privacy.
Symptom: Warning logged: macOS detected — capping max_engines to 4
Explanation: MATLAB on macOS has a hard limit of ~4 concurrent engine instances due to licensing restrictions.
Solution:
Set max_engines: 4 in your configuration:
pool:
max_engines: 4
min_engines: 1 # or 2 for headroomThe server respects your configured value but will not exceed 4 simultaneous engines.
Symptom:
- Client:
Connection refused: 127.0.0.1:8765 - Client: HTTP request times out
Likely Cause:
- Server not running
- Wrong port/host configuration
- Firewall blocking port
- Reverse proxy authentication failing
Solutions:
-
Verify server is running:
matlab-mcp --config config.yaml
or
python -m matlab_mcp.server --config config.yaml
-
Check server logs for startup errors:
server: log_level: "debug" log_file: "./server.log"
Then review
./server.log. -
Verify port configuration:
server: transport: "sse" host: "0.0.0.0" # All interfaces port: 8765
-
Test locally:
curl http://localhost:8765/health
Should return a JSON response. If connection refused, server is not listening.
-
Check firewall:
# macOS sudo lsof -i :8765 # Linux netstat -tlnp | grep 8765 # Windows netstat -ano | findstr :8765
-
For reverse proxy setups: Ensure the proxy is forwarding SSE/EventSource correctly:
- Preserve the
Content-Type: text/event-streamheader - Disable response buffering
- Forward authentication headers to the backend
- Preserve the
Symptom: Variables persist across different sessions/users
Likely Cause: workspace_isolation: false or not running clear all
Solution:
Ensure isolation is enabled:
execution:
workspace_isolation: true # Default: trueThe server will run these commands between sessions:
clear all
clear global
clear functions
fclose all
restoredefaultpathSymptom: BlockedFunctionError: Function 'system' is blocked for security
Explanation: The blocklist prevents dangerous functions (system, eval, unix, !, etc.) from executing.
Solutions:
-
Use MATLAB native alternatives:
Blocked Alternative system('command')Use dir,mkdir,copyfile,movefile,getenveval(str)Use feval(func_handle)with proper arguments!commandUse equivalent MATLAB function -
Remove specific functions from the blocklist (if safe for your use case):
security: blocked_functions_enabled: true blocked_functions: - "system" - "unix" - "dos" - "!" - "eval" - "feval" - "evalc" - "evalin" - "assignin" - "perl" - "python"
Remove entries that you need but trust the agent not to abuse.
-
Disable blocklist entirely (not recommended for shared servers):
security: blocked_functions_enabled: false
-
Check the code for false positives: The validator strips string literals and comments. If blocked text is in a string or comment, it won't trigger:
msg = "system commands are dangerous" % Safe: "system" in string % system('ls') % Safe: system in comment system('ls') % NOT safe: actual call
Symptom:
- Sync execution waits indefinitely
- Job promoted to async unexpectedly
- Agent reports timeout
Likely Cause:
-
sync_timeouttoo short for the computation - Code is stuck in a loop
- MATLAB is unresponsive
Solutions:
-
Increase
sync_timeoutfor longer computations:execution: sync_timeout: 60 # Default: 30s
-
Use async patterns for long-running code: Report progress and let the agent poll:
mcp_progress(__mcp_job_id__, percent, message);
-
Check MATLAB process:
# macOS/Linux ps aux | grep MATLAB # Windows tasklist | findstr matlab
If CPU is 0%, MATLAB may be stuck.
-
Check for infinite loops in the code.
Symptom: get_workspace returns empty or incomplete variable list
Likely Cause:
- Code exited with an error before creating variables
- Variables were local to a function
- Workspace was cleared
Solutions:
-
Check execution status:
Agent: "What was the execution status?"If "failed", check error message in
get_job_result. -
Verify variable names in code: Variables must be created at the workspace level, not inside functions:
% Good: variable at workspace level result = solve_system(A, b); % Bad: variable only inside function function my_func result = solve_system(A, b); end
-
Avoid
clear allin your code.
Symptom:
- Figure shows only as text, not interactive Plotly
- PNG fallback is generated but no JSON
Likely Cause:
- Figure type not supported by converter
-
mcp_extract_props.mfailed - Missing figure properties
Solutions:
-
Check supported figure types: The converter supports:
- Line plots (
plot) - Scatter plots (
scatter) - Bar charts (
bar) - Histograms (
histogram) - 3D surfaces (
surf,mesh) - Heatmaps (
imagesc,heatmap) - Multiple axes (subplots)
Complex custom graphics may not convert. Use
plot(),bar(), etc. directly. - Line plots (
-
Enable debug logging:
server: log_level: "debug"
Look for lines containing
mcp_extract_propsto see what went wrong. -
Check figure exists:
fig = gcf; % Get current figure assert(~isempty(fig), 'No figure open');
-
Fall back to static images only:
output: plotly_conversion: false static_image_format: "png" static_image_dpi: 150
-
Verify MATLAB Plotting Toolbox is available:
Agent: "What toolboxes are available?"Look for "MATLAB Plotting" or "MATLAB Graphics".
Symptom:
-
upload_datareturns error -
read_scriptsays file not found - File appears in
list_filesbut not readable
Likely Cause:
- Filename sanitization rejecting valid names
- Path traversal attack prevention blocking legitimate access
- File permissions issue
- Session temp directory missing
Solutions:
-
Check filename restrictions: Allowed characters:
[a-zA-Z0-9._-]onlyBad: my script.m (space) Bad: data[1].csv (brackets) Bad: ../etc/passwd (path traversal) Good: my_script.m Good: data_1.csv -
Check file size limit:
security: max_upload_size_mb: 100 # Default: 100MB
Increase if uploading larger files.
-
Verify temp directory exists: The server creates a temp directory per session. If it's deleted externally, operations fail.
-
Check file permissions:
ls -la <session_temp_dir>
The server process must have read/write access.
-
Use full relative path from temp directory: All file operations are relative to the session temp dir:
upload: "data.csv" # ✓ read: "subdir/data.csv" # ✓ upload: "/absolute/path" # ✗
Symptom:
- Upload times out
- Reading large
.matfile hangs - Download slow
Likely Cause:
- Large file size
- Network bandwidth
- MATLAB processing time
Solutions:
-
Increase timeout for I/O operations:
execution: sync_timeout: 120 # Allows more time for large I/O
-
Compress files before upload:
data = readmatrix('large_file.csv'); save('data.mat', 'data'); % More compact than CSV
-
Stream data instead of loading all at once: For very large files, process in chunks.
-
Check disk space:
df -h # Ensure temp directory has space
Symptom:
-
get_job_statusalways returns "running" - Progress hasn't updated in a long time
- Job never completes
Likely Cause:
- Code is in an infinite loop
- MATLAB process crashed silently
- Progress reporting not working
Solutions:
-
Cancel the job: Agent calls:
cancel_job(job_id="abc123") -
Check MATLAB process:
ps aux | grep MATLAB # macOS/Linux tasklist # Windows
-
Check max execution time:
execution: max_execution_time: 86400 # 24h hard limit
Jobs are force-killed if they exceed this.
-
Add progress reporting to debug:
for i = 1:1000000 if mod(i, 10000) == 0 mcp_progress(__mcp_job_id__, i/1000000*100, sprintf('Progress: %d%%', i/10000)); end end
-
Check for infinite loops:
% Bad: infinite loop while true % ... end % Good: bounded loop for i = 1:10000 % ... end
Symptom: get_job_status returns progress=0 or no message
Likely Cause:
-
mcp_progress()not called - Job completed too quickly (no time for progress updates)
- Progress file not being written
Solutions:
-
Call
mcp_progress()inside the loop:for i = 1:n % Do work... mcp_progress(__mcp_job_id__, i/n*100, sprintf('Iteration %d/%d', i, n)); end
-
Ensure job context is available: The job context (
__mcp_job_id__,__mcp_temp_dir__) is automatically injected. Verify it's accessible:assert(~isempty(__mcp_job_id__), 'Job context not available'); -
Check temp directory: Progress is stored in
<temp_dir>/.mcp_progress_<job_id>.json.
Symptom: Setting MATLAB_MCP_* env var doesn't change behavior
Likely Cause:
- Env var name incorrect
- Config file is overriding it
- Process not restarted after setting env var
Solutions:
-
Check env var naming pattern:
MATLAB_MCP_<MODULE>_<SETTING> = value Examples: MATLAB_MCP_POOL_MAX_ENGINES=16 MATLAB_MCP_SERVER_TRANSPORT=sse MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false -
Verify env var is set:
echo $MATLAB_MCP_POOL_MAX_ENGINES # macOS/Linux echo %MATLAB_MCP_POOL_MAX_ENGINES% # Windows
-
Restart the server:
matlab-mcp --config config.yaml
-
Check precedence: Config file > env var > default If a config file is explicitly provided, env vars still override it.
Symptom: Server starts with defaults, ignoring provided config file
Likely Cause:
- Wrong path to config file
- File doesn't exist
- Relative path not resolved correctly
Solutions:
-
Use absolute path:
matlab-mcp --config /absolute/path/to/config.yaml
-
Check file exists:
ls -la config.yaml # macOS/Linux dir config.yaml # Windows
-
Check YAML syntax:
python -c "import yaml; yaml.safe_load(open('config.yaml'))"If this fails, the YAML is malformed.
-
Use default location: If no
--configis provided, the server looks forconfig.yamlin the current directory.
To see detailed server activity:
-
In config file:
server: log_level: "debug" log_file: "./server.log"
-
Via environment variable:
export MATLAB_MCP_SERVER_LOG_LEVEL=debug matlab-mcp --config config.yaml -
Check log output:
tail -f server.log
Useful log patterns to search for:
-
[job abc123]— tracks specific job lifecycle -
Engine start timeout— engine startup issues -
BlockedFunctionError— security violations -
Sync timeout— promotion to async -
mcp_extract_props— plotting issues
When reporting an issue, include:
-
Server version:
pip show matlab-mcp-python
-
MATLAB version:
Agent: "What MATLAB version is this?" -
Python version:
python --version
-
Configuration (redacted): Paste your
config.yaml(remove sensitive paths/credentials) -
Full error message and stack trace: From server logs (with
log_level: debug) -
Minimal reproducible example: The exact MATLAB code that triggers the issue
-
System info:
- OS and version
- MATLAB Engine API installed correctly
- Virtual environment being used
-
Server logs (last 100 lines):
tail -100 server.log > diagnostic_logs.txt
- Architecture.md — System design and component interactions
- Configuration.md — Full YAML reference
- Async-Jobs.md — Job lifecycle and progress reporting
- Security.md — Blocklist and isolation details
- FAQ.md — Common questions
https://github.com/HanSur94/matlab-mcp-server-python/issues
https://github.com/HanSur94/matlab-mcp-server-python/issues/new
Include:
- Issue title describing the symptom
- Steps to reproduce
- Diagnostic information (from above section)
- Expected vs. actual behavior
For questions and feature requests:
- GitHub Discussions: https://github.com/HanSur94/matlab-mcp-server-python/discussions
- Consider linking related issues
flowchart TD
A["Problem Occurs"] --> B["Check Log Level<br/>Set to DEBUG"]
B --> C["Review Logs for Errors"]
C --> D{Error Category}
D -->|Installation| E["Check Python & MATLAB<br/>Versions"]
D -->|MATLAB Engine| F["Test matlab.engine<br/>Manually"]
D -->|Network/SSE| G["Test Port & Firewall"]
D -->|Code Execution| H["Check Security<br/>Blocklist"]
D -->|Async Job| I["Check Progress<br/>& Timeouts"]
D -->|File I/O| J["Check Permissions<br/>& Paths"]
D -->|Config| K["Validate YAML<br/>& Env Vars"]
E --> L["Consult Troubleshooting<br/>Section"]
F --> L
G --> L
H --> L
I --> L
J --> L
K --> L
L --> M{Resolved?}
M -->|Yes| N["Done"]
M -->|No| O["Open GitHub Issue<br/>with Diagnostics"]