Skip to content

MCP Protocol

MCP (Model Context Protocol) is an open standard proposed by Anthropic for connecting AI models to external tools and data sources. MateClaw implements a full MCP client that dynamically discovers and invokes tools exposed by external MCP servers, allowing Agents to use third-party capabilities exactly like built-in tools without writing additional code.

What is MCP

MCP uses a client-server architecture and communicates over JSON-RPC 2.0:

┌───────────────────────┐              ┌───────────────────────┐
│     MateClaw           │              │     MCP Server        │
│     (MCP Client)       │              │     (Tool Provider)   │
│                       │   JSON-RPC   │                       │
│  Agent Engine  ───────┼──────────────┼──► Tool A             │
│                       │              │    Tool B             │
│  Tool Registry ◄──────┼──────────────┼─── Tool Discovery     │
│                       │              │    (tools/list)       │
└───────────────────────┘              └───────────────────────┘

Core concepts:

  • MCP Client: MateClaw acts as the client, responsible for connecting to MCP servers, discovering tools, and forwarding tool invocation requests
  • MCP Server: A third-party tool server that declares its available tools and executes tool calls
  • Tool Discovery: The client sends a tools/list request to retrieve all tools and their parameter schemas from the server
  • Tool Invocation: When an Agent decides to call a tool during reasoning, the client forwards the request to the corresponding MCP server for execution

Through MCP, MateClaw can dynamically integrate new tool capabilities without modifying code or restarting the service.

Transport Types

MateClaw supports three MCP transport modes for different deployment scenarios:

stdio (Standard I/O)

Communicates through the stdin/stdout pipes of a subprocess. MateClaw spawns a local child process as the MCP server and exchanges JSON-RPC messages via standard I/O.

MateClaw  ── stdin ──►  MCP Server subprocess
          ◄─ stdout ──

Use cases:

  • Local Node.js/Python MCP tool packages (e.g., @anthropic/mcp-filesystem)
  • Command-line tool wrappers
  • Development and debugging

Advantages: No network configuration needed, works immediately, process isolation Limitations: Local deployment only; MateClaw must be able to execute the specified command directly

streamable_http (Streamable HTTP)

The latest recommended HTTP transport for MCP. Uses standard HTTP POST requests to send JSON-RPC, with responses streamed back over HTTP.

MateClaw  ── HTTP POST ──►  Remote MCP Server
          ◄─ HTTP Stream ──

Use cases:

  • Cloud-deployed MCP servers
  • Scenarios requiring load balancing or reverse proxies
  • Recommended for production environments

Advantages: Standard HTTP protocol, compatible with all network infrastructure (CDN, load balancers, firewalls), supports authentication headers Limitations: Requires the server to support Streamable HTTP transport

sse (Server-Sent Events)

The earlier HTTP transport mode for MCP, using SSE for server-to-client push.

MateClaw  ── HTTP POST ──►  Remote MCP Server
          ◄─── SSE ────────

Use cases:

  • Compatibility with older MCP servers that only support SSE transport
  • When the remote server has not yet upgraded to Streamable HTTP

Advantages: Good compatibility; many existing MCP servers still use this transport Limitations: Being gradually superseded by Streamable HTTP; new projects should prefer streamable_http

Transport Comparison

Featurestdiostreamable_httpsse
DeploymentLocal onlyLocal or remoteLocal or remote
Network requirementNoneHTTP reachableHTTP reachable
AuthenticationVia environment variablesHTTP HeadersHTTP Headers
Process managementMateClaw manages subprocessExternalExternal
RecommendationBest for local toolsBest for remote servicesLegacy compatibility

Configuration via UI

