Skip to main content

Examples

Below are practical examples for composing and proxying MCP servers. Use them as templates for your own configurations.


Repository Examples

The repository includes complete, runnable examples in the examples/ directory. Each example includes a Makefile for easy setup and execution.

Transport Examples

ExampleDescription
proxy-stdioSTDIO transport where the agent spawns MCP Compose as a subprocess. The simplest setup for local development with Claude Desktop or VS Code.
proxy-streamable-httpModern Streamable HTTP transport (recommended). MCP Compose runs as an HTTP server that clients connect to over the network.
proxy-sseServer-Sent Events transport (deprecated). Maintained for backward compatibility with older clients. Use Streamable HTTP for new projects.
embedded-streamable-httpEmbedded servers running in-process with the composer. Most efficient approach when servers are Python modules—no subprocess overhead.

Authentication Examples

ExampleDescription
anaconda-tokenAnaconda token authentication at the composer level. Demonstrates protecting your MCP Compose endpoint with Anaconda.org API tokens.
github-oauthGitHub OAuth2 authentication using the generic OAuth2 provider. Validates tokens via the GitHub API userinfo endpoint for enterprise SSO integration.

Observability & UI Examples

ExampleDescription
otelOpenTelemetry instrumentation with Logfire integration. Demonstrates distributed tracing for debugging and performance monitoring.
uiWeb UI dashboard with basic authentication. Includes a React-based management interface for testing tools, viewing logs, and managing servers.

Running the Examples

Each example follows the same pattern:

# Navigate to the example directory
cd examples/proxy-streamable-http

# Install dependencies
make install

# Start the MCP Compose server
make serve

# In another terminal, run the example agent
make agent

See the README in each example directory for detailed instructions.


Quick Start Examples

These examples illustrate common configuration patterns to help you get started quickly.

Local Development with Multiple STDIO Servers

The simplest setup: compose multiple local MCP servers for development. No authentication, STDIO transport for easy debugging with Claude Desktop or VS Code.

[composer]
name = "dev-tools"
conflict_resolution = "prefix"
log_level = "DEBUG"

[transport]
stdio_enabled = true

