fix(smithery): Use container runtime pattern for config discovery

ADR-016: For container runtime deployment, Smithery does not auto-generate
the .well-known/mcp-config endpoint like it does for Python CLI runtime.

Changes:
- Remove [tool.smithery] from pyproject.toml (not used in container mode)
- Remove smithery_server.py (Python CLI runtime specific)
- Add .well-known/mcp-config endpoint to return JSON Schema config
- Add SmitheryConfigMiddleware to extract config from URL query params
- Use ContextVar to pass session config to tool handlers

The container runtime passes config as URL query parameters to /mcp:
  GET /mcp?nextcloud_url=...&username=...&app_password=...

Tested:
- All 164 unit tests passing
- Docker container builds successfully
- .well-known/mcp-config returns valid JSON Schema
- Health endpoints working

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2025-11-22 18:22:55 +01:00
co-authored by Claude
parent b8dc413b73
commit 706a15f0bc
6 changed files with 142 additions and 101 deletions
+13 -14
View File
@@ -108,13 +108,16 @@ def _get_client_from_session_config(ctx: Context) -> NextcloudClient:
with the user's Nextcloud credentials. This function creates a fresh client
for each request - no state is persisted between requests.
For container runtime, config is extracted from URL query parameters by
SmitheryConfigMiddleware and stored in a context variable.
Expected session config fields (from Smithery configSchema):
- nextcloud_url: str - Nextcloud instance URL (required)
- username: str - Nextcloud username (required)
- app_password: str - Nextcloud app password (required)
Args:
ctx: MCP request context containing session_config
ctx: MCP request context (not used directly for Smithery config)
Returns:
NextcloudClient configured with session credentials
@@ -122,25 +125,21 @@ def _get_client_from_session_config(ctx: Context) -> NextcloudClient:
Raises:
ValueError: If required session config fields are missing
"""
# Access session config from context
# In Smithery mode, this is populated from URL parameters
session_config = getattr(ctx, "session_config", None)
# ADR-016: Get session config from context variable (set by SmitheryConfigMiddleware)
from nextcloud_mcp_server.app import get_smithery_session_config
session_config = get_smithery_session_config()
if session_config is None:
raise ValueError(
"Session configuration required in Smithery mode. "
"Ensure nextcloud_url, username, and app_password are provided."
"Ensure nextcloud_url, username, and app_password are provided as URL query parameters."
)
# Extract required fields - support both dict and object access
if isinstance(session_config, dict):
nextcloud_url = session_config.get("nextcloud_url")
username = session_config.get("username")
app_password = session_config.get("app_password")
else:
nextcloud_url = getattr(session_config, "nextcloud_url", None)
username = getattr(session_config, "username", None)
app_password = getattr(session_config, "app_password", None)
# Extract required fields - config is always a dict from SmitheryConfigMiddleware
nextcloud_url = session_config.get("nextcloud_url")
username = session_config.get("username")
app_password = session_config.get("app_password")
# Validate required fields
missing_fields = []