Adding an MCP Server

  1. Log in to the MateClaw admin interface
  2. Navigate to the "Tool Management" page
  3. Switch to the "MCP Servers" tab
  4. Click the "Add MCP Server" button
  5. Fill in the configuration form:
    • Name: Unique server identifier (letters, numbers, _, -, ., and spaces allowed; 1-128 characters)
    • Description: Optional, describes the server's purpose
    • Transport type: Select stdio, streamable_http, or sse
    • Command (stdio): The command to start the MCP server, e.g., npx, node, python
    • Arguments (stdio): Command-line arguments in JSON array format, e.g., ["-y", "@anthropic/mcp-filesystem", "/path"]
    • Working directory (stdio): Optional, the working directory for command execution
    • Environment variables (stdio): JSON object format, e.g., {"API_KEY": "xxx"}; supports ${ENV_VAR} references to system environment variables
    • URL (streamable_http/sse): The MCP server endpoint URL
    • HTTP Headers (streamable_http/sse): JSON object format, e.g., {"Authorization": "Bearer token"}
    • Connect timeout: Connection establishment timeout, default 30 seconds
    • Read timeout: Request response timeout, default 30 seconds
  6. Click "Save"

After saving, if the server is enabled, MateClaw will automatically attempt to connect and discover tools.

Testing a Connection

In the MCP server list, click the "Test Connection" button for a specific server. The test will:

  • Attempt to establish a connection to the MCP server
  • Send a tools/list request to discover available tools
  • Return the connection result (success/failure), latency, and discovered tool list
  • Test connections do not affect currently active connections

Enabling and Disabling

Each MCP server has an independent enable/disable toggle:

  • Enabled: MateClaw establishes a connection; discovered tools become available to Agents
  • Disabled: Connection is dropped; the server's tools are no longer available, but configuration is preserved

Viewing Connection Status

The MCP server list displays real-time status for each server:

  • connected: Connected and tools are available
  • disconnected: Disconnected (manually disabled or not yet connected)
  • error: Connection failed; error details are available

Configuration via REST API

Full CRUD operations for MCP servers are available through the /api/v1/mcp/servers endpoint. All endpoints require JWT authentication.

List All MCP Servers

bash
curl -s http://localhost:18088/api/v1/mcp/servers \
  -H "Authorization: Bearer <token>" | jq

Example response:

json
{
  "code": 200,
  "data": [
    {
      "id": "1",
      "name": "filesystem",
      "transport": "stdio",
      "command": "npx",
      "argsJson": "[\"-y\", \"@anthropic/mcp-filesystem\", \"/home/user\"]",
      "enabled": true,
      "lastStatus": "connected",
      "toolCount": 5,
      "lastConnectedTime": "2026-04-01T10:30:00"
    }
  ]
}

Note: The headersJson and envJson fields in responses are automatically sanitized (e.g., sk-****abcd) to protect sensitive information.

Get a Single MCP Server

bash
curl -s http://localhost:18088/api/v1/mcp/servers/{id} \
  -H "Authorization: Bearer <token>"

Create an MCP Server (stdio type)

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "filesystem",
    "description": "File system read/write tools",
    "transport": "stdio",
    "command": "npx",
    "argsJson": "[\"-y\", \"@anthropic/mcp-filesystem\", \"/home/user/workspace\"]",
    "enabled": true
  }'

Create an MCP Server (streamable_http type)

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "remote-tools",
    "description": "Remote tool service",
    "transport": "streamable_http",
    "url": "https://mcp.example.com/mcp",
    "headersJson": "{\"Authorization\": \"Bearer your-api-key\"}",
    "connectTimeoutSeconds": 15,
    "readTimeoutSeconds": 60,
    "enabled": true
  }'

Update an MCP Server

Uses PATCH semantics -- only pass the fields you want to change; unspecified fields remain unchanged:

bash
curl -X PUT http://localhost:18088/api/v1/mcp/servers/{id} \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "description": "Updated description",
    "readTimeoutSeconds": 60
  }'

After updating, if the server is enabled, it will automatically reconnect.

Delete an MCP Server

bash
curl -X DELETE http://localhost:18088/api/v1/mcp/servers/{id} \
  -H "Authorization: Bearer <token>"

The connection is automatically dropped before deletion. Note: Built-in servers (marked as builtin) cannot be deleted.

