Understanding mcp_servers_config in Dify MCP-SSE Agent: JSON Structure and Validation Guide

The mcp_servers_config JSON structure defines connection parameters for Model-Centric Protocol (MCP) servers in the Dify MCP-SSE agent, specifying transport protocols, URLs, and authentication headers, while the plugin validates it through JSON syntax checks, server name pattern matching, and transport protocol verification.

The mcp_servers_config parameter is a critical configuration component in the junjiem/dify-plugin-agent-mcp_sse repository that enables the FunctionCalling agent strategy to discover and invoke tools from external MCP servers. This JSON-encoded string defines how the agent establishes connections via Server-Sent Events (SSE) or Streamable HTTP transports, and the plugin implements multiple validation layers to ensure configuration integrity before attempting remote connections.

Structure of mcp_servers_config

Top-Level Configuration Format

The mcp_servers_config expects a JSON object where each top-level key represents a unique server identifier. According to the implementation in strategies/function_calling.py (lines 91-97), the configuration string is parsed using orjson.loads() after stripping any surrounding quotes.

Each server entry must contain:

  • transport: Specifies the connection protocol. Valid values are "sse" (default) or "streamable_http".
  • url: The endpoint URL where the MCP server is accessible.
  • headers (optional): Custom HTTP headers for authentication or metadata.
  • timeout (optional): Connection timeout in seconds.
  • sse_read_timeout (optional): Specific timeout for SSE connections.

Server Entry Properties

The McpClients class in utils/mcp_client.py processes each server entry to instantiate the appropriate client type. When transport is "sse", the code creates an McpSseClient instance; for "streamable_http", it uses McpStreamableHttpClient.

Both client constructors require the url parameter. If omitted, a TypeError is raised immediately during initialization, providing early validation feedback.

Optional Wrapper Key

The configuration supports an optional wrapper key "mcpServers" at the root level. As implemented in utils/mcp_client.py (lines 32-34), the McpClients.__init__ method automatically unwraps this structure if present:

if "mcpServers" in config:
    config = config["mcpServers"]

This compatibility feature allows the plugin to accept configurations formatted for other MCP implementations while maintaining internal consistency.

Validation Mechanisms

JSON Syntax Validation

The first validation layer occurs in strategies/function_calling.py where the FunctionCallingAgentStrategy class processes the raw configuration string. The code attempts to parse the JSON using orjson.loads():

try:
    mcp_servers_config_dict = orjson.loads(mcp_servers_config.strip('"'))
except orjson.JSONDecodeError as e:
    raise ValueError(f"Invalid JSON format for mcp_servers_config: {e}")

If the string contains syntax errors, invalid escape sequences, or malformed structures, a ValueError is raised with a descriptive message indicating the specific JSON error.

Server Name Pattern Checking

After successful JSON parsing, McpClients validates each server identifier against a strict naming pattern. In utils/mcp_client.py (lines 50-53), the init_client method enforces the regex ^[a-zA-Z0-9_-]+$:

if not re.match(r'^[a-zA-Z0-9_-]+$', name):
    raise ValueError(f"Invalid server name: {name}. Only alphanumeric, underscore, and hyphen are allowed.")

This validation ensures server names are URL-safe and can be used as prefixes for generated tool names without causing identifier collisions or injection issues.

Transport and URL Verification

The final validation layer occurs during client instantiation. The code checks that the transport field contains either "sse" or "streamable_http", defaulting to "sse" if unspecified. Both concrete client implementations (McpSseClient and McpStreamableHttpClient) require the url parameter in their constructors.

If the url field is missing, Python raises a TypeError during the McpClients.init_client execution, effectively validating that all server entries contain the mandatory endpoint address before any network connection is attempted.

Practical Configuration Examples

Basic SSE Configuration

{
  "news_server": {
    "transport": "sse",
    "url": "http://127.0.0.1:8000/sse"
  }
}

Multiple Servers with Authentication

{
  "internal_api": {
    "transport": "streamable_http",
    "url": "https://api.company.com/mcp",
    "headers": {
      "Authorization": "Bearer token123",
      "X-API-Version": "v2"
    },
    "timeout": 30
  },
  "file_processor": {
    "transport": "sse",
    "url": "http://localhost:9000/sse",
    "sse_read_timeout": 60
  }
}

Using the mcpServers Wrapper

{
  "mcpServers": {
    "wrapped_server": {
      "transport": "sse",
      "url": "http://example.com/sse"
    }
  }
}

Key Implementation Files

File Role Location
strategies/function_calling.yaml Declares the mcp_servers_config parameter as a required string with default JSON example strategies/function_calling.yaml
strategies/function_calling.py Parses JSON using orjson.loads(), handles JSONDecodeError, and instantiates McpClients strategies/function_calling.py (lines 91-97)
utils/mcp_client.py Implements McpClients class, validates server names with regex ^[a-zA-Z0-9_-]+$, unwraps "mcpServers" wrapper, and manages client lifecycle utils/mcp_client.py (lines 32-34, 50-53)

Summary

  • The mcp_servers_config JSON structure defines MCP server endpoints, transport protocols, and connection parameters for the Dify MCP-SSE agent.
  • Configuration entries support two transport types: sse (default) and streamable_http, each requiring a valid url field.
  • The plugin validates configurations through four layers: JSON syntax parsing in strategies/function_calling.py, server name pattern matching against ^[a-zA-Z0-9_-]+$, transport protocol verification, and mandatory URL presence checks.
  • An optional "mcpServers" wrapper key is automatically unwrapped by McpClients for compatibility with other MCP implementations.
  • Validation errors surface as ValueError or TypeError exceptions with descriptive messages before any network connections are attempted.

Frequently Asked Questions

What is the purpose of the mcp_servers_config JSON structure?

The mcp_servers_config JSON structure serves as the configuration interface between the Dify agent and external MCP (Model-Centric Protocol) servers. It specifies connection endpoints, transport protocols (SSE or Streamable HTTP), authentication headers, and timeout settings. According to the implementation in strategies/function_calling.py, this configuration enables the FunctionCallingAgentStrategy to instantiate McpClients and automatically discover available tools, resources, and prompts from the specified servers.

How does the Dify MCP-SSE agent validate server names in the configuration?

The agent validates server names using a strict regex pattern enforced in utils/mcp_client.py (lines 50-53). Each server key in the JSON configuration must match the pattern ^[a-zA-Z0-9_-]+$, allowing only alphanumeric characters, underscores, and hyphens. If a server name contains spaces, special characters, or unicode symbols, the McpClients.init_client method raises a ValueError with a descriptive message indicating that only alphanumeric, underscore, and hyphen characters are allowed.

What transport protocols are supported by mcp_servers_config?

The configuration supports two transport protocols: sse (Server-Sent Events) and streamable_http. The transport field in each server entry accepts these string values, defaulting to "sse" if omitted. According to utils/mcp_client.py, when "sse" is specified, the code instantiates McpSseClient; for "streamable_http", it uses McpStreamableHttpClient. Both clients require a valid url parameter in their constructors, and any other transport value will either fall back to SSE or raise validation errors during client instantiation.

What happens if I wrap the configuration in an "mcpServers" key?

The plugin automatically unwraps configurations that use the "mcpServers" wrapper key for compatibility with other MCP implementations. In utils/mcp_client.py (lines 32-34), the McpClients.__init__ method checks for the presence of this key and extracts the nested configuration object if found. This means you can provide either a flat object with server names as keys or a nested structure under "mcpServers", and the validation and client initialization logic will proceed identically in both cases.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →