-
Notifications
You must be signed in to change notification settings - Fork 0
Examples
This page provides practical, real-world usage examples demonstrating the MATLAB MCP Server's capabilities. Progress from simple calculations to advanced async jobs and custom tools.
graph LR
Agent["AI Agent<br/>(Claude/Cursor)"]
MCP["MCP Server<br/>(FastMCP)"]
Exec["Job Executor"]
Pool["Engine Pool<br/>(1-16 engines)"]
MATLAB["MATLAB Engine<br/>Instances"]
Agent -->|execute_code<br/>check_code| MCP
MCP --> Exec
Exec -->|acquire/release| Pool
Pool -->|eval,workspace| MATLAB
MATLAB -->|results| Pool
Pool -->|done| Exec
Exec -->|job_id or result| MCP
MCP -->|text/plots| Agent
What it demonstrates: Basic arithmetic and MATLAB function calls.
% Calculate eigenvalues of a magic square
A = magic(3);
eigs = eig(A);
disp('Eigenvalues:');
disp(eigs);
% Also compute some statistics
fprintf('Mean eigenvalue: %.4f\n', mean(eigs));
fprintf('Max eigenvalue: %.4f\n', max(eigs));Prerequisites: None — standard MATLAB.
What it demonstrates: Working with arrays, matrix multiplication, and trace computation.
% Create two random matrices
A = rand(100, 100);
B = rand(100, 100);
% Matrix multiplication
C = A * B;
% Compute trace (sum of diagonal)
tr = trace(C);
fprintf('Trace of A*B: %.6f\n', tr);
% Frobenius norm
fro = norm(C, 'fro');
fprintf('Frobenius norm: %.6f\n', fro);
% Display summary
[m, n] = size(C);
fprintf('Result matrix: %d x %d\n', m, n);Prerequisites: None.
What it demonstrates: Using MATLAB's backslash operator for linear algebra.
% System of equations:
% 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];
% Solve A*x = b
x = A \ b;
disp('Solution:');
disp(x);
% Verify
residual = A*x - b;
fprintf('Residual norm: %.2e\n', norm(residual));Prerequisites: None.
All figures are automatically converted to interactive Plotly JSON and static PNG images for inline viewing in agent UIs.
What it demonstrates: 2D line plots with labels, grid, and styling.
% Plot sin(x) and cos(x)
x = linspace(0, 2*pi, 200);
y1 = sin(x);
y2 = cos(x);
figure('Position', [100 100 800 400]);
plot(x, y1, 'b-', 'LineWidth', 2, 'DisplayName', 'sin(x)');
hold on;
plot(x, y2, 'r--', 'LineWidth', 2, 'DisplayName', 'cos(x)');
xlabel('x (radians)', 'FontSize', 12);
ylabel('y', 'FontSize', 12);
title('Trigonometric Functions', 'FontSize', 14);
legend('Location', 'northeast');
grid on;
axis tight;Prerequisites: MATLAB with plot support.
What it demonstrates: 3D visualization with colormap and lighting.
% Create a 3D surface
[X, Y] = meshgrid(-3:0.1:3, -3:0.1:3);
Z = peaks(X, Y);
figure('Position', [100 100 800 600]);
surf(X, Y, Z, 'FaceColor', 'interp', 'EdgeColor', 'none');
colorbar;
shading interp;
camlight;
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Peaks Function (3D)', 'FontSize', 14);Prerequisites: MATLAB with peaks() function.
What it demonstrates: Arranging multiple plots in a grid layout.
% Create a 2x2 subplot grid
t = linspace(0, 1, 1000);
frequencies = [5, 10, 20, 50];
figure('Position', [100 100 900 700]);
for i = 1:4
subplot(2, 2, i);
freq = frequencies(i);
y = sin(2*pi*freq*t);
plot(t, y, 'LineWidth', 1.5);
title(sprintf('%d Hz', freq), 'FontSize', 12);
xlabel('Time (s)');
ylabel('Amplitude');
grid on;
end
sgtitle('Frequency Sweep', 'FontSize', 14);Prerequisites: MATLAB with subplot support.
What it demonstrates: Plotting distributions and density curves.
% Generate random data from normal distribution
data = randn(1, 10000);
figure('Position', [100 100 800 500]);
% Histogram with density overlay
histogram(data, 'Normalization', 'probability', 'BinWidth', 0.1, ...
'FaceColor', [0.2 0.5 0.8], 'EdgeColor', 'none');
hold on;
% Overlay theoretical normal curve
x = linspace(-4, 4, 200);
y = (1/sqrt(2*pi)) * exp(-0.5*x.^2);
plot(x, y, 'r-', 'LineWidth', 2, 'DisplayName', 'N(0,1)');
xlabel('Value');
ylabel('Probability');
title('Normal Distribution Histogram');
legend;
grid on;Prerequisites: MATLAB with histogram() function.
What it demonstrates: Frequency domain analysis with fast Fourier transform.
% Generate a multi-frequency signal
fs = 8000; % Sample rate
t = 0:1/fs:0.5;
% Composite signal: 440 Hz + 880 Hz + noise
signal = sin(2*pi*440*t) + 0.5*sin(2*pi*880*t) + 0.1*randn(size(t));
% Compute FFT
N = length(signal);
Y = fft(signal);
f = (0:N-1) * fs / N;
% Plot time and frequency domain
figure('Position', [100 100 1000 500]);
subplot(1, 2, 1);
plot(t(1:4000), signal(1:4000));
xlabel('Time (s)');
ylabel('Amplitude');
title('Time Domain (first 0.5s)');
grid on;
subplot(1, 2, 2);
plot(f(1:N/2), abs(Y(1:N/2))/N);
xlabel('Frequency (Hz)');
ylabel('Magnitude');
title('Frequency Domain');
xlim([0 2000]);
grid on;Prerequisites: MATLAB with signal processing basics (no toolbox required).
What it demonstrates: Filter design and frequency filtering of signals.
% Design a low-pass Butterworth filter
fs = 8000;
Wn = 1000 / (fs/2); % Normalized cutoff frequency
[b, a] = butter(4, Wn, 'low');
% Generate noisy signal (contains high-frequency noise)
t = 0:1/fs:1;
signal = sin(2*pi*100*t) + 0.5*sin(2*pi*3000*t); % 100 Hz + 3 kHz noise
% Apply filter
filtered = filtfilt(b, a, signal);
% Plot results
figure('Position', [100 100 1000 400]);
subplot(1, 2, 1);
plot(t(1:2000), signal(1:2000));
title('Original (noisy)');
xlabel('Time (s)');
grid on;
subplot(1, 2, 2);
plot(t(1:2000), filtered(1:2000));
title('Filtered (100 Hz LP)');
xlabel('Time (s)');
grid on;Prerequisites: Signal Processing Toolbox (or equivalent basic filter functions).
Jobs exceeding sync_timeout (default 30 seconds) are automatically promoted to async execution. Use the mcp_progress() helper to report real-time progress.
What it demonstrates: Async job execution with progress updates via mcp_progress().
% Monte Carlo estimation of pi
% Progress updates are written to a JSON file for the agent to poll
n_trials = 1e6;
inside_count = 0;
for i = 1:n_trials
% Generate random point in unit square
x = rand();
y = rand();
% Check if inside unit circle
if x^2 + y^2 <= 1
inside_count = inside_count + 1
end
% Report progress every 100k trials
if mod(i, 1e5) == 0
progress_pct = (i / n_trials) * 100;
message = sprintf('Trial %d / %d (%.1f%%)', i, n_trials, progress_pct);
% Write progress to temp directory
mcp_progress(__mcp_job_id__, progress_pct, message);
end
end
% Compute pi estimate
pi_estimate = 4 * inside_count / n_trials;
fprintf('Pi estimate: %.6f\n', pi_estimate);
fprintf('Actual pi: %.6f\n', pi);
fprintf('Error: %.6f\n', abs(pi_estimate - pi));Prerequisites: Standard MATLAB.
Agent Usage:
Agent: "Estimate pi using Monte Carlo with 1 million trials"
← Returns job_id: "j-abc123..."
Agent: "What's the progress?"
← 15%, Trial 150000/1000000
Agent: "Check again"
← 87%, Trial 870000/1000000
What it demonstrates: Large computation promoted to async with inline status.
% Compute SVD of large random matrix
% This typically takes >30s and is auto-promoted to async
disp('Generating large random matrix...');
A = rand(3000, 3000);
mcp_progress(__mcp_job_id__, 10, 'Matrix generated, starting SVD...');
disp('Computing SVD...');
[U, S, V] = svd(A);
mcp_progress(__mcp_job_id__, 90, 'SVD complete, analyzing results...');
% Analyze singular values
singular_vals = diag(S);
condition_number = singular_vals(1) / singular_vals(end);
rank_approx = sum(singular_vals > 1e-10);
mcp_progress(__mcp_job_id__, 100, 'Analysis complete');
fprintf('Matrix condition number: %.2e\n', condition_number);
fprintf('Approximate rank: %d\n', rank_approx);
fprintf('Frobenius norm: %.6f\n', norm(A, 'fro'));Prerequisites: Standard MATLAB (large computation may require sufficient memory).
What it demonstrates: Custom iterative algorithm with percentage-based progress reporting.
% Jacobi iterative solver for Ax = b
% A is SPD, b is RHS
% Set up problem
n = 500;
A = gallery('poisson', floor(sqrt(n)));
b = ones(n, 1);
x = zeros(n, 1);
% Jacobi iteration
max_iter = 1000;
tolerance = 1e-6;
D = diag(diag(A));
R = A - D;
for iter = 1:max_iter
x_old = x;
x = D \ (b - R*x_old);
residual = norm(A*x - b);
% Report progress every 100 iterations
if mod(iter, 100) == 0
pct = (iter / max_iter) * 100;
msg = sprintf('Iteration %d/%d, residual=%.2e', iter, max_iter, residual);
mcp_progress(__mcp_job_id__, pct, msg);
end
if residual < tolerance
fprintf('Converged at iteration %d\n', iter);
mcp_progress(__mcp_job_id__, 100, sprintf('Converged, residual=%.2e', residual));
break
end
end
fprintf('Final residual: %.2e\n', norm(A*x - b));Prerequisites: Standard MATLAB.
What it demonstrates: Exposing domain-specific MATLAB functions as first-class MCP tools.
YAML Configuration (custom_tools.yaml):
tools:
- name: "signal_analysis"
function: "my_signal_analysis"
description: "Analyze frequency content and spectral properties of a signal"
parameters:
signal:
type: "array"
description: "Input signal (1D array)"
sample_rate:
type: "number"
description: "Sample rate in Hz"
default: 8000
fft_size:
type: "number"
description: "FFT size for spectral analysis"
default: 1024
return_value:
description: "Struct with dominant_freq, power_spectrum, cepstrum"
- name: "train_model"
function: "my_train_classifier"
description: "Train a simple neural network classifier"
parameters:
X_train:
type: "array"
description: "Training features (NxM)"
y_train:
type: "array"
description: "Training labels (Nx1)"
hidden_size:
type: "number"
description: "Hidden layer size"
default: 64
return_value:
description: "Trained model struct with weights and performance metrics"MATLAB Implementation (my_signal_analysis.m):
function result = my_signal_analysis(signal, sample_rate, fft_size)
% Compute FFT
N = min(fft_size, length(signal));
Y = fft(signal(1:N));
f = (0:N-1) * sample_rate / N;
% Find dominant frequency
[~, idx] = max(abs(Y(1:N/2)));
dominant_freq = f(idx);
% Power spectrum
power_spectrum = abs(Y(1:N/2)).^2 / N;
result.dominant_freq = dominant_freq;
result.power_spectrum = power_spectrum;
result.frequencies = f(1:N/2);
endAgent Usage:
Agent: "Analyze the frequency content of this signal"
← Automatically discovers signal_analysis tool
← Calls my_signal_analysis with proper argument marshaling
← Returns dominant frequency, power spectrum, etc.
What it demonstrates: File upload → processing → result retrieval workflow.
Step 1: Upload CSV data
upload_data(filename="data.csv", content_base64="<base64-encoded CSV>")
Step 2: Process in MATLAB
% Read and analyze uploaded CSV
data_table = readtable('./data.csv');
fprintf('Loaded table with %d rows, %d columns\n', height(data_table), width(data_table));
% Compute summary statistics
summary_stats = table();
for col = data_table.Properties.VariableNames
col_name = col{1};
summary_stats.(col_name) = {mean(data_table.(col_name)), std(data_table.(col_name))};
end
% Save results
writetable(summary_stats, './summary.csv');
disp('Results saved to summary.csv');Step 3: Read results
read_data(filename="summary.csv", format="summary")
What it demonstrates: Creating a figure and viewing it inline.
% Generate a heatmap and save as PNG
data = magic(10);
figure('Position', [100 100 600 500]);
imagesc(data);
colorbar;
title('Magic Square Heatmap');
xlabel('Column');
ylabel('Row');
% Save as PNG (server auto-detects and converts)
savefig('./heatmap.fig');
print('./heatmap.png', '-dpng', '-r150');Agent Usage:
Agent: "Show me the heatmap you created"
← read_image(filename="heatmap.png")
← Returns image rendered inline in UI
server:
name: "matlab-mcp-local"
transport: "stdio"
log_level: "info"
pool:
min_engines: 1
max_engines: 2
execution:
sync_timeout: 30
max_execution_time: 3600
security:
blocked_functions_enabled: trueUse case: Local development with Claude Desktop or Cursor.
server:
name: "matlab-mcp-server"
transport: "sse"
host: "0.0.0.0"
port: 8765
log_level: "warning"
log_file: "/var/log/matlab-mcp/server.log"
pool:
min_engines: 4
max_engines: 16
scale_down_idle_timeout: 600
health_check_interval: 30
execution:
sync_timeout: 30
max_execution_time: 86400
workspace_isolation: true
sessions:
max_sessions: 100
session_timeout: 7200
job_retention_seconds: 604800 # 1 week
security:
blocked_functions_enabled: true
require_proxy_auth: true
max_upload_size_mb: 500
monitoring:
enabled: true
sample_interval: 5
retention_days: 30
db_path: "/var/lib/matlab-mcp/metrics.db"
dashboard_enabled: trueUse case: Shared team server behind reverse proxy with authentication.
sequenceDiagram
participant Agent
participant MCP as MCP Server
participant Executor
participant Pool as Engine Pool
participant MATLAB as MATLAB Engine
Agent->>MCP: execute_code("x = eig(magic(3))")
MCP->>Executor: execute(session_id, code)
Executor->>Executor: Create Job (PENDING)
Executor->>Pool: acquire()
Pool-->>Executor: Engine (IDLE)
Executor->>Executor: Mark RUNNING
Executor->>MATLAB: eval(code)
MATLAB->>MATLAB: Execute
MATLAB-->>Executor: result
Executor->>Executor: Mark COMPLETED
Executor->>Pool: release(engine)
Pool-->>Executor: Released
Executor->>Executor: Format result
Executor-->>MCP: {status, output, ...}
MCP-->>Agent: Inline result
stateDiagram-v2
[*] --> PENDING: execute_code(code)
PENDING --> RUNNING: acquire engine
RUNNING --> COMPLETED: job finishes\n(sync < 30s)
RUNNING --> ASYNC: exceeds sync_timeout
ASYNC --> RUNNING: background execution
RUNNING --> COMPLETED: result ready
RUNNING --> FAILED: error
PENDING --> CANCELLED: cancel_job()
RUNNING --> CANCELLED: cancel_job()
COMPLETED --> [*]
FAILED --> [*]
CANCELLED --> [*]
note right of ASYNC
Job promoted to background
Agent polls get_job_status()
Progress via mcp_progress()
end
All examples above are runnable directly — just ask your AI agent to execute the code block:
"Execute this MATLAB code:"
[paste example code]
The agent will:
- ✅ Validate the code (security check)
- 🔄 Acquire an engine from the pool
- 🚀 Execute the code
- 📊 Convert plots to Plotly JSON + PNG
- 📝 Format and return results
- 🔄 Release the engine back to the pool
For long-running jobs (>30s), the agent receives a job_id immediately and can poll progress with get_job_status(job_id).
- See all tools: MCP-Tools-Reference
- Custom tools: Custom-Tools
- Configuration: Configuration
- Async jobs: Async-Jobs