Enable/Disable an MCP Server

bash
# Disable
curl -X PUT "http://localhost:18088/api/v1/mcp/servers/{id}/toggle?enabled=false" \
  -H "Authorization: Bearer <token>"

# Enable
curl -X PUT "http://localhost:18088/api/v1/mcp/servers/{id}/toggle?enabled=true" \
  -H "Authorization: Bearer <token>"

Test Connection

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers/{id}/test \
  -H "Authorization: Bearer <token>"

Example response:

json
{
  "code": 200,
  "data": {
    "success": true,
    "message": "Connected",
    "toolCount": 5,
    "latencyMs": 1234,
    "discoveredTools": ["read_file", "write_file", "list_directory", "search_files", "get_file_info"],
    "timestamp": "2026-04-01T10:30:00"
  }
}

Refresh All Connections

Disconnects all existing connections and reconnects all enabled MCP servers:

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers/refresh \
  -H "Authorization: Bearer <token>"

Practical Examples

Example 1: Filesystem MCP Server (stdio)

Use the official Anthropic filesystem MCP server to give Agents file read/write and directory search capabilities.

Prerequisites: Node.js (v18+) and npm installed on the server.

Create via API:

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "filesystem",
    "description": "File system read/write (restricted to specified directory)",
    "transport": "stdio",
    "command": "npx",
    "argsJson": "[\"-y\", \"@anthropic/mcp-filesystem\", \"/home/user/workspace\"]",
    "enabled": true
  }'

Once connected, the following tools will be discovered:

Tool NameDescription
read_fileRead file contents
write_fileWrite to a file
list_directoryList directory contents
search_filesSearch for files
get_file_infoGet file metadata

Security note: @anthropic/mcp-filesystem only allows access to the directory specified in the startup arguments and its subdirectories, preventing access to other system files.

Example 2: Remote HTTP MCP Server (streamable_http with Authentication)

Connect to a remote MCP server that requires API key authentication, such as an internal enterprise data query service.

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "internal-data-service",
    "description": "Internal enterprise data query MCP service",
    "transport": "streamable_http",
    "url": "https://mcp-api.internal.example.com/mcp",
    "headersJson": "{\"Authorization\": \"Bearer sk-your-api-key\", \"X-Team-Id\": \"engineering\"}",
    "connectTimeoutSeconds": 10,
    "readTimeoutSeconds": 120,
    "enabled": true
  }'

Configuration notes:

  • url points to the remote MCP server's Streamable HTTP endpoint
  • headersJson provides authentication; these headers are sent with every HTTP request
  • Header values support environment variable references: {"Authorization": "Bearer ${MCP_API_KEY}"} will be replaced at runtime with the system environment variable value
  • A longer readTimeoutSeconds is appropriate for long-running data queries

Example 3: Tavily Search MCP Server (stdio with Environment Variables)

Integrate the Tavily search MCP server to give Agents real-time web search capabilities.

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "tavily-search",
    "description": "Tavily real-time web search",
    "transport": "stdio",
    "command": "npx",
    "argsJson": "[\"-y\", \"@anthropic/mcp-tavily\"]",
    "envJson": "{\"TAVILY_API_KEY\": \"${TAVILY_API_KEY}\"}",
    "enabled": true
  }'

Configuration notes:

  • ${TAVILY_API_KEY} in envJson is replaced at runtime with the corresponding system environment variable from the MateClaw process
  • You can also write the key directly: {"TAVILY_API_KEY": "tvly-xxxxxx"}, but using environment variable references is recommended to avoid storing secrets in the database
  • The subprocess inherits the specified environment variables

Example 4: Legacy SSE MCP Server

Connect to an MCP server that only supports SSE transport:

bash
curl -X POST http://localhost:18088/api/v1/mcp/servers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "legacy-mcp-server",
    "description": "Legacy SSE transport MCP server",
    "transport": "sse",
    "url": "http://192.168.1.100:3001/sse",
    "enabled": true
  }'

