feat: Implement ADR-016 Smithery stateless deployment mode
Adds support for Smithery hosted deployment with stateless operation: - Add DeploymentMode enum with SELF_HOSTED and SMITHERY_STATELESS modes - Add get_deployment_mode() to detect mode from SMITHERY_DEPLOYMENT env var - Update get_client() to create per-request clients from session config - Add conditional tool registration (skip semantic search in Smithery mode) - Add conditional /app admin UI mounting (skip in Smithery mode) - Create smithery.yaml with configSchema for user credentials - Create Dockerfile.smithery for minimal stateless container - Create smithery_main.py entrypoint for Smithery deployment In Smithery mode: - Users provide nextcloud_url, username, app_password via session config - Each request creates a fresh NextcloudClient (no state between requests) - Semantic search tools are disabled (no vector database) - Admin UI (/app) is disabled (no webhooks, vector viz) All existing self-hosted functionality remains unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""Smithery-specific entrypoint for stateless deployment.
|
||||
|
||||
ADR-016: This entrypoint is used when deploying on Smithery's hosting platform.
|
||||
It configures the server for stateless operation with per-session authentication.
|
||||
|
||||
Features disabled in Smithery mode:
|
||||
- Vector sync / semantic search (no persistent storage)
|
||||
- Admin UI at /app (no webhooks, no vector viz)
|
||||
- OAuth provisioning tools (no token storage)
|
||||
|
||||
Features enabled:
|
||||
- Core Nextcloud tools (notes, calendar, contacts, files, deck, tables, cookbook)
|
||||
- Per-session app password authentication via Smithery configSchema
|
||||
- Health check endpoints (/health/live, /health/ready)
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import uvicorn
|
||||
|
||||
from nextcloud_mcp_server.config import setup_logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
"""Start the MCP server in Smithery stateless mode."""
|
||||
# Setup logging first
|
||||
setup_logging()
|
||||
|
||||
# Force stateless mode environment variables
|
||||
os.environ["SMITHERY_DEPLOYMENT"] = "true"
|
||||
os.environ["VECTOR_SYNC_ENABLED"] = "false"
|
||||
|
||||
logger.info("Starting Nextcloud MCP Server in Smithery stateless mode")
|
||||
|
||||
# Import app after setting environment variables
|
||||
from nextcloud_mcp_server.app import get_app
|
||||
|
||||
# Create the app with streamable-http transport (required for Smithery)
|
||||
app = get_app(transport="streamable-http")
|
||||
|
||||
# Smithery sets PORT environment variable
|
||||
port = int(os.environ.get("PORT", 8081))
|
||||
|
||||
logger.info(f"Listening on port {port}")
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host="0.0.0.0",
|
||||
port=port,
|
||||
log_level="info",
|
||||
# Disable access log for cleaner output
|
||||
access_log=False,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user