Skip to content

Examples

github-actions[bot] edited this page Apr 3, 2026 · 20 revisions

Examples

This page provides practical, real-world usage examples for the MATLAB MCP Server across Python, JavaScript, and MATLAB.

Architecture Overview

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"]
Loading

Basic Examples — JavaScript

Example 1: Connect via Streamable HTTP (Recommended)

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));

Example 2: Execute MATLAB Code

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);

Example 3: Poll Async Job Status

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);

Intermediate Examples — Python

Example 1: Configure and Start Server Programmatically

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.py

Example 2: Execute MATLAB Code Synchronously

Execute 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())

Example 3: Upload Data and Process It

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())

Example 4: Discover Available Toolboxes

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())

Example 5: Handle Long-Running Jobs with Progress

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())

Advanced Examples — MATLAB

Example 1: Custom Tool Definition via YAML

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.yaml

The tools signal_analysis and linear_regression now appear in the tool list and can be called by agents.

Example 2: User-Defined MATLAB Function

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 ...
    );
end

Register 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}

Example 3: Generate and Return Plots

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.

Example 4: Human-in-the-Loop Approval

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]);
end

Configuration for HITL approval (config.yaml):

hitl:
  enabled: true
  protected_functions:
    - delete
    - rmdir
    - system
  protect_file_ops: true
  all_execute: false

When the agent tries to execute the code above, the server will:

  1. Detect the delete() call
  2. Call ctx.elicit() to request human approval
  3. Wait for the human to approve/decline in the agent UI
  4. Only proceed if approved

Configuration Examples

Minimal Single-User Setup

File: config.yaml

server:
  transport: "stdio"
  log_level: "info"

pool:
  min_engines: 1
  max_engines: 2

execution:
  sync_timeout: 30

security:
  blocked_functions_enabled: true

Start:

matlab-mcp --config config.yaml

Windows 10 No-Admin Multi-User Setup

File: 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: true

Start with auth token:

export MATLAB_MCP_AUTH_TOKEN=$(matlab-mcp --generate-token | grep export | cut -d' ' -f2)
matlab-mcp --config config.yaml

Load-Balanced Cluster (Stateless HTTP)

File: 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: true

Deploy 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";
    }
}

Troubleshooting

MATLAB Engine Fails to Start

Symptom: MATLAB engine startup timeout

Solution:

# Increase engine startup timeout
export MATLAB_MCP_POOL_ENGINE_START_TIMEOUT=300
matlab-mcp --config config.yaml

Auth Token Rejected

Symptom: 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=abc123def456ghi789jkl012mno345pqr678stu901vwx234yza567bcd890

Copy the export line and set it before connecting agents.

Session Isolation Not Working

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: 50

Each HTTP client with a unique mcp-session-id header gets its own session directory.


For more examples, see the examples/ directory in the repository.

Clone this wiki locally