How MCP Tools Are Registered

MCP tools go through the following pipeline from discovery to becoming available for Agent invocation:

McpServerBootstrapRunner (application startup)
        |
        v
McpServerService.initEnabledServers()
        |  Iterates all enabled MCP servers
        v
McpClientManager.connect(server)
        |  1. Build McpSyncClient based on transport type
        |  2. Call client.initialize() to establish connection
        |  3. Call client.listTools() to discover tools
        |  4. Cache in clients and toolsCache maps
        v
McpToolCallbackProvider.getToolCallbacks()
        |  Implements Spring AI's ToolCallbackProvider interface
        |  Retrieves ToolCallbacks from all active clients in McpClientManager
        v
ToolRegistry
        |  Aggregates built-in tools + MCP tools
        v
Agent Tool Set
        |  Agents can invoke any registered tool during reasoning

Key implementation details:

  • McpToolCallbackProvider implements Spring AI's ToolCallbackProvider interface. Every call to getToolCallbacks() fetches the latest active tool list from McpClientManager, so adding or removing MCP servers takes effect without restarting the application.
  • SyncMcpToolCallbackProvider (built into Spring AI) converts a single McpSyncClient's tools into a ToolCallback array.
  • MCP tools and built-in @Tool-annotated tools are completely identical at the Agent invocation layer -- Agents cannot and do not need to distinguish the tool source.
  • Each MCP tool's name, description, and parameter schema are declared by the MCP server in its tools/list response.

Connection Management

Automatic Connection on Startup

After MateClaw finishes starting, McpServerBootstrapRunner automatically connects all MCP servers marked as enabled=true in the database. A single server's connection failure does not block other servers or application startup.

Thread Safety

McpClientManager uses a ConcurrentHashMap to store active clients and maintains an independent ReentrantLock per server, ensuring that connect/replace/remove operations on the same server do not conflict concurrently.

Connection Replacement

When MCP server configuration is updated, the system follows a "connect new, then disconnect old" replacement strategy:

  1. Create and initialize a new McpSyncClient with the updated configuration
  2. After the new client connects successfully, place it into the active client pool
  3. Close the old client

If the new client fails to connect, the old client remains unaffected (if one exists).

Subprocess Cleanup

For stdio-type MCP servers, MateClaw spawns a child process. The following scenarios ensure proper subprocess cleanup:

  • Manually disabling or deleting an MCP server
  • Replacing an MCP server's configuration
  • Application shutdown (via @PreDestroy hook)
  • Connection failure (subprocesses started during initialization are closed)

Status Monitoring

After each connection operation, the system persists the connection result to the database:

  • last_status: connected / disconnected / error
  • last_error: Error message (cleared on successful connection)
  • last_connected_time: Timestamp of the last successful connection
  • tool_count: Number of currently discovered tools

Manual Refresh

The "Refresh All Connections" operation (API: POST /api/v1/mcp/servers/refresh) disconnects all existing connections and reconnects all enabled servers. This is useful for troubleshooting connection issues or when the MCP server-side tool list has changed and needs rediscovery.

Database Storage

MCP server configurations are stored in the mate_mcp_server table. The complete field list:

