Add envvar overrides for mcp app (#606)
Needed for deployed MCP servers so that the Engine can override port, host, and transport.
This commit is contained in:
parent
ab93356e7c
commit
805ad2d888
2 changed files with 89 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ Provides a clean, minimal API for building MCP servers with lazy initialization.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Literal, ParamSpec, TypeVar
|
||||
|
|
@ -210,6 +211,8 @@ class MCPApp:
|
|||
|
||||
logger.info(f"Starting {self.name} v{self.version} with {len(self._catalog)} tools")
|
||||
|
||||
host, port, transport = MCPApp._get_configuration_overrides(host, port, transport)
|
||||
|
||||
if transport in ["http", "streamable-http", "streamable"]:
|
||||
run_arcade_mcp(
|
||||
catalog=self._catalog,
|
||||
|
|
@ -232,6 +235,37 @@ class MCPApp:
|
|||
else:
|
||||
raise ServerError(f"Invalid transport: {transport}")
|
||||
|
||||
@staticmethod
|
||||
def _get_configuration_overrides(
|
||||
host: str, port: int, transport: TransportType
|
||||
) -> tuple[str, int, TransportType]:
|
||||
"""Get configuration overrides from environment variables."""
|
||||
if envvar_transport := os.getenv("ARCADE_SERVER_TRANSPORT"):
|
||||
transport = envvar_transport
|
||||
logger.debug(
|
||||
f"Using '{transport}' as transport from ARCADE_SERVER_TRANSPORT environment variable"
|
||||
)
|
||||
|
||||
# host and port are only relevant for HTTP Streamable transport
|
||||
if transport in ["http", "streamable-http", "streamable"]:
|
||||
if envvar_host := os.getenv("ARCADE_SERVER_HOST"):
|
||||
host = envvar_host
|
||||
logger.debug(f"Using '{host}' as host from ARCADE_SERVER_HOST environment variable")
|
||||
|
||||
if envvar_port := os.getenv("ARCADE_SERVER_PORT"):
|
||||
try:
|
||||
port = int(envvar_port)
|
||||
except ValueError:
|
||||
logger.warning(
|
||||
f"Invalid port: '{envvar_port}' from ARCADE_SERVER_PORT environment variable. Using default port {port}"
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
f"Using '{port}' as port from ARCADE_SERVER_PORT environment variable"
|
||||
)
|
||||
|
||||
return host, port, transport
|
||||
|
||||
|
||||
class _ToolsAPI:
|
||||
"""Unified tools API for MCPApp (build-time and runtime)."""
|
||||
|
|
|
|||
|
|
@ -179,3 +179,58 @@ class TestMCPApp:
|
|||
# Test removing a resource at runtime
|
||||
removed_resource = await mcp_app.resources.remove("file:///test.txt")
|
||||
assert removed_resource.uri == "file:///test.txt"
|
||||
|
||||
def test_get_configuration_overrides(self, monkeypatch):
|
||||
"""Test configuration overrides from environment variables."""
|
||||
# Ensure environment variables are clear at the start
|
||||
monkeypatch.delenv("ARCADE_SERVER_TRANSPORT", raising=False)
|
||||
monkeypatch.delenv("ARCADE_SERVER_HOST", raising=False)
|
||||
monkeypatch.delenv("ARCADE_SERVER_PORT", raising=False)
|
||||
|
||||
# Test default values (no environment variables)
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
assert host == "127.0.0.1"
|
||||
assert port == 8000
|
||||
assert transport == "http"
|
||||
|
||||
# Test transport override
|
||||
monkeypatch.setenv("ARCADE_SERVER_TRANSPORT", "stdio")
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
assert transport == "stdio"
|
||||
monkeypatch.delenv("ARCADE_SERVER_TRANSPORT")
|
||||
|
||||
# Test host override (only works with HTTP transport)
|
||||
monkeypatch.setenv("ARCADE_SERVER_TRANSPORT", "http")
|
||||
monkeypatch.setenv("ARCADE_SERVER_HOST", "192.168.1.1")
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
assert host == "192.168.1.1"
|
||||
assert transport == "http"
|
||||
monkeypatch.delenv("ARCADE_SERVER_HOST")
|
||||
monkeypatch.delenv("ARCADE_SERVER_TRANSPORT")
|
||||
|
||||
# Test port override (only works with HTTP transport)
|
||||
monkeypatch.setenv("ARCADE_SERVER_PORT", "9000")
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
assert port == 9000
|
||||
monkeypatch.delenv("ARCADE_SERVER_PORT")
|
||||
|
||||
# Test invalid port value
|
||||
monkeypatch.setenv("ARCADE_SERVER_TRANSPORT", "http")
|
||||
monkeypatch.setenv("ARCADE_SERVER_PORT", "invalid_port")
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
assert port == 8000 # Should keep the default value
|
||||
monkeypatch.delenv("ARCADE_SERVER_PORT")
|
||||
monkeypatch.delenv("ARCADE_SERVER_TRANSPORT")
|
||||
|
||||
# Test host/port with stdio transport
|
||||
monkeypatch.setenv("ARCADE_SERVER_TRANSPORT", "stdio")
|
||||
monkeypatch.setenv("ARCADE_SERVER_HOST", "192.168.1.1")
|
||||
monkeypatch.setenv("ARCADE_SERVER_PORT", "9000")
|
||||
host, port, transport = MCPApp._get_configuration_overrides("127.0.0.1", 8000, "http")
|
||||
# For stdio, host and port are still returned but not used by the server
|
||||
assert host == "127.0.0.1" # Host should remain unchanged for stdio transport
|
||||
assert port == 8000 # Port should remain unchanged for stdio transport
|
||||
assert transport == "stdio"
|
||||
monkeypatch.delenv("ARCADE_SERVER_HOST")
|
||||
monkeypatch.delenv("ARCADE_SERVER_PORT")
|
||||
monkeypatch.delenv("ARCADE_SERVER_TRANSPORT")
|
||||
|
|
|
|||
Loading…
Reference in a new issue