SurfSense/surfsense_mcp/mcp_server/__main__.py
CREDO23 116291a3b6 refactor(mcp): flatten to mcp_server package, drop src layout
Rename the import package surfsense_mcp -> mcp_server and remove the
src/ layer so the project mirrors the backend's shape (project folder
!= package name, e.g. surfsense_backend/app). Kills the redundant
surfsense_mcp/src/surfsense_mcp nesting.

Distribution name and console command (surfsense-mcp) are unchanged;
only python -m and internal import paths move to mcp_server. Dockerfile
CMD updated; no PYTHONPATH added since the editable install already
makes the package importable.
2026-07-07 20:24:53 +02:00

58 lines
1.7 KiB
Python

"""Entry point: load settings from the environment and run the MCP server.
Two transports share one build:
- ``stdio`` (default): Cursor/Claude launch one process per user; the key comes
from the environment, so it is required here.
- ``streamable-http``: one process serves many users, each passing their own key
per request; the key is enforced by the transport's auth middleware instead.
For stdio, stdout is the protocol channel, so every log line goes to stderr.
"""
from __future__ import annotations
import logging
import os
import sys
from mcp.server.fastmcp import FastMCP
from .config import Settings
from .server import build_server
def main() -> None:
logging.basicConfig(
level=logging.INFO,
stream=sys.stderr,
format="%(levelname)s %(name)s: %(message)s",
)
settings = Settings.from_env()
transport = os.environ.get("SURFSENSE_MCP_TRANSPORT", "stdio").strip() or "stdio"
mcp, _client = build_server(settings)
if transport in ("streamable-http", "http"):
_run_http(mcp, settings)
return
if transport == "stdio" and not settings.api_key:
raise SystemExit(
"SURFSENSE_API_KEY is required for stdio transport. Create an API "
"key in SurfSense (Settings -> API) and pass it via the "
"SURFSENSE_API_KEY environment variable."
)
mcp.run(transport=transport)
def _run_http(mcp: FastMCP, settings: Settings) -> None:
"""Serve the streamable-http app directly, so the per-request identity
middleware wraps the SDK's MCP endpoint."""
import uvicorn
from .core.transport import build_http_app
uvicorn.run(build_http_app(mcp), host=settings.host, port=settings.port)
if __name__ == "__main__":
main()