-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
All settings are configured in config.yaml with sensible defaults. Every configuration option can be overridden via environment variables using the MATLAB_MCP_ prefix.
The server looks for config.yaml in the current working directory by default. Override with:
matlab-mcp --config /path/to/my_config.yamlEnvironment variables use the naming convention MATLAB_MCP_<SECTION>_<KEY> where values are automatically coerced to the expected type:
# Examples
export MATLAB_MCP_POOL_MIN_ENGINES=4 # int
export MATLAB_MCP_POOL_MAX_ENGINES=16 # int
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=60 # int
export MATLAB_MCP_SERVER_TRANSPORT=sse # string
export MATLAB_MCP_SERVER_PORT=9000 # int
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false # boolLimitation: Multi-word section names (e.g., code_checker, custom_tools) cannot be overridden via environment variables due to the flat naming scheme. Use the config file for these sections.
Type Coercion: Values are automatically converted from strings to int, float, bool, or list based on the expected field type in the Pydantic model.
| Key | Type | Default | Description |
|---|---|---|---|
server.name |
string | "matlab-mcp-server" |
Server name reported to MCP clients |
server.transport |
string | "stdio" |
Transport type: stdio (single-session, stdin/stdout) or sse (multi-session, HTTP Server-Sent Events) |
server.host |
string | "0.0.0.0" |
Bind address for SSE transport (HTTP server) |
server.port |
integer | 8765 |
Port for SSE transport; ignored when transport: stdio
|
server.log_level |
string | "info" |
Logging level: debug, info, warning, error
|
server.log_file |
string | "./logs/server.log" |
Absolute or relative path to log file; parent directories are created on startup |
server.result_dir |
string | "./results" |
Directory where large truncated results are saved as files |
server.drain_timeout_seconds |
integer | 300 |
Maximum seconds to wait for running jobs to complete during graceful shutdown (5 minutes) |
Environment Variable Examples:
export MATLAB_MCP_SERVER_TRANSPORT=sse
export MATLAB_MCP_SERVER_PORT=9000
export MATLAB_MCP_SERVER_LOG_LEVEL=debug
export MATLAB_MCP_SERVER_DRAIN_TIMEOUT_SECONDS=600| Key | Type | Default | Description |
|---|---|---|---|
pool.min_engines |
integer | 2 |
Minimum number of MATLAB engines to keep warm; server starts with this many |
pool.max_engines |
integer | 10 |
Maximum number of MATLAB engines; hard ceiling. macOS limit: 4 engines max |
pool.scale_down_idle_timeout |
integer | 900 |
Seconds an engine must be idle before it is stopped and removed from pool, down to min_engines (15 minutes) |
pool.engine_start_timeout |
integer | 120 |
Maximum seconds to wait for a MATLAB engine to start; exceeding this fails the request |
pool.health_check_interval |
integer | 60 |
Seconds between health check pings (sends 1+1 to each engine) |
pool.proactive_warmup_threshold |
float | 0.8 |
Utilization ratio (0.0–1.0) at which the server preemptively starts a new engine; 0.8 = 80% busy |
pool.queue_max_size |
integer | 50 |
Maximum number of execution requests queued when all engines are busy; requests beyond this are rejected |
pool.matlab_root |
string or null | null |
Explicit MATLAB installation root; null means auto-detect via system search |
Environment Variable Examples:
export MATLAB_MCP_POOL_MIN_ENGINES=4
export MATLAB_MCP_POOL_MAX_ENGINES=16
export MATLAB_MCP_POOL_SCALE_DOWN_IDLE_TIMEOUT=600
export MATLAB_MCP_POOL_HEALTH_CHECK_INTERVAL=30macOS Note: MATLAB on macOS has a hard limit of 4 concurrent engines per MATLAB license. The server will log a warning if max_engines > 4 on macOS but still respects the configured value; attempts to start more engines will fail.
| Key | Type | Default | Description |
|---|---|---|---|
execution.sync_timeout |
integer | 30 |
Seconds to wait for code to complete before auto-promoting to async job; returning job_id instead of inline result |
execution.max_execution_time |
integer | 86400 |
Hard limit per job in seconds; jobs exceeding this are cancelled (86400 = 24 hours) |
execution.workspace_isolation |
boolean | true |
Run clear all between sessions to prevent variable leakage; set false to keep workspace persistent |
execution.engine_affinity |
boolean | false |
Pin each session to a specific engine for consistent state; false allows any available engine |
execution.temp_dir |
string | "./temp" |
Base temporary directory for session workspaces; each session gets a subdirectory |
execution.temp_cleanup_on_disconnect |
boolean | true |
Automatically delete temp files when a session disconnects; set false for debugging or archival |
Environment Variable Examples:
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=60
export MATLAB_MCP_EXECUTION_MAX_EXECUTION_TIME=3600
export MATLAB_MCP_EXECUTION_WORKSPACE_ISOLATION=false
export MATLAB_MCP_EXECUTION_TEMP_DIR=/mnt/data/matlab_tempTimeout Behavior:
- Code completes in <
sync_timeout→ returns result inline immediately - Code exceeds
sync_timeout→ returns{"status": "running", "job_id": "..."}for polling withget_job_status/get_job_result
| Key | Type | Default | Description |
|---|---|---|---|
workspace.default_paths |
list of strings | [] |
Paths to add to MATLAB search path on each engine startup (e.g., custom libraries, data directories) |
workspace.startup_commands |
list of strings | [] |
MATLAB commands to run on each engine startup (e.g., format long, setpref, license initialization) |
Example:
workspace:
default_paths:
- "/usr/local/custom_libs"
- "/shared/data/models"
startup_commands:
- "format long"
- "addpath(genpath('/shared/toolboxes'))"
- "setpref('Internet','SMTP_Server','mail.example.com')"Environment Variable Examples:
# Lists cannot be set via env vars; use config file instead
# But individual paths can be comma-separated in MATLAB_MCP_WORKSPACE_DEFAULT_PATHS if needed| Key | Type | Default | Description |
|---|---|---|---|
toolboxes.mode |
string | "all" |
Filtering mode: whitelist (only listed toolboxes), blacklist (all except listed), or all (report all installed) |
toolboxes.list |
list of strings | [] |
Toolbox names to include (whitelist mode) or exclude (blacklist mode) |
Example Whitelist:
toolboxes:
mode: "whitelist"
list:
- "Signal Processing Toolbox"
- "Image Processing Toolbox"
- "Statistics and Machine Learning Toolbox"
- "Optimization Toolbox"Example Blacklist:
toolboxes:
mode: "blacklist"
list:
- "Simulink"
- "MATLAB Compiler"| Mode | Behavior |
|---|---|
whitelist |
Only toolboxes in list are discoverable by agents; limits unnecessary information |
blacklist |
All toolboxes EXCEPT those in list are discoverable |
all |
All installed toolboxes are reported; largest information surface |
| Key | Type | Default | Description |
|---|---|---|---|
security.blocked_functions_enabled |
boolean | true |
Enable the security validator to block dangerous functions and shell escapes |
security.blocked_functions |
list of strings | See below | Function names and patterns to block; checked before execution |
security.max_upload_size_mb |
integer | 100 |
Maximum file size for uploads (MB); prevents resource exhaustion |
security.require_proxy_auth |
boolean | false |
Require HTTP proxy authentication headers for SSE transport; set true for production deployments |
Default Blocked Functions:
security:
blocked_functions_enabled: true
blocked_functions:
- "system" # Execute shell commands
- "unix" # Unix-specific shell execution
- "dos" # DOS-specific shell execution
- "!" # Shell escape operator
- "eval" # Dynamic code evaluation
- "feval" # Function handle evaluation
- "evalc" # Evaluation with output capture
- "evalin" # Evaluation in specific workspace
- "assignin" # Dynamic variable assignment
- "perl" # Perl interpreter execution
- "python" # Python interpreter execution
max_upload_size_mb: 100
require_proxy_auth: falseHow Blocking Works:
- Code is scanned before execution using regex patterns for function calls
- String literals (
'...'and"...") are stripped to avoid false positives - Comments are ignored;
% system('cmd')in a comment is allowed - If a blocked function is detected, execution is rejected with
BlockedFunctionError
Customization Example:
security:
blocked_functions_enabled: true
blocked_functions:
- "system"
- "eval"
# Remove "unix", "dos", "!" if your use case requires themEnvironment Variable Examples:
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false
export MATLAB_MCP_SECURITY_MAX_UPLOAD_SIZE_MB=500
export MATLAB_MCP_SECURITY_REQUIRE_PROXY_AUTH=true| Key | Type | Default | Description |
|---|---|---|---|
code_checker.enabled |
boolean | true |
Enable the check_code MCP tool (MATLAB linter integration) |
code_checker.auto_check_before_execute |
boolean | false |
Automatically run linter before every code execution; can be slow on large codebases |
code_checker.severity_levels |
list of strings | ["error", "warning"] |
Severity levels to report; include "info", "error", "warning" as needed |
Example:
code_checker:
enabled: true
auto_check_before_execute: false # Manual checking via check_code tool
severity_levels: ["error", "warning"] # Skip info-level messages| Key | Type | Default | Description |
|---|---|---|---|
custom_tools.config_file |
string | "./custom_tools.yaml" |
Path to YAML file defining custom MATLAB tools; absolute or relative to CWD |
Example:
custom_tools:
config_file: "./custom_tools.yaml"See the Custom Tools wiki page for the full custom tools YAML format and examples.
| Key | Type | Default | Description |
|---|---|---|---|
output.plotly_conversion |
boolean | true |
Convert MATLAB figures to interactive Plotly JSON; requires mcp_extract_props.m helper |
output.static_image_format |
string | "png" |
Image format for static thumbnails: png, jpg, svg
|
output.static_image_dpi |
integer | 150 |
DPI for static images; higher = sharper but larger files |
output.thumbnail_enabled |
boolean | true |
Generate base64-encoded image thumbnails for inline rendering in agent UIs |
output.thumbnail_max_width |
integer | 400 |
Maximum pixel width for thumbnails; aspect ratio preserved |
output.large_result_threshold |
integer | 10000 |
Number of elements in output array before saving to file instead of embedding |
output.max_inline_text_length |
integer | 50000 |
Maximum characters of text to return inline; larger text is saved to file |
Example:
output:
plotly_conversion: true
static_image_format: "png"
static_image_dpi: 150
thumbnail_enabled: true
thumbnail_max_width: 400
large_result_threshold: 10000
max_inline_text_length: 50000Text Truncation Behavior:
- Text output exceeding
max_inline_text_lengthis saved to a file inresult_dir - Response includes
"result_file": "results/job-abc123.txt"path for retrieval - Large arrays and matrices are summarized:
"x: <1000x500 double>"instead of full content
| Key | Type | Default | Description |
|---|---|---|---|
sessions.max_sessions |
integer | 50 |
Hard limit on concurrent sessions per server; new sessions rejected when limit reached |
sessions.session_timeout |
integer | 3600 |
Seconds of inactivity before automatic session cleanup (3600 = 1 hour) |
sessions.job_retention_seconds |
integer | 86400 |
Duration to keep completed job metadata in memory (86400 = 24 hours); older jobs are pruned |
Example:
sessions:
max_sessions: 50 # Up to 50 concurrent users (SSE)
session_timeout: 3600 # 1 hour idle timeout
job_retention_seconds: 86400 # Keep job history for 24 hoursBehavior:
- stdio transport: Single
"default"session per server instance - SSE transport: Multiple sessions, one per authenticated client
- Idle session cleanup: Session is destroyed if no requests received for
session_timeoutseconds - Job pruning: Completed/failed jobs older than
job_retention_secondsare removed from tracker
| Key | Type | Default | Description |
|---|---|---|---|
monitoring.enabled |
boolean | false |
Enable metrics collection (requires optional dependencies: psutil, aiosqlite, uvicorn) |
monitoring.sample_interval |
integer | 10 |
Seconds between metric collection samples; higher = less frequent sampling |
monitoring.retention_days |
integer | 7 |
Days to retain historical metrics in SQLite database; older data is pruned |
monitoring.db_path |
string | "./monitoring/metrics.db" |
Path to SQLite database file; parent directories created on startup |
monitoring.dashboard_enabled |
boolean | true |
Enable the web dashboard at http://localhost:8766/dashboard (when monitoring enabled) |
monitoring.http_port |
integer | 8766 |
Port for the monitoring HTTP server (independent of server.port) |
Example:
monitoring:
enabled: true
sample_interval: 10
retention_days: 7
db_path: "./monitoring/metrics.db"
dashboard_enabled: true
http_port: 8766Installation of Optional Dependencies:
# Install monitoring dependencies
pip install matlab-mcp-server[monitoring]
# Or install all dev dependencies
pip install matlab-mcp-server[dev]
# Or manually
pip install psutil aiosqlite uvicornMetrics Collected:
- Pool utilization (busy/available/total engines)
- Job throughput (completed, failed, active)
- Execution time statistics (avg, p95)
- Session counts
- System metrics (memory, CPU)
- Error events (blocked functions, failures, health checks)
Dashboard Endpoints:
-
GET /dashboard— Static HTML dashboard -
GET /dashboard/static/*— CSS, JavaScript, images -
GET /dashboard/api/current— Latest metrics snapshot -
GET /dashboard/api/history?hours=1— Historical time-series data -
GET /dashboard/api/events?type=job_completed— Event log with filtering -
GET /health— Server health check (200or503) -
GET /metrics— Prometheus-compatible metrics
# matlab-mcp-server configuration
# All settings have sensible defaults; edit only what you need
# ============================================================================
# Server Configuration
# ============================================================================
server:
name: "matlab-mcp-server"
transport: "stdio" # stdio (local) or sse (network multi-user)
host: "0.0.0.0" # Bind address (SSE only)
port: 8765 # Port (SSE only)
log_level: "info" # debug | info | warning | error
log_file: "./logs/server.log" # Relative to CWD
result_dir: "./results" # Where to save large results
drain_timeout_seconds: 300 # Max seconds for graceful shutdown
# ============================================================================
# Engine Pool Configuration
# ============================================================================
pool:
min_engines: 2 # Warm engine count
max_engines: 10 # Hard ceiling (macOS: max 4)
scale_down_idle_timeout: 900 # Seconds before idle engine shutdown (15 min)
engine_start_timeout: 120 # Seconds to wait for engine startup
health_check_interval: 60 # Seconds between health pings
proactive_warmup_threshold: 0.8 # Utilization threshold to start new engine
queue_max_size: 50 # Max pending requests when pool busy
matlab_root: null # null = auto-detect, or set explicit path
# ============================================================================
# Code Execution Configuration
# ============================================================================
execution:
sync_timeout: 30 # Seconds before auto-promoting to async
max_execution_time: 86400 # Hard limit per job (24 hours)
workspace_isolation: true # Clear workspace between sessions
engine_affinity: false # Pin session to specific engine
temp_dir: "./temp" # Temporary workspace directory
temp_cleanup_on_disconnect: true # Delete temp on session close
# ============================================================================
# MATLAB Workspace Configuration
# ============================================================================
workspace:
default_paths: # Added to MATLAB path on engine start
# Example paths (uncomment as needed):
# - "/usr/local/custom_libs"
# - "/shared/data/models"
startup_commands: # Run on each engine startup
# Example commands (uncomment as needed):
# - "format long"
# - "setpref('Internet','SMTP_Server','mail.example.com')"
# ============================================================================
# Toolboxes Configuration
# ============================================================================
toolboxes:
mode: "all" # whitelist | blacklist | all
list: # Only used in whitelist/blacklist modes
# Example for whitelist:
# - "Signal Processing Toolbox"
# - "Image Processing Toolbox"
# - "Statistics and Machine Learning Toolbox"
# ============================================================================
# Security Configuration
# ============================================================================
security:
blocked_functions_enabled: true # Block dangerous functions
blocked_functions:
- "system" # Shell execution
- "unix" # Unix-specific shell
- "dos" # DOS-specific shell
- "!" # Shell escape operator
- "eval" # Dynamic code evaluation
- "feval" # Function handle evaluation
- "evalc" # Evaluation with output capture
- "evalin" # Evaluation in workspace
- "assignin" # Dynamic variable assignment
- "perl" # Perl interpreter
- "python" # Python interpreter
max_upload_size_mb: 100 # Max file upload size
require_proxy_auth: false # Require auth headers (SSE production)
# ============================================================================
# Code Checker Configuration
# ============================================================================
code_checker:
enabled: true # Enable check_code tool
auto_check_before_execute: false # Check before every execution
severity_levels: ["error", "warning"] # Severity levels to report
# ============================================================================
# Custom Tools Configuration
# ============================================================================
custom_tools:
config_file: "./custom_tools.yaml" # Path to custom tool definitions
# ============================================================================
# Output Configuration
# ============================================================================
output:
plotly_conversion: true # Convert figures to Plotly JSON
static_image_format: "png" # png | jpg | svg
static_image_dpi: 150 # DPI for static images
thumbnail_enabled: true # Generate thumbnails
thumbnail_max_width: 400 # Thumbnail width (pixels)
large_result_threshold: 10000 # Elements before saving to file
max_inline_text_length: 50000 # Characters before saving to file
# ============================================================================
# Sessions Configuration
# ============================================================================
sessions:
max_sessions: 50 # Concurrent sessions limit
session_timeout: 3600 # Seconds of inactivity before cleanup (1h)
job_retention_seconds: 86400 # Keep job metadata for 24 hours
# ============================================================================
# Monitoring Configuration (Requires Optional Dependencies)
# ============================================================================
monitoring:
enabled: false # Set to true if psutil/aiosqlite installed
sample_interval: 10 # Seconds between samples
retention_days: 7 # Days to keep historical data
db_path: "./monitoring/metrics.db" # SQLite database path
dashboard_enabled: true # Enable web dashboard
http_port: 8766 # Dashboard HTTP portserver:
transport: "stdio"
log_level: "debug"
pool:
min_engines: 1
max_engines: 2
execution:
sync_timeout: 30
sessions:
max_sessions: 1
monitoring:
enabled: false # Skip overheadserver:
transport: "sse"
host: "0.0.0.0"
port: 8765
log_level: "info"
pool:
min_engines: 4
max_engines: 16
health_check_interval: 30
execution:
sync_timeout: 60
workspace_isolation: true
security:
blocked_functions_enabled: true
require_proxy_auth: true # Behind reverse proxy with auth
sessions:
max_sessions: 50
session_timeout: 1800 # 30 minutes
monitoring:
enabled: true
http_port: 8766pool:
min_engines: 8
max_engines: 32
scale_down_idle_timeout: 1800 # 30 minutes
proactive_warmup_threshold: 0.6 # Start new engine at 60%
execution:
sync_timeout: 120 # Longer timeout for batch jobs
max_execution_time: 604800 # 1 week
workspace_isolation: false # Keep state across jobs
output:
max_inline_text_length: 100000 # Larger inline limitsProblem: "Too many open engines" error on macOS
Solution: Set pool.max_engines: 4 (macOS hard limit per license)
Problem: Jobs frequently timeout
Solution: Increase execution.sync_timeout: 60 or 120
Problem: High memory usage with large workspaces
Solution: Enable execution.workspace_isolation: true to clear variables between sessions
Problem: Slow startup with many custom paths
Solution: Reduce workspace.default_paths or consolidate into a single shared directory
Problem: "Request rejected: queue full" errors
Solution: Increase pool.queue_max_size: 100 or increase pool.max_engines
graph LR
A["config.yaml<br/>+ ENV vars"] -->|Parse & Validate| B["AppConfig<br/>Pydantic Models"]
B -->|Pass to| C["MatlabMCPServer"]
C -->|pool config| D["EnginePoolManager"]
C -->|execution config| E["JobExecutor"]
C -->|security config| F["SecurityValidator"]
C -->|sessions config| G["SessionManager"]
C -->|output config| H["ResultFormatter"]
C -->|monitoring config| I["MetricsCollector<br/>+ Store"]
D -->|min/max/health| J["MATLAB Engine Pool"]
E -->|temp_dir/timeout| K["Code Execution"]
F -->|blocklist| K
G -->|isolation/timeout| K
H -->|format/truncate| L["MCP Response"]
I -->|collect metrics| M["Dashboard"]
K --> L
L -->|to Agent| N["AI Client"]