Extension MCP Integration
This guide explains how extensions can provide MCP server configurations and how they integrate with workspace MCP configurations.
Overviewβ
Extensions can include MCP server configurations that are automatically loaded and merged with workspace MCP configurations. This allows extensions to provide pre-configured MCP servers that users can use immediately.
Configuration Precedenceβ
MCP server configurations are loaded in the following order (precedence from highest to lowest):
- Workspace MCP Config (
.radium/mcp-servers.toml) - Highest Precedence - Extension MCP Configs (from installed extensions) - Lower Precedence
Precedence Rulesβ
- Workspace configs take precedence: If a server with the same name exists in both workspace and extension configs, the workspace configuration is used.
- Extension configs are additive: Extension servers that don't conflict with workspace servers are added to the server list.
- No overwriting: Extension configs cannot overwrite workspace configs, even if the extension is installed after workspace configuration.
Extension MCP Config Formatβ
Extension MCP configurations can be provided in two formats:
Format 1: JSON (Extension Format)β
Place JSON files in the extension's mcp/ directory:
my-extension/
βββ manifest.toml
βββ mcp/
βββ database-server.json
Example JSON format:
{
"name": "database-server",
"transport": "stdio",
"command": "mcp-postgres",
"args": ["postgresql://localhost/mydb"]
}
Format 2: TOML (Workspace Format)β
Extensions can also use TOML format (same as workspace configs):
my-extension/
βββ manifest.toml
βββ mcp/
βββ servers.toml
Example TOML format:
[[servers]]
name = "database-server"
transport = "stdio"
command = "mcp-postgres"
args = ["postgresql://localhost/mydb"]
Configuration Fieldsβ
Required Fieldsβ
name: Unique server identifier (string)transport: Transport type -"stdio","sse", or"http"(string)
Transport-Specific Fieldsβ
For stdio transport:
command: Command to execute (required)args: Optional array of command arguments
For SSE/HTTP transport:
url: Server URL (required)
Optional Fieldsβ
auth: Authentication configuration (see Authentication Guide)
Examplesβ
Example 1: Simple Stdio Serverβ
Extension structure:
my-extension/
βββ manifest.toml
βββ mcp/
βββ filesystem-server.json
mcp/filesystem-server.json:
{
"name": "extension-filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
Example 2: Remote HTTP Serverβ
mcp/api-server.json:
{
"name": "extension-api",
"transport": "http",
"url": "https://api.example.com/mcp"
}
Example 3: Multiple Servers (TOML)β
mcp/servers.toml:
[[servers]]
name = "extension-db"
transport = "stdio"
command = "mcp-postgres"
args = ["postgresql://localhost/extdb"]
[[servers]]
name = "extension-api"
transport = "http"
url = "https://api.example.com/mcp"
Precedence Examplesβ
Example 1: No Conflictβ
Workspace config:
[[servers]]
name = "workspace-server"
transport = "stdio"
command = "mcp-workspace"
Extension config:
{
"name": "extension-server",
"transport": "stdio",
"command": "mcp-extension"
}
Result: Both servers are loaded (no conflict).
Example 2: Name Conflictβ
Workspace config:
[[servers]]
name = "database-server"
transport = "stdio"
command = "mcp-postgres-workspace"
Extension config:
{
"name": "database-server",
"transport": "stdio",
"command": "mcp-postgres-extension"
}
Result: Only workspace server is loaded (workspace takes precedence).
Example 3: Multiple Extensionsβ
Extension A config:
{ "name": "server-a", "transport": "stdio", "command": "mcp-a" }
Extension B config:
{ "name": "server-b", "transport": "stdio", "command": "mcp-b" }
Result: Both servers are loaded (no conflicts).
User Overrideβ
Users can override extension MCP configs by adding a server with the same name to their workspace config:
Extension provides:
{
"name": "extension-server",
"transport": "stdio",
"command": "mcp-default"
}
User workspace config:
[[servers]]
name = "extension-server"
transport = "stdio"
command = "mcp-custom"
args = ["--custom", "config"]
Result: User's custom configuration is used instead of extension default.
Best Practices for Extension Developersβ
1. Use Descriptive Namesβ
Use namespaced server names to avoid conflicts:
{
"name": "my-extension-database",
"transport": "stdio",
"command": "mcp-postgres"
}
2. Provide Sensible Defaultsβ
Configure servers with reasonable defaults that work out of the box:
{
"name": "my-extension-files",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "${HOME}/Documents"]
}
3. Document Requirementsβ
Document any requirements in your extension's README:
- Required system dependencies
- Required environment variables
- Required permissions
- Network requirements
4. Handle Missing Dependenciesβ
Design your MCP server configs to fail gracefully if dependencies are missing:
- Use
npxfor npm-based servers (auto-installs) - Provide clear error messages
- Document installation steps
5. Avoid Authentication in Extensionsβ
Don't include OAuth credentials in extension configs:
- Users should configure authentication themselves
- Credentials are sensitive and user-specific
- Use placeholder or documentation instead
Instead, document authentication:
{
"name": "my-extension-api",
"transport": "http",
"url": "https://api.example.com/mcp"
// Note: Users must configure OAuth authentication
// See extension README for setup instructions
}
Troubleshooting Extension MCP Configsβ
Server Not Loadingβ
Check:
- Extension is installed and discovered
- MCP config file is in
mcp/directory - Config file format is valid (JSON or TOML)
- Server name doesn't conflict with workspace config
- Required fields are present
Server Overridden by Workspaceβ
Problem: Extension server not appearing
Solution: This is expected behavior - workspace configs take precedence. Users can:
- Remove conflicting workspace server
- Rename extension server in workspace config
- Use different server name in extension
Invalid Config Formatβ
Problem: Extension MCP config not parsed
Solutions:
- Verify JSON/TOML syntax is valid
- Check required fields are present
- Verify transport-specific fields (command for stdio, url for HTTP/SSE)
- Check file encoding (should be UTF-8)
Integration Detailsβ
Loading Processβ
- Workspace configs loaded first:
.radium/mcp-servers.tomlis loaded - Extension configs discovered: All extensions are scanned for
mcp/directory - Extension configs parsed: Each config file is parsed (JSON or TOML)
- Conflict resolution: Extension servers with conflicting names are skipped
- Servers connected: All non-conflicting servers are connected
File Discoveryβ
Extension MCP configs are discovered from:
- Project-level extensions:
.radium/extensions/{extension-name}/mcp/ - User-level extensions:
~/.radium/extensions/{extension-name}/mcp/
All .json and .toml files in the mcp/ directory are loaded.
Error Handlingβ
- Invalid configs are skipped: If an extension config is invalid, it's skipped with a warning
- Partial failures don't block: If some extension servers fail to connect, others still work
- Errors are logged: Check logs for detailed error messages
Related Documentationβ
- MCP User Guide - User-facing MCP documentation
- MCP Configuration - Configuration reference
- Creating Extensions - How to create extensions
- Extension Architecture - Extension system overview
Examplesβ
See the examples directory for complete extension examples with MCP integration.