-
Notifications
You must be signed in to change notification settings - Fork 0
Examples
Ready-to-run examples are in the examples/ directory. You don't run these directly—ask your AI agent to execute them through the MCP server!
"Calculate the eigenvalues of a 3×3 magic square"
A = magic(3);
eigenvalues = eig(A);
disp(eigenvalues);What this demonstrates: Basic matrix creation, function calls, and output display. The server captures the disp output and returns it to the agent.
"Create two 100×100 random matrices, multiply them, and show the trace"
A = rand(100);
B = rand(100);
C = A * B;
fprintf('Trace: %.4f\n', trace(C));What this demonstrates: Matrix multiplication, built-in functions (trace), and formatted output with fprintf.
"Solve this system: 3x + 2y - z = 1, 2x − 2y + 4z = −2, −x + 0.5y − z = 0"
A = [3 2 -1; 2 -2 4; -1 0.5 -1];
b = [1; -2; 0];
x = A \ b;
disp('Solution:');
disp(x);What this demonstrates: The backslash operator for linear system solving, matrix construction, and solution display.
"Generate 1000 random samples and compute mean, std, and quantiles"
data = randn(1000, 1);
fprintf('Mean: %.4f\n', mean(data));
fprintf('Std: %.4f\n', std(data));
fprintf('Median: %.4f\n', median(data));
fprintf('IQR: %.4f\n', iqr(data));What this demonstrates: Statistical functions and formatted numerical output.
"Create a table with names and ages, then display it"
names = {'Alice'; 'Bob'; 'Charlie'};
ages = [28; 35; 42];
scores = [92.5; 87.3; 95.1];
T = table(ages, scores, 'RowNames', names);
disp(T);What this demonstrates: Table creation, array operations, and structured data display.
All figures are automatically converted to interactive Plotly JSON and static PNG thumbnails.
"Plot sin(x) from 0 to 2π with labels and grid"
x = linspace(0, 2*pi, 200);
y = sin(x);
plot(x, y, 'LineWidth', 2);
xlabel('x');
ylabel('sin(x)');
title('Sine Wave');
grid on;What this demonstrates: Basic 2D line plotting with styling, labels, and grid. The server automatically captures and converts to Plotly.
"Create a scatter plot of 100 random points colored by distance from origin"
N = 100;
x = randn(N, 1);
y = randn(N, 1);
d = sqrt(x.^2 + y.^2);
scatter(x, y, 50, d, 'filled');
colorbar;
title('Random Points Colored by Distance');
xlabel('X'); ylabel('Y');What this demonstrates: Scatter plots with color mapping and colorbars.
"Show me the peaks function as a 3D surface"
[X, Y] = meshgrid(-3:0.1:3);
Z = peaks(X, Y);
surf(X, Y, Z);
colorbar;
shading interp;
title('Peaks Function');
xlabel('X'); ylabel('Y'); zlabel('Z');What this demonstrates: 3D surface visualization with interpolated shading and colorbars.
"Compare sales data across quarters"
quarters = {'Q1', 'Q2', 'Q3', 'Q4'};
sales = [150000, 175000, 200000, 225000];
bar(categorical(quarters), sales, 'FaceColor', '#2E86AB');
ylabel('Sales ($)');
title('Quarterly Sales');
grid on;What this demonstrates: Bar charts with categorical data and color customization.
"Show the distribution of 10,000 normally distributed samples"
data = randn(10000, 1);
histogram(data, 50, 'EdgeColor', 'black', 'FaceColor', '#A23B72');
title('Normal Distribution');
xlabel('Value');
ylabel('Frequency');What this demonstrates: Histograms with bin control and styling.
"Plot 4 different frequency sine waves side-by-side"
t = linspace(0, 1, 1000);
freqs = [5, 10, 20, 50];
for i = 1:4
subplot(2, 2, i);
plot(t, sin(2*pi*freqs(i)*t), 'LineWidth', 1.5);
title(sprintf('%d Hz', freqs(i)));
xlabel('Time (s)');
ylabel('Amplitude');
end
sgtitle('Sine Waves at Different Frequencies');What this demonstrates: Subplot layouts with multiple axes, automatic Plotly conversion preserves subplot structure.
"Display a correlation matrix as a heatmap"
% Generate sample data
data = randn(100, 5);
corr_matrix = corrcoef(data);
% Create heatmap
imagesc(corr_matrix);
colorbar;
colormap jet;
title('Correlation Matrix');
set(gca, 'XTick', 1:5, 'YTick', 1:5);
set(gca, 'XTickLabel', {'A', 'B', 'C', 'D', 'E'});
set(gca, 'YTickLabel', {'A', 'B', 'C', 'D', 'E'});What this demonstrates: Image-based heatmaps with colormaps and labeled axes.
"Generate a noisy 440Hz signal, compute its FFT, and show both time and frequency domains"
fs = 8000; % Sample rate
duration = 0.1; % 100 ms
t = 0:1/fs:duration;
% Signal: 440Hz sine + noise
signal = sin(2*pi*440*t) + 0.3*randn(size(t));
% Compute FFT
N = length(signal);
Y = fft(signal);
f = (0:N-1) * fs / N;
% Plot time domain
subplot(2, 1, 1);
plot(t*1000, signal, 'b', 'LineWidth', 0.5);
title('Time Domain: 440Hz Signal + Noise');
xlabel('Time (ms)'); ylabel('Amplitude');
% Plot frequency domain
subplot(2, 1, 2);
plot(f(1:N/2), abs(Y(1:N/2))/N, 'r', 'LineWidth', 1);
title('Frequency Domain: FFT Magnitude');
xlabel('Frequency (Hz)'); ylabel('Magnitude');
xlim([0, 2000]);Prerequisites: Basic signal processing knowledge. The FFT is automatically computed and visualized.
What this demonstrates: Frequency-domain analysis, subplot layouts with different plot types.
"Design a 4th-order lowpass Butterworth filter at 1000 Hz and filter a signal"
fs = 8000; % Sample rate
fc = 1000; % Cutoff frequency
order = 4;
% Design filter (requires Signal Processing Toolbox)
[b, a] = butter(order, fc/(fs/2));
% Generate test signal: 440Hz + 3000Hz
t = 0:1/fs:0.5;
signal = sin(2*pi*440*t) + 0.5*sin(2*pi*3000*t);
% Apply filter
filtered = filter(b, a, signal);
% Plot
subplot(2, 1, 1);
plot(t, signal); title('Original Signal');
subplot(2, 1, 2);
plot(t, filtered); title('Filtered Signal (1kHz cutoff)');Prerequisites: Signal Processing Toolbox must be available (add to toolbox whitelist in config).
What this demonstrates: Filter design, frequency-domain signal conditioning, signal comparison via subplots.
"Compute and visualize a spectrogram of a chirp signal"
fs = 1000;
t = 0:1/fs:5;
% Chirp signal: frequency sweeps from 10Hz to 200Hz
f_start = 10;
f_end = 200;
signal = chirp(t, f_start, t(end), f_end);
% Compute spectrogram
spectrogram(signal, 256, 250, 256, fs, 'yaxis');
title('Spectrogram of Chirp Signal');
colorbar;Prerequisites: Signal Processing Toolbox for chirp and spectrogram.
What this demonstrates: Time-frequency analysis, visualization of signal evolution over time.
Jobs exceeding sync_timeout (default 30 seconds) are automatically promoted to async background execution. Use the mcp_progress() helper to report progress.
sequenceDiagram
participant Agent as AI Agent
participant Server as MCP Server
participant Engine as MATLAB Engine
Agent->>Server: execute_code(code)
Server->>Engine: Start background job
Server-->>Agent: status="pending", job_id="abc123"
loop Progress polling
Agent->>Server: get_job_status(job_id)
Server->>Engine: Read progress file
Server-->>Agent: status="running", progress=45%
end
Engine->>Engine: Completes
Agent->>Server: get_job_status(job_id)
Server-->>Agent: status="completed", result={...}
"Estimate π using Monte Carlo with 1 million trials, showing progress updates every 100k trials"
n_trials = 1e6;
inside_circle = 0;
for i = 1:n_trials
% Generate random point in [0,1]²
x = rand();
y = rand();
% Check if inside unit circle
if sqrt(x^2 + y^2) <= 1
inside_circle = inside_circle + 1;
end
% Report progress every 100k trials
if mod(i, 1e5) == 0
pct = (i / n_trials) * 100;
msg = sprintf('Trials: %d / %d', i, n_trials);
mcp_progress(__mcp_job_id__, pct, msg);
end
end
% Final estimate
pi_estimate = 4 * inside_circle / n_trials;
fprintf('π ≈ %.6f (error: %.6f)\n', pi_estimate, abs(pi_estimate - pi));Expected runtime: ~5–10 seconds depending on system. Auto-promoted to async on timeout.
Progress updates visible to agent:
- "Trials: 100000 / 1000000" (10%)
- "Trials: 500000 / 1000000" (50%)
- "Trials: 1000000 / 1000000" (100%)
"Compute SVD of a 5000×5000 random matrix and report progress"
n = 5000;
fprintf('Generating %d x %d random matrix...\n', n, n);
A = randn(n, n);
fprintf('Computing SVD...\n');
mcp_progress(__mcp_job_id__, 0, 'SVD: Initializing...');
[U, S, V] = svd(A);
fprintf('SVD complete.\n');
fprintf('Condition number: %.2e\n', S(1) / S(n));
fprintf('Singular value range: [%.2e, %.2e]\n', S(n), S(1));
mcp_progress(__mcp_job_id__, 100, 'SVD complete');Expected runtime: ~15–30 seconds depending on system resources.
What this demonstrates: Memory-intensive computation, progress reporting for long operations.
"Solve Ax=b using conjugate gradient with convergence monitoring"
n = 1000;
A = sprand(n, n, 0.01);
A = A * A'; % Make symmetric positive definite
b = rand(n, 1);
mcp_progress(__mcp_job_id__, 0, 'CG Solver: Starting');
% Conjugate gradient
x = zeros(n, 1);
r = b - A*x;
p = r;
rsold = r' * r;
max_iters = min(n, 200);
for i = 1:max_iters
Ap = A * p;
alpha = rsold / (p' * Ap);
x = x + alpha * p;
r = r - alpha * Ap;
rsnew = r' * r;
if mod(i, 10) == 0
residual = sqrt(rsnew);
pct = (i / max_iters) * 100;
msg = sprintf('Iter %d: residual=%.2e', i, residual);
mcp_progress(__mcp_job_id__, pct, msg);
end
if sqrt(rsnew) < 1e-8
fprintf('Converged in %d iterations\n', i);
break;
end
beta = rsnew / rsold;
p = r + beta * p;
rsold = rsnew;
end
fprintf('Final residual: %.2e\n', sqrt(rsnew));What this demonstrates: Iterative numerical algorithms with per-iteration progress reporting.
The server provides tools to upload and download files. These reside in the session's isolated temp directory.
The agent calls:
read_script(filename="my_analysis.m")
Returns the .m file content as inline text.
To inspect a .mat file without downloading raw bytes:
read_data(filename="results.mat", format="summary")
Returns variable names, sizes, and types via MATLAB whos:
Name Size Bytes Class
==================================================
output_signal 1000x1 8000 double
timestamps 1000x1 8000 double
metadata 1x1 1024 struct
read_data(filename="output.csv", format="summary")
Returns the CSV content as inline text:
Time,Temperature,Pressure
0.0,20.1,101.3
0.1,20.2,101.4
0.2,20.3,101.5
The agent calls:
read_image(filename="result_plot.png")
Returns the image as an inline content block that renders directly in agent UIs (Claude Desktop, Cursor, etc.).
Supported formats: .png, .jpg, .gif
For development or personal use with stdio transport:
# config_minimal.yaml
server:
name: "matlab-mcp-dev"
transport: "stdio"
log_level: "debug"
pool:
min_engines: 1
max_engines: 2
health_check_interval: 30
execution:
sync_timeout: 30
max_execution_time: 3600
security:
blocked_functions_enabled: trueStart the server:
matlab-mcp --config examples/config_minimal.yamlFor shared server with multiple team members:
# config_multiuser.yaml
server:
name: "matlab-mcp-team"
transport: "sse"
host: "127.0.0.1"
port: 8765
log_level: "info"
pool:
min_engines: 4
max_engines: 16
scale_down_idle_timeout: 1800
health_check_interval: 30
execution:
sync_timeout: 30
max_execution_time: 86400
workspace_isolation: true
security:
blocked_functions_enabled: true
require_proxy_auth: true
max_upload_size_mb: 500
sessions:
max_sessions: 100
session_timeout: 7200
job_retention_seconds: 172800 # 2 days
monitoring:
enabled: true
sample_interval: 10
retention_days: 30
dashboard_enabled: trueDeploy behind nginx reverse proxy with OAuth:
upstream matlab_mcp {
server 127.0.0.1:8765;
}
server {
listen 443 ssl;
server_name matlab-mcp.company.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
# OAuth2 Proxy authentication
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
location / {
proxy_pass http://matlab_mcp;
proxy_http_version 1.1;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade;
}
}Define your own MATLAB functions as first-class MCP tools in custom_tools.yaml:
# custom_tools.yaml
tools:
- name: "signal_analysis"
function_name: "my_signal_analysis"
description: "Analyze a signal and return spectral features"
parameters:
- name: "signal"
type: "list"
description: "Signal samples as array of floats"
required: true
- name: "fs"
type: "float"
description: "Sampling frequency (Hz)"
default: 1000
returns:
description: "Dict with peak_frequency, snr, spectral_entropy"
- name: "image_processing"
function_name: "process_image_custom"
description: "Apply custom image filters"
parameters:
- name: "image_path"
type: "string"
description: "Path to image file"
required: true
- name: "filter_type"
type: "string"
description: "gaussian, median, or laplacian"
default: "gaussian"
returns:
description: "Base64-encoded filtered image"Then the agent can call:
signal_analysis(signal=[1.0, 2.0, 3.0, ...], fs=8000)
graph TB
Agent["AI Agent<br/>(Claude, Cursor)"]
Agent -->|stdio or SSE| FastMCP["FastMCP Server<br/>(MCP Protocol Handler)"]
FastMCP --> ToolRouter["Tool Router<br/>(20 Built-in + Custom)"]
ToolRouter -->|Code Execution| Executor["Job Executor"]
ToolRouter -->|File Ops| FileTools["File Tools<br/>(upload/download/list)"]
ToolRouter -->|Discovery| Discovery["Discovery Tools<br/>(list toolboxes/functions)"]
ToolRouter -->|Admin| Admin["Admin Tools<br/>(pool status, health)"]
Executor --> Validator["Security Validator<br/>(Blocklist Check)"]
Validator --> Pool["Engine Pool Manager<br/>(Min/Max Scaling)"]
Pool -->|Acquire/Release| Engine1["MATLAB Engine<br/>Instance 1"]
Pool -->|Acquire/Release| Engine2["MATLAB Engine<br/>Instance 2"]
Pool -->|Acquire/Release| EngineN["MATLAB Engine<br/>Instance N"]
Executor --> Tracker["Job Tracker<br/>(Status, Progress)"]
Executor --> Formatter["Result Formatter<br/>(Text, JSON, Files)"]
Executor --> Plotly["Plotly Converter<br/>(Figures → Interactive JSON)"]
Agent -->|Poll Progress| Tracker
Agent -->|Read Results| Formatter
Formatter -->|Optional| Monitoring["Metrics & Health<br/>(Collector, Store, Dashboard)"]
sequenceDiagram
participant Claude as Claude (AI Agent)
participant MCP as MCP Server
participant Validator as Security Validator
participant Pool as Engine Pool
participant MATLAB as MATLAB Engine
participant Tracker as Job Tracker
Claude->>MCP: execute_code("x = rand(5)")
MCP->>Validator: check_code("x = rand(5)")
Validator-->>MCP: OK (not blocked)
MCP->>Pool: acquire()
Pool-->>MCP: engine_1
MCP->>MATLAB: eval("x = rand(5)")
MATLAB-->>MCP: ans = [0.4 0.6 ... ]
MCP->>Tracker: create_job("code", result)
MCP-->>Claude: {status: "completed", output: "..."}
Claude->>MCP: execute_code("long_running_code")
MCP->>Pool: acquire()
Pool-->>MCP: engine_2
MCP->>MATLAB: eval(..., background=True)
MCP->>Tracker: create_job("pending")
MCP-->>Claude: {status: "pending", job_id: "abc123"}
loop Progress Polling
Claude->>MCP: get_job_status("abc123")
MCP->>Tracker: lookup("abc123")
Tracker-->>MCP: {progress: 50%, message: "..."}
MCP-->>Claude: {progress: 50%, message: "..."}
end
MATLAB->>MATLAB: (completes)
Claude->>MCP: get_job_result("abc123")
MCP->>Tracker: lookup("abc123")
Tracker-->>MCP: {status: "completed", output: "..."}
MCP-->>Claude: {output: "...", execution_time: 45.2}
- Explore the Tools Reference for detailed tool parameters and responses
- Configure Custom Tools to expose your own MATLAB libraries
- Learn about Async Jobs for long-running computations
- Review Security best practices for team deployments