Skip to content

feat: Add MATLAB MCP server #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

XiaoliangQi
Copy link
Contributor

@XiaoliangQi XiaoliangQi commented Jun 22, 2025

User description

This commit introduces a new MCP server, matlab-server, allowing agents to execute MATLAB code.

Key features:

  • Executes MATLAB code via matlab -batch.
  • Supports both text output and capturing plots as PNG images.
  • Includes comprehensive README for setup and usage.
  • Provides unit tests with mocking for MATLAB interaction.

The server structure is based on the mathematica-check server. It checks for MATLAB availability and handles errors during execution.

Includes:

  • Server logic in servers/matlab-server/src/matlab_server/server.py.
  • Project files: pyproject.toml, setup.py.
  • Documentation: servers/matlab-server/README.md.
  • Tests: servers/matlab-server/tests/test_server.py and pytest.ini.
  • Python version file: servers/matlab-server/.python-version (set to 3.11.8).

PR Type

Enhancement


Description

  • Add complete MATLAB MCP server implementation

  • Support text output and PNG plot generation

  • Include comprehensive test suite with mocking

  • Provide detailed documentation and setup instructions


Changes walkthrough 📝

Relevant files
Configuration changes
5 files
setup.py
Package setup configuration for MATLAB server                       
+17/-0   
.python-version
Update Python version to 3.11.8                                                   
+1/-1     
.python-version
Set Python version for MATLAB server                                         
+1/-0     
pyproject.toml
Project metadata and dependencies configuration                   
+16/-0   
pytest.ini
Pytest configuration for testing                                                 
+3/-0     
Miscellaneous
1 files
__init__.py
Python package initialization file                                             
+2/-0     
Enhancement
1 files
server.py
Core MATLAB MCP server implementation                                       
+277/-0 
Tests
1 files
test_server.py
Comprehensive test suite with mocking                                       
+316/-0 
Documentation
1 files
README.md
Complete documentation and setup guide                                     
+154/-0 

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • This commit introduces a new MCP server, `matlab-server`, allowing agents to execute MATLAB code.
    
    Key features:
    - Executes MATLAB code via `matlab -batch`.
    - Supports both text output and capturing plots as PNG images.
    - Includes comprehensive README for setup and usage.
    - Provides unit tests with mocking for MATLAB interaction.
    
    The server structure is based on the `mathematica-check` server.
    It checks for MATLAB availability and handles errors during execution.
    
    Includes:
    - Server logic in `servers/matlab-server/src/matlab_server/server.py`.
    - Project files: `pyproject.toml`, `setup.py`.
    - Documentation: `servers/matlab-server/README.md`.
    - Tests: `servers/matlab-server/tests/test_server.py` and `pytest.ini`.
    - Python version file: `servers/matlab-server/.python-version` (set to 3.11.8).
    @Copilot Copilot AI review requested due to automatic review settings June 22, 2025 00:30
    Copy link
    Contributor

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 Security concerns

    Command injection:
    The code parameter from user input is directly embedded into MATLAB command strings without proper sanitization or escaping. An attacker could potentially inject malicious commands by crafting MATLAB code that breaks out of the intended context. For example, malicious code could include MATLAB commands that interact with the file system or execute system commands through MATLAB's system() function. The code should implement proper input validation and consider using safer execution methods.

    ⚡ Recommended focus areas for review

    Security Risk

    The code directly passes user input to subprocess execution without proper sanitization. The code parameter is inserted into MATLAB command strings that are executed via subprocess, potentially allowing command injection attacks.

    matlab_command_code = f"""
    try
        {code}
        % Check if a figure exists before trying to save
        if ~isempty(get(groot,'CurrentFigure'))
            print('-dpng', '{safe_plot_file_path}');
        else
            disp('MATLAB_WARNING: No figure was generated to save.');
        end
    catch ME
        disp(['MATLAB_ERROR: ' ME.message]);
        % Optional: rethrow(ME); % if we want MATLAB to exit with error code for script errors
    end
    exit; % Ensure MATLAB exits
    """
    Resource Leak

    Temporary files created by tempfile.mkstemp() may not be properly cleaned up if exceptions occur before reaching the finally block. The file descriptor is closed but the file cleanup in finally block might not execute in all error scenarios.

    fd, temp_plot_file_path = tempfile.mkstemp(suffix=".png")
    os.close(fd) # Close the file descriptor, MATLAB will open and write to it.
    temp_plot_file = temp_plot_file_path
    Error Handling

    The global state variables for MATLAB availability checking are not thread-safe and could lead to race conditions in concurrent environments. Multiple simultaneous calls could interfere with each other's state.

    _matlab_checked = False
    _matlab_available = False
    
    
    async def check_matlab_installation() -> bool:
        """Checks if MATLAB is installed and accessible."""
        global _matlab_checked, _matlab_available
        if _matlab_checked:
            return _matlab_available

    Copy link
    Contributor

    @Copilot Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull Request Overview

    This PR introduces a new MATLAB MCP server to execute MATLAB code and capture both text and plot outputs. Key changes include adding the server logic and MCP tool in Python, a comprehensive suite of unit tests using async mocks, and updated configuration files (setup.py, pyproject.toml, pytest.ini, and README).

    Reviewed Changes

    Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

    Show a summary per file
    File Description
    servers/matlab-server/tests/test_server.py Comprehensive unit tests covering MATLAB installation checks, text/plot code execution, and global state resets.
    servers/matlab-server/src/matlab_server/server.py Server logic for checking MATLAB availability, executing MATLAB code, and handling plot output.
    servers/matlab-server/src/matlab_server/init.py Package initialization file.
    servers/matlab-server/setup.py Build and packaging configuration for the MATLAB server.
    servers/matlab-server/pytest.ini Pytest configuration ensuring proper module discovery and asyncio mode setup.
    servers/matlab-server/pyproject.toml Project metadata and dependency configuration.
    servers/matlab-server/README.md Updated documentation detailing installation, usage, and integration with MCP clients.
    servers/matlab-server/.python-version Specifies the required Python version (3.11.8) for the MATLAB server.
    .python-version Updated global Python version to 3.11.8.

    # The user's code should generate a figure. We then save it.
    # `print('-dpng', '{filepath}')` saves the current figure.
    # We add `exit;` to ensure MATLAB closes after execution.
    matlab_command_code = f"""
    Copy link
    Preview

    Copilot AI Jun 22, 2025

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Consider using textwrap.dedent to build multiline MATLAB command strings so that unintended leading whitespace does not affect MATLAB's interpretation of the script.

    Suggested change
    matlab_command_code = f"""
    matlab_command_code = textwrap.dedent(f"""

    Copilot uses AI. Check for mistakes.

    Copy link
    Contributor

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Security
    Fix temporary file race condition

    Closing the file descriptor immediately after mkstemp() creates a race condition
    where another process could potentially claim the file path before MATLAB writes
    to it. Consider using tempfile.NamedTemporaryFile with delete=False for safer
    temporary file handling.

    servers/matlab-server/src/matlab_server/server.py [106-107]

    -fd, temp_plot_file_path = tempfile.mkstemp(suffix=".png")
    -os.close(fd) # Close the file descriptor, MATLAB will open and write to it.
    +temp_file = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
    +temp_plot_file_path = temp_file.name
    +temp_file.close()  # Close but don't delete
    • Apply / Chat
    Suggestion importance[1-10]: 9

    __

    Why: The suggestion correctly identifies a potential race condition (TOCTOU vulnerability) when creating a temporary file. The proposed solution using tempfile.NamedTemporaryFile with delete=False is a much safer and more robust way to handle this, making it a critical security improvement.

    High
    General
    Handle critical stderr messages properly

    The code continues execution after logging a stderr warning, but stderr from
    MATLAB often indicates serious issues that should be handled more carefully.
    Consider evaluating if the stderr content warrants stopping execution or
    returning an error.

    servers/matlab-server/src/matlab_server/server.py [174-178]

     if stderr_str: # Process-level stderr
         logger.warning(f"MATLAB process produced stderr: {stderr_str}")
    -
    +    # Consider if stderr indicates a critical error that should halt execution
    +    if any(critical_term in stderr_str.lower() for critical_term in ['error', 'failed', 'exception']):
    +        raise RuntimeError(f"MATLAB execution failed with critical stderr: {stderr_str}")
     
     if output_format == "plot":
    • Apply / Chat
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly points out that stderr from the MATLAB process might contain critical errors that should halt execution. While the current code logs stderr as a warning, explicitly checking for error keywords and raising a RuntimeError would make the error handling more robust and prevent silent failures.

    Medium
    • More

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant