Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions backend/mcp/env-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Environment Variable Demo MCP Server

This MCP server demonstrates the environment variable passing capability added to Atlas UI 3. It shows how to configure and use environment variables for MCP servers through the `mcp.json` configuration file.

## Purpose

This server provides tools to:
- Retrieve specific environment variables
- List all configured environment variables
- Demonstrate practical usage patterns for environment variables

## Configuration

The server is configured in `config/overrides/mcp.json` (or `config/defaults/mcp.json`) with the `env` field:

```json
{
"env-demo": {
"command": ["python", "mcp/env-demo/main.py"],
"cwd": "backend",
"env": {
"CLOUD_PROFILE": "demo-profile",
"CLOUD_REGION": "us-west-2",
"DEBUG_MODE": "true",
"ENVIRONMENT": "development",
"API_KEY": "${DEMO_API_KEY}"
},
"groups": ["users"],
"description": "Demonstrates environment variable passing to MCP servers",
"compliance_level": "Public"
}
}
```

## Environment Variable Features

### Literal Values
Set environment variables with literal string values:
```json
"env": {
"CLOUD_REGION": "us-west-2",
"DEBUG_MODE": "true"
}
```

### Variable Substitution
Reference system environment variables using `${VAR_NAME}` syntax:
```json
"env": {
"API_KEY": "${DEMO_API_KEY}"
}
```

Before starting Atlas UI, set the system environment variable:
```bash
export DEMO_API_KEY="your-secret-key"
```

## Available Tools

### 1. `get_env_var`
Retrieves the value of a specific environment variable.

**Input:**
- `var_name` (string): Name of the environment variable

**Example Usage:**
```
Get the value of CLOUD_REGION
```

### 2. `list_configured_env_vars`
Lists all configured environment variables that are commonly expected.

**Example Usage:**
```
Show me the configured environment variables
```

### 3. `demonstrate_env_usage`
Shows practical examples of using environment variables.

**Input:**
- `operation` (string): Type of demonstration
- `"info"`: General information about env var configuration
- `"config"`: Demonstrates configuration usage (profile, region)
- `"credentials"`: Demonstrates secure credential handling

**Example Usage:**
```
Demonstrate how to use environment variables for configuration
```

## Use Cases

### Cloud Configuration
```json
"env": {
"CLOUD_PROFILE": "production-profile",
"CLOUD_REGION": "us-east-1",
"AVAILABILITY_ZONE": "us-east-1a"
}
```

### API Credentials
```json
"env": {
"API_KEY": "${MY_SERVICE_API_KEY}",
"API_ENDPOINT": "https://api.example.com"
}
```

### Feature Flags
```json
"env": {
"DEBUG_MODE": "false",
"ENABLE_CACHING": "true",
"MAX_RETRIES": "3"
}
```

## Security Best Practices

1. **Never commit secrets**: Use `${VAR_NAME}` substitution for sensitive values
2. **Set system env vars**: Configure sensitive values at the system level
3. **Use appropriate compliance levels**: Mark servers with sensitive access appropriately
4. **Document required variables**: Clearly document which env vars are needed

## Testing

To test this server:

1. Set any optional environment variables:
```bash
export DEMO_API_KEY="test-key-123"
```

2. Start Atlas UI (the server will automatically load with the configured env vars)

3. In the chat interface, try:
```
List all configured environment variables for the env-demo server
```

```
Get the value of CLOUD_REGION
```

```
Demonstrate how environment variables are used for credentials
```

## Notes

- Environment variables are only passed to stdio servers (not HTTP/SSE servers)
- If a `${VAR_NAME}` reference cannot be resolved, server initialization will fail with a clear error message
- Empty `env: {}` is valid and will set no environment variables
- The `env` field is optional; servers work without it as before
199 changes: 199 additions & 0 deletions backend/mcp/env-demo/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#!/usr/bin/env python3
"""
Environment Variable Demo MCP Server using FastMCP

This server demonstrates the environment variable passing capability.
It reads environment variables that are configured in mcp.json and
exposes them through MCP tools.
"""

import os
import time
from typing import Any, Dict

from fastmcp import FastMCP

# Initialize the MCP server
mcp = FastMCP("Environment Variable Demo")


@mcp.tool
def get_env_var(var_name: str) -> Dict[str, Any]:
"""Get the value of a specific environment variable.

This tool demonstrates how environment variables configured in mcp.json
are passed to the MCP server process.

Args:
var_name: Name of the environment variable to retrieve

Returns:
MCP contract shape with the environment variable value:
{
"results": {
"var_name": str,
"var_value": str or None,
"is_set": bool
},
"meta_data": {
"elapsed_ms": float
}
}
"""
start = time.perf_counter()

