-
Notifications
You must be signed in to change notification settings - Fork 0
Examples
This page provides practical, real-world usage examples for the MATLAB MCP Server across Python, JavaScript, and MATLAB.
graph TB
Agent["AI Agent<br/>(Claude, Cursor, Codex CLI)"]
Agent -->|MCP Protocol| Transport{Transport Mode}
Transport -->|Local| Stdio["stdio<br/>Single Agent"]
Transport -->|Remote| HTTP["Streamable HTTP<br/>Multi-Agent"]
Transport -->|Legacy| SSE["SSE<br/>Deprecated"]
Stdio --> Auth["Authentication<br/>(Bearer Token)"]
HTTP --> Auth
SSE --> Auth
Auth --> Server["MATLAB MCP Server<br/>(FastMCP 3.2.0)"]
Server --> Tools["20 Built-in Tools<br/>+ Custom Tools"]
Tools --> Executor["Job Executor<br/>(Sync/Async)"]
Executor --> Pool["Engine Pool Manager<br/>(Elastic Scaling)"]
Pool --> MATLAB["MATLAB Engine<br/>(R2022b+)"]
Tools --> Session["Session Manager<br/>(Workspace Isolation)"]
Session --> FileOps["File Operations<br/>& Temp Storage"]
Tools --> Monitoring["Monitoring & Metrics<br/>Dashboard"]
Prerequisites:
- MATLAB MCP Server running:
matlab-mcp --transport streamablehttp --port 8765 - Node.js 18+
- MCP SDK:
npm install @modelcontextprotocol/sdk
Connect and list tools:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import fetch from "node-fetch";
// For HTTP transport, use fetch-based connection
const response = await fetch("http://localhost:8765/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MATLAB_MCP_AUTH_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/list",
params: {}
})
});
const result = await response.json();
console.log("Available tools:", result.result.tools.map(t => t.name));Execute a simple calculation:
const executeRequest = {
jsonrpc: "2.0",
id: 2,
method: "tools/call",
params: {
name: "execute_code",
arguments: {
code: `
% Calculate eigenvalues of a magic matrix
A = magic(3);
eigenvalues = eig(A);
disp(eigenvalues);
`
}
}
};
const response = await fetch("http://localhost:8765/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MATLAB_MCP_AUTH_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify(executeRequest)
});
const result = await response.json();
console.log("Execution result:", result.result.content[0].text);For long-running jobs (exceeds sync timeout):
// First, execute code that will auto-promote to async
const longRunningCode = `
% Monte Carlo Pi estimation
n = 1e7;
inside = sum(rand(n,1).^2 + rand(n,1).^2 <= 1);
pi_estimate = 4 * inside / n;
fprintf('Pi ≈ %.6f\\n', pi_estimate);
`;
const execResponse = await fetch("http://localhost:8765/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MATLAB_MCP_AUTH_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 3,
method: "tools/call",
params: {
name: "execute_code",
arguments: { code: longRunningCode }
}
})
});
const execResult = await execResponse.json();
const jobId = execResult.result.content[0].text.match(/Job ID: (\S+)/)?.[1];
// Poll job status
async function pollJob(jobId) {
for (let i = 0; i < 30; i++) {
const statusResponse = await fetch("http://localhost:8765/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MATLAB_MCP_AUTH_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 4,
method: "tools/call",
params: {
name: "get_job_status",
arguments: { job_id: jobId }
}
})
});
const statusResult = await statusResponse.json();
const status = statusResult.result.content[0].text;
if (status.includes("COMPLETED") || status.includes("FAILED")) {
return status;
}
console.log(`Job ${jobId} status: ${status}`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
const finalStatus = await pollJob(jobId);
console.log("Final job status:", finalStatus);Prerequisites:
- Python 3.10+
- MATLAB R2022b+ with Engine API
pip install matlab-mcp-python
Start server with custom configuration:
import asyncio
import os
from pathlib import Path
from matlab_mcp.config import AppConfig, ServerConfig, PoolConfig
from matlab_mcp.server import create_server
async def main():
# Create config programmatically
config = AppConfig(
server=ServerConfig(
transport="streamablehttp",
host="127.0.0.1",
port=8765,
log_level="info"
),
pool=PoolConfig(
min_engines=2,
max_engines=8,
engine_start_timeout=120
)
)
# Create server with all subsystems
server = create_server(config)
# Start server (runs forever until interrupted)
await server.run()
if __name__ == "__main__":
# Set bearer token for HTTP auth
os.environ["MATLAB_MCP_AUTH_TOKEN"] = os.environ.get(
"MATLAB_MCP_AUTH_TOKEN",
"abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef"
)
asyncio.run(main())Run it:
export MATLAB_MCP_AUTH_TOKEN=$(matlab-mcp --generate-token | grep "export" | cut -d' ' -f2)
python my_server.pyExecute code and get results immediately:
import asyncio
from matlab_mcp.server import create_server
from matlab_mcp.config import AppConfig
async def example_sync_execution():
config = AppConfig()
server = create_server(config)
# Manually invoke tool (simulating MCP call)
result = await server.execute_code_impl(
code="""
% Solve a linear system
A = [3 2; 2 3];
b = [5; 5];
x = A \\ b;
disp(x);
"""
)
print("Result:", result)
# Output: {'type': 'text', 'text': '1\n2\n'}
asyncio.run(example_sync_execution())Upload CSV, process in MATLAB, retrieve results:
import asyncio
import base64
from matlab_mcp.server import create_server
from matlab_mcp.config import AppConfig
async def example_file_workflow():
config = AppConfig()
server = create_server(config)
# Create sample CSV data
csv_content = "x,y\n1,2\n3,4\n5,6\n"
csv_b64 = base64.b64encode(csv_content.encode()).decode()
# Upload file
upload_result = await server.upload_data_impl(
filename="data.csv",
data=csv_b64,
session_id="default"
)
print("Upload:", upload_result)
# Process in MATLAB
process_result = await server.execute_code_impl(
code="""
% Read and process CSV
data = readtable('data.csv');
mean_y = mean(data.y);
fprintf('Mean of y: %.2f\\n', mean_y);
save('result.mat', 'mean_y');
""",
session_id="default"
)
print("Processing:", process_result)
# Read result file
read_result = await server.read_data_impl(
filename="result.mat",
format="summary",
session_id="default"
)
print("Results:", read_result)
asyncio.run(example_file_workflow())List installed toolboxes and functions:
import asyncio
from matlab_mcp.server import create_server
from matlab_mcp.config import AppConfig
async def example_discovery():
config = AppConfig()
server = create_server(config)
# List toolboxes
toolboxes = await server.list_toolboxes_impl()
print("Installed toolboxes:", toolboxes)
# Get functions from Signal Processing Toolbox
functions = await server.list_functions_impl(
toolbox="Signal Processing"
)
print("Signal Processing functions:", functions)
# Get help for a specific function
help_text = await server.get_help_impl(
function_name="fft"
)
print("FFT help:", help_text)
asyncio.run(example_discovery())Execute code with progress tracking:
import asyncio
import time
from matlab_mcp.server import create_server
from matlab_mcp.config import AppConfig
async def example_async_with_progress():
config = AppConfig(
execution=ExecutionConfig(
sync_timeout=10 # Promote to async after 10 seconds
)
)
server = create_server(config)
job_result = await server.execute_code_impl(
code="""
% Long-running simulation
n = 1e6;
inside = 0;
for i = 1:n
if rand()^2 + rand()^2 <= 1
inside = inside + 1;
end
if mod(i, 1e5) == 0
mcp_progress(__mcp_job_id__, i/n*100, ...
sprintf('Iteration %d/%d', i, n));
end
end
fprintf('Pi estimate: %.6f\\n', 4*inside/n);
"""
)
# Check if async
if "job_id" in str(job_result):
job_id = job_result['text'].split("Job ID: ")[1].split("\n")[0]
print(f"Job promoted to async: {job_id}")
# Poll status
for _ in range(60):
status = await server.get_job_status_impl(job_id)
print(f"Status: {status}")
if "COMPLETED" in str(status):
result = await server.get_job_result_impl(job_id)
print(f"Final result: {result}")
break
await asyncio.sleep(2)
else:
print(f"Sync result: {job_result}")
asyncio.run(example_async_with_progress())File: custom_tools.yaml
custom_tools:
- name: "signal_analysis"
description: "Analyze frequency content of a signal using FFT"
function_name: "signal_processing.fft_analysis"
parameters:
signal:
type: "array"
description: "Input signal vector"
sampling_rate:
type: "float"
description: "Sampling frequency in Hz"
default: 1000.0
returns:
description: "Frequency spectrum with peaks identified"
- name: "linear_regression"
description: "Fit linear model to 2D data"
function_name: "statistics.fit_linear"
parameters:
x_data:
type: "array"
description: "X values"
y_data:
type: "array"
description: "Y values"
returns:
description: "Slope, intercept, and R-squared"Run server with custom tools:
matlab-mcp --config config.yamlThe tools signal_analysis and linear_regression now appear in the tool list and can be called by agents.
File: +mylib/signal_analysis.m
function result = signal_analysis(signal, sampling_rate)
% Analyze frequency content via FFT
%
% Inputs:
% signal - input signal vector
% sampling_rate - sampling frequency (Hz)
%
% Output:
% result - struct with 'frequencies', 'magnitudes', 'peaks'
N = length(signal);
Y = fft(signal);
freqs = (0:N-1) * sampling_rate / N;
% Get magnitude spectrum (one-sided)
mags = 2 * abs(Y(1:N/2)) / N;
freqs = freqs(1:N/2);
% Find peaks
[peak_mags, peak_idx] = findpeaks(mags, 'SortStr', 'descend', 'NPeaks', 5);
peak_freqs = freqs(peak_idx);
result = struct(...
'frequencies', freqs, ...
'magnitudes', mags, ...
'peak_frequencies', peak_freqs, ...
'peak_magnitudes', peak_mags ...
);
endRegister in custom_tools.yaml:
custom_tools:
- name: "fft_analysis"
function_name: "mylib.signal_analysis"
parameters:
signal: {type: "array"}
sampling_rate: {type: "float", default: 1000.0}MATLAB code that creates a figure and returns it:
% Create a figure the agent can view
x = linspace(0, 2*pi, 200);
y1 = sin(x);
y2 = cos(x);
figure('Visible', 'off');
plot(x, y1, 'b-', 'LineWidth', 2); hold on;
plot(x, y2, 'r--', 'LineWidth', 2);
xlabel('x'); ylabel('y');
legend('sin(x)', 'cos(x)');
title('Trigonometric Functions');
grid on;
% Save and return
saveas(gcf, 'trig_plot.png');
close all;
disp("Plot saved to trig_plot.png");Agent can then call:
read_image(filename="trig_plot.png")
To view the plot directly in the chat.
MATLAB code with sensitive operations (requires approval):
% This code calls delete() — a protected function
% Will pause for human approval if HITL enabled in config
file_to_remove = 'temp_data.csv';
if isfile(file_to_remove)
delete(file_to_remove);
disp(['Deleted: ' file_to_remove]);
else
disp(['File not found: ' file_to_remove]);
endConfiguration for HITL approval (config.yaml):
hitl:
enabled: true
protected_functions:
- delete
- rmdir
- system
protect_file_ops: true
all_execute: falseWhen the agent tries to execute the code above, the server will:
- Detect the
delete()call - Call
ctx.elicit()to request human approval - Wait for the human to approve/decline in the agent UI
- Only proceed if approved
File: config.yaml
server:
transport: "stdio"
log_level: "info"
pool:
min_engines: 1
max_engines: 2
execution:
sync_timeout: 30
security:
blocked_functions_enabled: trueStart:
matlab-mcp --config config.yamlFile: config.yaml
server:
name: "Team MATLAB Server"
transport: "streamablehttp"
host: "127.0.0.1" # Loopback — no firewall prompts
port: 8765
log_level: "info"
pool:
min_engines: 2
max_engines: 8
health_check_interval: 60
execution:
sync_timeout: 30
sessions:
max_sessions: 50
idle_timeout_seconds: 3600
security:
blocked_functions_enabled: true
max_upload_size_mb: 500
monitoring:
enabled: true
dashboard_enabled: trueStart with auth token:
export MATLAB_MCP_AUTH_TOKEN=$(matlab-mcp --generate-token | grep export | cut -d' ' -f2)
matlab-mcp --config config.yamlFile: config.yaml
server:
name: "Cluster Node"
transport: "streamablehttp"
host: "0.0.0.0" # Accept from load balancer
port: 8765
stateless_http: true # Each request gets ephemeral temp dir
pool:
min_engines: 4
max_engines: 16
proactive_warmup_threshold: 0.7
sessions:
idle_timeout_seconds: 300 # Short timeout in cluster
monitoring:
enabled: trueDeploy behind reverse proxy (nginx) with auth:
server {
listen 443 ssl http2;
server_name matlab-mcp.company.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8765;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# Inject bearer token from reverse proxy auth
proxy_set_header Authorization "Bearer $mqtt_token";
}
}Symptom: MATLAB engine startup timeout
Solution:
# Increase engine startup timeout
export MATLAB_MCP_POOL_ENGINE_START_TIMEOUT=300
matlab-mcp --config config.yamlSymptom: HTTP 401 Unauthorized when connecting with agent
Generate a valid token:
matlab-mcp --generate-token
# Output:
# 64-character hex token:
# abc123def456ghi789jkl012mno345pqr678stu901vwx234yza567bcd890
#
# POSIX shell:
# export MATLAB_MCP_AUTH_TOKEN=abc123def456ghi789jkl012mno345pqr678stu901vwx234yza567bcd890Copy the export line and set it before connecting agents.
Symptom: Multiple agents are sharing the same temp directory
Check configuration:
server:
transport: "streamablehttp" # Required for multi-session
# NOT stateless_http: true (that creates ephemeral dirs)
sessions:
max_sessions: 50Each HTTP client with a unique mcp-session-id header gets its own session directory.
For more examples, see the examples/ directory in the repository.