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

> Learn the purpose of mcp_servers_config in Dify MCP-SSE Agent. Understand its JSON structure and validation methods for secure server connections.

- Repository: [Junjie.M/dify-plugin-agent-mcp_sse](https://github.com/junjiem/dify-plugin-agent-mcp_sse)
- Tags: how-to-guide
- Published: 2026-03-05

---

**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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py) (lines 32-34), the `McpClients.__init__` method automatically unwraps this structure if present:

```python
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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.py) where the `FunctionCallingAgentStrategy` class processes the raw configuration string. The code attempts to parse the JSON using `orjson.loads()`:

```python
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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py) (lines 50-53), the `init_client` method enforces the regex `^[a-zA-Z0-9_-]+$`:

```python
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

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

```

### Multiple Servers with Authentication

```json
{
  "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

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

```

## Key Implementation Files

| File | Role | Location |
|------|------|----------|
| [`strategies/function_calling.yaml`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.yaml) | Declares the `mcp_servers_config` parameter as a required string with default JSON example | [`strategies/function_calling.yaml`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.yaml) |
| [`strategies/function_calling.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.py) | Parses JSON using `orjson.loads()`, handles `JSONDecodeError`, and instantiates `McpClients` | [`strategies/function_calling.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.py) (lines 91-97) |
| [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/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.