var_value = os.environ.get(var_name)
is_set = var_name in os.environ

elapsed_ms = round((time.perf_counter() - start) * 1000, 3)

return {
"results": {
"var_name": var_name,
"var_value": var_value,
"is_set": is_set
},
"meta_data": {
"elapsed_ms": elapsed_ms
}
}


@mcp.tool
def list_configured_env_vars() -> Dict[str, Any]:
"""List all environment variables that were configured in mcp.json.

This tool shows which environment variables from the mcp.json configuration
are available to this server. It returns commonly expected configuration
variables that might be set.

Returns:
MCP contract shape with environment variables:
{
"results": {
"configured_vars": dict of var_name -> var_value,
"total_count": int
},
"meta_data": {
"elapsed_ms": float
}
}
"""
start = time.perf_counter()

# List of common configuration environment variables
# This demonstrates what might be passed from mcp.json
common_config_vars = [
"CLOUD_PROFILE",
"CLOUD_REGION",
"API_KEY",
"DEBUG_MODE",
"MAX_RETRIES",
"TIMEOUT_SECONDS",
"ENVIRONMENT",
"SERVICE_URL"
]

configured_vars = {}
for var_name in common_config_vars:
if var_name in os.environ:
configured_vars[var_name] = os.environ[var_name]

elapsed_ms = round((time.perf_counter() - start) * 1000, 3)

return {
"results": {
"configured_vars": configured_vars,
"total_count": len(configured_vars)
},
"meta_data": {
"elapsed_ms": elapsed_ms
}
}


@mcp.tool
def demonstrate_env_usage(operation: str = "info") -> Dict[str, Any]:
"""Demonstrate how environment variables can be used in MCP server operations.

This tool shows practical examples of using environment variables for:
- Configuration (e.g., region, profile)
- Feature flags (e.g., debug mode)
- API credentials (e.g., API keys)

Args:
operation: Type of demonstration ("info", "config", "credentials")

Returns:
MCP contract shape with demonstration results:
{
"results": {
"operation": str,
"example": str,
"details": dict
},
"meta_data": {
"elapsed_ms": float
}
}
"""
start = time.perf_counter()

if operation == "config":
# Demonstrate configuration from environment
cloud_profile = os.environ.get("CLOUD_PROFILE", "default")
cloud_region = os.environ.get("CLOUD_REGION", "us-east-1")

example = f"Using cloud profile '{cloud_profile}' in region '{cloud_region}'"
details = {
"profile": cloud_profile,
"region": cloud_region,
"source": "environment variables from mcp.json"
}

elif operation == "credentials":
# Demonstrate secure credential handling
api_key = os.environ.get("API_KEY")
has_key = api_key is not None

example = f"API key is {'configured' if has_key else 'not configured'}"
details = {
"has_api_key": has_key,
"key_length": len(api_key) if api_key else 0,
"masked_key": f"{api_key[:4]}...{api_key[-4:]}" if api_key and len(api_key) > 8 else None,
"source": "environment variable ${API_KEY} from mcp.json"
}

else: # info
example = "Environment variables can be configured in mcp.json"
details = {
"usage": "Set env dict in mcp.json server configuration",
"syntax": {
"literal": "KEY: 'literal-value'",
"substitution": "KEY: '${SYSTEM_ENV_VAR}'"
},
"example_config": {
"env": {
"CLOUD_PROFILE": "my-profile-9",
"CLOUD_REGION": "us-east-7",
"API_KEY": "${MY_API_KEY}"
}
}
}

elapsed_ms = round((time.perf_counter() - start) * 1000, 3)

return {
"results": {
"operation": operation,
"example": example,
"details": details
},
"meta_data": {
"elapsed_ms": elapsed_ms
}
}


if __name__ == "__main__":
mcp.run()
1 change: 1 addition & 0 deletions backend/modules/config/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class MCPServerConfig(BaseModel):
enabled: bool = True
command: Optional[List[str]] = None # Command to run server (for stdio servers)
cwd: Optional[str] = None # Working directory for command
env: Optional[Dict[str, str]] = None # Environment variables for stdio servers
url: Optional[str] = None # URL for HTTP servers
type: str = "stdio" # Server type: "stdio" or "http" (deprecated, use transport)
transport: Optional[str] = None # Explicit transport: "stdio", "http", "sse" - takes priority over auto-detection
Expand Down
Loading
Loading