[[servers.proxied.stdio]]
name = "filesystem"
command = ["uvx", "mcp-server-filesystem", "./workspace"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

[[servers.proxied.stdio]]
name = "git"
command = ["uvx", "mcp-server-git"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

[[servers.proxied.stdio]]
name = "sqlite"
command = ["uvx", "mcp-server-sqlite", "--db-path", "./data.db"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

This configuration composes three popular MCP servers into one. The prefix strategy ensures tools like filesystem_read_file and git_status are clearly distinguished. Setting log_level = "DEBUG" helps troubleshoot tool discovery issues during development.

Anaconda Token Authentication at Composer Level

Protect your MCP Compose endpoint with Anaconda authentication. Clients must provide a valid Anaconda bearer token to access any of the composed servers. Authentication happens at the composer level—the downstream servers don't need authentication logic.

[composer]
name = "anaconda-compose"
conflict_resolution = "prefix"
log_level = "INFO"

[authentication]
enabled = true
providers = ["anaconda"]
default_provider = "anaconda"

[authentication.anaconda]
domain = "anaconda.com"

[[servers.proxied.stdio]]
name = "calculator"
command = ["python", "mcp1.py"]
restart_policy = "never"

[[servers.proxied.stdio]]
name = "filesystem"
command = ["uvx", "mcp-server-filesystem", "./data"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

This configuration enables Anaconda authentication at the MCP Compose level. Clients connecting to this endpoint must include a valid Anaconda token in the Authorization header. The composer validates tokens using the Anaconda API—no ANACONDA_API_KEY is required on the server side.

Clients authenticate by including their Anaconda token:

# Using curl
curl -H "Authorization: Bearer <your_anaconda_token>" http://localhost:8080/mcp

# Or configure in your MCP client

See the anaconda-token example for a complete runnable setup.

Team Server with HTTP Transport and API Key Protection

A shared MCP Compose instance that multiple team members can connect to over the network, protected by API keys.

[composer]
name = "team-mcp-server"
conflict_resolution = "prefix"
log_level = "INFO"
port = 8080

[transport]
stdio_enabled = false
streamable_http_enabled = true
streamable_http_path = "/mcp"
streamable_http_cors_enabled = true

[authentication]
enabled = true
providers = ["api_key"]
default_provider = "api_key"

[authentication.api_key]
header_name = "X-API-Key"
keys = ["${TEAM_API_KEY_ALICE}", "${TEAM_API_KEY_BOB}", "${TEAM_API_KEY_SHARED}"]

[[servers.proxied.stdio]]
name = "docs"
command = ["python", "-m", "docs_mcp_server"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

[[servers.proxied.stdio]]
name = "jira"
command = ["uvx", "mcp-server-jira"]
env = { JIRA_API_TOKEN = "${JIRA_API_TOKEN}", JIRA_URL = "${JIRA_URL}" }
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

This configuration runs MCP Compose as an HTTP server on port 8080. Team members connect from their MCP clients using the Streamable HTTP URL (http://server:8080/mcp) and must include a valid API key in the X-API-Key header. Each team member can have their own key for auditing, or share a common key for simplicity.

Start the server:

export TEAM_API_KEY_ALICE="alice-secret-key"
export TEAM_API_KEY_BOB="bob-secret-key"
export JIRA_API_TOKEN="jira-token"
export JIRA_URL="https://yourcompany.atlassian.net"

mcp-compose serve --config mcp_compose.toml

Team members configure their MCP client to connect:

{
"mcpServers": {
"team-tools": {
"url": "http://mcp-server.internal:8080/mcp",
"headers": {
"X-API-Key": "alice-secret-key"
}
}
}
}

Server Transport Examples

STDIO Server

[[servers.proxied.stdio]]
name = "filesystem"
command = ["uvx", "mcp-server-filesystem", "./data"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"

Streamable HTTP Server

[[servers.proxied.http]]
name = "remote-server"
url = "http://localhost:8080/mcp"
protocol = "lines"
auth_token = "${REMOTE_SERVER_TOKEN}"
auth_type = "bearer"
timeout = 30
reconnect_on_failure = true

SSE Server (Deprecated)

warning

SSE transport is deprecated. Use Streamable HTTP instead.

[[servers.proxied.sse]]
name = "legacy-sse"
url = "http://localhost:8080/sse"
auth_token = "${SSE_TOKEN}"
timeout = 30
reconnect_on_failure = true

Complete Production Example

Here's a complete configuration example combining multiple features for production deployment:

# ============================================================================
# Composer Settings
# ============================================================================
[composer]
name = "production-composer"
conflict_resolution = "prefix"
log_level = "INFO"
port = 8080

# ============================================================================
# Transport Configuration
# ============================================================================
[transport]
stdio_enabled = false
streamable_http_enabled = true
streamable_http_path = "/mcp"
streamable_http_cors_enabled = true

# ============================================================================
# Authentication
# ============================================================================
[authentication]
enabled = true
providers = ["jwt"]
default_provider = "jwt"

[authentication.jwt]
secret = "${JWT_SECRET}"
algorithm = "HS256"
issuer = "mcp-compose"

# ============================================================================
# Servers
# ============================================================================
[[servers.proxied.stdio]]
name = "filesystem"
command = ["python", "-m", "mcp_server_filesystem", "./data"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"
restart_policy = "on-failure"
max_restarts = 3

[[servers.proxied.stdio]]
name = "database"
command = ["python", "db_server.py"]
working_dir = "${MCP_COMPOSE_CONFIG_DIR}"
env = { DATABASE_URL = "${DATABASE_URL}" }
health_check_enabled = true
health_check_interval = 30

[[servers.proxied.http]]
name = "remote-api"
url = "https://api.example.com/mcp"
auth_token = "${API_TOKEN}"
timeout = 60
reconnect_on_failure = true

# ============================================================================
# Monitoring
# ============================================================================
[monitoring]
enabled = true

[monitoring.metrics]
enabled = true
provider = "prometheus"
endpoint = "/metrics"

[monitoring.logging]
level = "INFO"
format = "json"
output = "stdout"

[monitoring.health]
endpoint = "/health"

Docker Deployment

Run MCP Compose in a container:

docker-compose up -d

Then access:

  • http://localhost:8000 - Web UI
  • http://localhost:8000/api/v1 - REST API