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
2 changes: 1 addition & 1 deletion docs/router_tech_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ flowchart TB
```python
import asyncio
from mcpm.router import MCPRouter
from mcpm.schema.server_config import STDIOServerConfig, SSEServerConfig
from mcpm.core.schema import STDIOServerConfig, SSEServerConfig

async def main():
# Create a router
Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pydantic import TypeAdapter
from ruamel.yaml import YAML

from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig
from mcpm.utils.config import ROUTER_SERVER_NAME
from mcpm.utils.router_server import format_server_url

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/claude_desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import Any, Dict

from mcpm.clients.base import JSONClientManager
from mcpm.schemas.server_config import ServerConfig, SSEServerConfig
from mcpm.core.schema import ServerConfig, SSEServerConfig
from mcpm.utils.router_server import format_server_url_with_proxy_headers

logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/continue_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pydantic import TypeAdapter

from mcpm.clients.base import YAMLClientManager
from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig
from mcpm.utils.router_server import format_server_url_with_proxy_headers

logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/fiveire.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pydantic import TypeAdapter

from mcpm.clients.base import JSONClientManager
from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/goose.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pydantic import TypeAdapter

from mcpm.clients.base import YAMLClientManager
from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/trae.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any, Dict

from mcpm.clients.base import JSONClientManager
from mcpm.schemas.server_config import ServerConfig
from mcpm.core.schema import ServerConfig

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/clients/managers/windsurf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import Any, Dict

from mcpm.clients.base import JSONClientManager
from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/commands/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from mcpm.clients.client_config import ClientConfigManager
from mcpm.clients.client_registry import ClientRegistry
from mcpm.commands.server_operations.common import determine_scope
from mcpm.core.schema import ServerConfig
from mcpm.profile.profile_config import ProfileConfigManager
from mcpm.schemas.server_config import ServerConfig
from mcpm.utils.display import print_client_error, print_server_config
from mcpm.utils.scope import ScopeType, format_scope

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/commands/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from rich.table import Table

from mcpm.clients.client_registry import ClientRegistry
from mcpm.core.schema import STDIOServerConfig
from mcpm.profile.profile_config import ProfileConfigManager
from mcpm.schemas.server_config import STDIOServerConfig
from mcpm.utils.config import ConfigManager

profile_config_manager = ProfileConfigManager()
Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/commands/server_operations/common.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from rich.console import Console

from mcpm.clients.client_registry import ClientRegistry
from mcpm.core.schema import ServerConfig
from mcpm.profile.profile_config import ProfileConfigManager
from mcpm.schemas.server_config import ServerConfig
from mcpm.utils.display import print_active_scope, print_no_active_scope
from mcpm.utils.scope import ScopeType, extract_from_scope, parse_server

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/commands/server_operations/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rich.prompt import Confirm, Prompt

from mcpm.commands.server_operations.common import client_add_server, determine_scope, profile_add_server
from mcpm.schemas.server_config import SSEServerConfig, STDIOServerConfig
from mcpm.core.schema import SSEServerConfig, STDIOServerConfig
from mcpm.utils.display import print_server_config
from mcpm.utils.scope import ScopeType

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/commands/server_operations/pop.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from mcpm.clients.client_config import ClientConfigManager
from mcpm.clients.client_registry import ClientRegistry
from mcpm.commands.server_operations.common import determine_target
from mcpm.core.schema import ServerConfig
from mcpm.profile.profile_config import ProfileConfigManager
from mcpm.schemas.server_config import ServerConfig
from mcpm.utils.scope import ScopeType, format_scope

console = Console()
Expand Down
84 changes: 84 additions & 0 deletions src/mcpm/core/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel


class BaseServerConfig(BaseModel):
name: str

def to_dict(self) -> Dict[str, Any]:
return self.model_dump()


class STDIOServerConfig(BaseServerConfig):
command: str
args: List[str] = []
env: Dict[str, str] = {}

def get_filtered_env_vars(self, env: Dict[str, str]) -> Dict[str, str]:
"""Get filtered environment variables with empty values removed

This is a utility for clients to filter out empty environment
variables, regardless of client-specific formatting.

Args:
env: Dictionary of environment variables to use for resolving
${VAR_NAME} references.

Returns:
Dictionary of non-empty environment variables
"""
if not self.env:
return {}

# Use provided environment without falling back to os.environ
environment = env

# Keep all environment variables, including empty strings
filtered_env = {}
for key, value in self.env.items():
# For environment variable references like ${VAR_NAME}, check if the variable exists
# and has a non-empty value. If it doesn't exist or is empty, exclude it.
if value is not None and isinstance(value, str):
if value.startswith("${") and value.endswith("}"):
# Extract the variable name from ${VAR_NAME}
env_var_name = value[2:-1]
env_value = environment.get(env_var_name, "")
# Include all values, even empty ones
filtered_env[key] = env_value
else:
# Include all values, even empty ones
filtered_env[key] = value

return filtered_env


class SSEServerConfig(BaseServerConfig):
url: str
headers: Dict[str, Any] = {}

def to_mcp_proxy_stdio(self) -> STDIOServerConfig:
proxy_args = [
"mcp-proxy",
self.url,
]
if self.headers:
proxy_args.append("--headers")
for key, value in self.headers.items():
proxy_args.append(f"{key}")
proxy_args.append(f"{value}")

return STDIOServerConfig(
name=self.name,
command="uvx",
args=proxy_args,
)


ServerConfig = Union[STDIOServerConfig, SSEServerConfig]


class Profile(BaseModel):
name: str
api_key: Optional[str]
servers: list[ServerConfig]
2 changes: 1 addition & 1 deletion src/mcpm/profile/profile_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import TypeAdapter

from mcpm.schemas.server_config import ServerConfig
from mcpm.core.schema import ServerConfig

DEFAULT_PROFILE_PATH = os.path.expanduser("~/.config/mcpm/profiles.json")

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/router/client_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mcp import ClientSession, InitializeResult, StdioServerParameters, stdio_client
from mcp.client.sse import sse_client

from mcpm.schemas.server_config import ServerConfig, SSEServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, SSEServerConfig, STDIOServerConfig

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/router/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
from starlette.routing import Mount, Route
from starlette.types import AppType, Lifespan

from mcpm.core.schema import ServerConfig
from mcpm.monitor.base import AccessEventType
from mcpm.monitor.event import trace_event
from mcpm.profile.profile_config import ProfileConfigManager
from mcpm.schemas.server_config import ServerConfig
from mcpm.utils.config import PROMPT_SPLITOR, RESOURCE_SPLITOR, RESOURCE_TEMPLATE_SPLITOR, TOOL_SPLITOR
from mcpm.utils.errlog_manager import ServerErrorLogManager

Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/schemas/full_server_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel, Field, model_validator

from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig


class FullServerConfig(BaseModel):
Expand Down
79 changes: 4 additions & 75 deletions src/mcpm/schemas/server_config.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,7 @@
from typing import Any, Dict, List, Union
import warnings

from pydantic import BaseModel
from mcpm.core.schema import ServerConfig, SSEServerConfig, STDIOServerConfig

__all__ = ["ServerConfig", "SSEServerConfig", "STDIOServerConfig"]

class BaseServerConfig(BaseModel):
name: str

def to_dict(self) -> Dict[str, Any]:
return self.model_dump()


class STDIOServerConfig(BaseServerConfig):
command: str
args: List[str] = []
env: Dict[str, str] = {}

def get_filtered_env_vars(self, env: Dict[str, str]) -> Dict[str, str]:
"""Get filtered environment variables with empty values removed

This is a utility for clients to filter out empty environment
variables, regardless of client-specific formatting.

Args:
env: Dictionary of environment variables to use for resolving
${VAR_NAME} references.

Returns:
Dictionary of non-empty environment variables
"""
if not self.env:
return {}

# Use provided environment without falling back to os.environ
environment = env

# Keep all environment variables, including empty strings
filtered_env = {}
for key, value in self.env.items():
# For environment variable references like ${VAR_NAME}, check if the variable exists
# and has a non-empty value. If it doesn't exist or is empty, exclude it.
if value is not None and isinstance(value, str):
if value.startswith("${") and value.endswith("}"):
# Extract the variable name from ${VAR_NAME}
env_var_name = value[2:-1]
env_value = environment.get(env_var_name, "")
# Include all values, even empty ones
filtered_env[key] = env_value
else:
# Include all values, even empty ones
filtered_env[key] = value

return filtered_env


class SSEServerConfig(BaseServerConfig):
url: str
headers: Dict[str, Any] = {}

def to_mcp_proxy_stdio(self) -> STDIOServerConfig:
proxy_args = [
"mcp-proxy",
self.url,
]
if self.headers:
proxy_args.append("--headers")
for key, value in self.headers.items():
proxy_args.append(f"{key}")
proxy_args.append(f"{value}")

return STDIOServerConfig(
name=self.name,
command="uvx",
args=proxy_args,
)


ServerConfig = Union[STDIOServerConfig, SSEServerConfig]
warnings.warn("mcpm.schemas.server_config is deprecated, use mcpm.core.schema instead", DeprecationWarning)
2 changes: 1 addition & 1 deletion src/mcpm/utils/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from rich.markup import escape
from rich.table import Table

from mcpm.schemas.server_config import ServerConfig, SSEServerConfig
from mcpm.core.schema import ServerConfig, SSEServerConfig
from mcpm.utils.scope import CLIENT_PREFIX, PROFILE_PREFIX

console = Console()
Expand Down
2 changes: 1 addition & 1 deletion src/mcpm/utils/router_server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from mcpm.clients.base import ROUTER_SERVER_NAME
from mcpm.schemas.server_config import ServerConfig, SSEServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, SSEServerConfig, STDIOServerConfig


def format_server_url(client: str, profile: str, router_url: str) -> ServerConfig:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from mcpm.clients.client_registry import ClientRegistry
from mcpm.commands.server_operations.add import add
from mcpm.schemas.server_config import SSEServerConfig
from mcpm.core.schema import SSEServerConfig
from mcpm.utils.repository import RepositoryManager


Expand Down
2 changes: 1 addition & 1 deletion tests/test_windsurf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import pytest

from mcpm.clients.managers.windsurf import WindsurfManager
from mcpm.schemas.server_config import ServerConfig, STDIOServerConfig
from mcpm.core.schema import ServerConfig, STDIOServerConfig
from mcpm.utils.config import ConfigManager


Expand Down