ColumnTypeDefaultDescription
idBIGINT-Primary key (snowflake ID)
nameVARCHAR(128)-Server name, unique identifier. Allows letters, numbers, _, -, ., and spaces; 1-128 characters
descriptionTEXTNULLServer description
transportVARCHAR(32)stdioTransport type: stdio / streamable_http / sse
urlVARCHAR(512)NULLRemote URL (required for streamable_http/sse types)
headers_jsonTEXTNULLHTTP headers as JSON object, e.g., {"Authorization": "Bearer xxx"}
commandVARCHAR(512)NULLStartup command (required for stdio type), e.g., npx, node, python
args_jsonTEXTNULLCommand arguments as JSON array, e.g., ["-y", "@anthropic/mcp-filesystem"]
env_jsonTEXTNULLEnvironment variables as JSON object; supports ${VAR} references to system env vars
cwdVARCHAR(512)NULLWorking directory (used by stdio type)
enabledBOOLEANTRUEWhether the server is active
connect_timeout_secondsINT30Connection establishment timeout in seconds (used by HTTP transport types)
read_timeout_secondsINT30Request response timeout in seconds; controls initialize/listTools/callTool timeouts
last_statusVARCHAR(32)disconnectedLast connection status: connected / disconnected / error
last_errorTEXTNULLLast error message
last_connected_timeDATETIMENULLLast successful connection timestamp
tool_countINT0Number of discovered tools
builtinBOOLEANFALSEWhether the server is built-in (built-in servers cannot be deleted)
create_timeDATETIME-Creation timestamp
update_timeDATETIME-Last update timestamp
deletedINT0Logical delete flag

Sensitive Data Sanitization

When returning MCP server lists via the API, values in headers_json and env_json are automatically masked (showing the first few and last four characters, with * in between). args_json is returned as-is since it does not contain sensitive information.

Environment Variable References

Values in env_json and headers_json support system environment variable references:

  • ${VAR_NAME} -- Exact match and replacement
  • $VAR_NAME -- Regex match (ensures variables with similar prefixes are not accidentally replaced)

For example, {"TAVILY_API_KEY": "${TAVILY_API_KEY}"} is replaced at runtime with the corresponding value from the MateClaw process environment. This avoids storing plaintext secrets in the database.

Troubleshooting

Command Not Found (stdio type)

Symptom: Connection fails with an error containing "command not found" or "No such file or directory".

Steps:

  1. Confirm the command specified in the command field is available in the PATH of the user running MateClaw
  2. Manually run the command on the server terminal to verify: which npx or npx --version
  3. If deploying with Docker, confirm the command is installed inside the container
  4. You can use the full path instead of the command name, e.g., /usr/local/bin/npx

Connection Timeout

Symptom: Connection fails with an error containing "timeout" or "timed out".

Steps:

  1. For HTTP/SSE types, confirm the URL is reachable: curl -v <url>
  2. Check firewall rules to ensure outbound connections are allowed
  3. Increase connectTimeoutSeconds and readTimeoutSeconds as needed
  4. For stdio type, the first npx -y execution may need to download packages, which takes longer -- increase the timeout or pre-install the package

SSL/TLS Errors

Symptom: Connection to an HTTPS endpoint fails with an error containing "SSL" or "certificate".

Steps:

  1. Confirm the remote MCP server's SSL certificate is valid and not expired
  2. If using a self-signed certificate, add the CA certificate to the JVM trust store
  3. Confirm the JDK version in the MateClaw runtime supports the required TLS version

Tools Not Showing Up

Symptom: MCP server status is connected, but corresponding tools do not appear in the Agent tool list.

Steps:

  1. Check whether the tool_count field is greater than 0
  2. Use the test connection feature to confirm the discoveredTools list is not empty
  3. Verify that the MCP server correctly implements the tools/list endpoint
  4. Check MateClaw backend logs for McpToolCallbackProvider-related output

Tool Invocation Failures

Symptom: Agent receives an error when calling an MCP tool.

Steps:

  1. Check the MateClaw backend logs for specific error messages
  2. Confirm the MCP server process is still running (stdio type)
  3. Confirm the remote MCP server is reachable (HTTP/SSE type)
  4. Check whether readTimeoutSeconds is sufficient (some tools take longer to execute)
  5. Try refreshing connections: POST /api/v1/mcp/servers/refresh

Orphaned Subprocesses (stdio type)

Symptom: After stopping MateClaw, MCP child processes are still running.

Steps:

  1. Under normal circumstances, the @PreDestroy hook cleans up all subprocesses
  2. If MateClaw was forcefully terminated (kill -9), subprocesses may remain and must be cleaned up manually
  3. Use ps aux | grep mcp to find and terminate orphaned processes

Next Steps