feat: add streaming to markdown, fix raycast mcps exposing

This commit is contained in:
hh
2026-05-21 13:52:48 +02:00
parent 7fc0c9c0b1
commit 11f061070f
6 changed files with 557 additions and 99 deletions
+15 -13
View File
@@ -48,8 +48,8 @@ ALL_NAMESPACE = "all"
def build_internal_app(
mcps: Iterable[McpServerT], *, host: str, port: int
) -> tuple[Starlette, dict[str, str]]:
"""Build the aggregator ``Starlette`` app and the per-namespace URL map.
) -> tuple[Starlette, dict[str, str], dict[str, FastMCP]]:
"""Build the aggregator ``Starlette`` app, per-namespace URL map, and server map.
``host``/``port`` only flavour the URL strings handed back — actually
listening on them is the caller's job (``cli.main`` runs a uvicorn
@@ -57,21 +57,23 @@ def build_internal_app(
have to format the URLs themselves and risk drifting from the
``/mcp/<name>`` convention.
Returns a map of ``{namespace: url}`` for the per-domain endpoints
only (claude-code's MCP routing expects per-domain framing). The
``/mcp/all/`` bundle endpoint exists on the same app but is
intentionally omitted from the URL map — it's only meaningful to
external clients via the MCP frontend, not to claude-code.
Returns:
* Starlette app to serve via uvicorn.
* ``{namespace: url}`` for the per-domain endpoints (claude-code's
MCP routing expects per-domain framing). ``/mcp/all/`` is
omitted — only meaningful to external clients via the MCP
frontend, not to claude-code.
* ``{namespace: FastMCP}`` for backends that need in-process
access (Raycast doesn't natively understand MCP, so the
gateway calls ``list_tools``/``call_tool`` directly to splice
MCP tools into the Raycast wire).
"""
servers: dict[str, FastMCP] = {spec.name: _build_server(spec) for spec in mcps}
child_apps = {
name: s.http_app(transport="http", path="/")
for name, s in servers.items()
name: s.http_app(transport="http", path="/") for name, s in servers.items()
}
routes = [
Mount(f"/mcp/{name}", app=app) for name, app in child_apps.items()
]
routes = [Mount(f"/mcp/{name}", app=app) for name, app in child_apps.items()]
# /mcp/all — flat-namespace bundle. Skip when there's nothing to
# bundle so we don't pay for an empty session manager lifecycle.
@@ -102,7 +104,7 @@ def build_internal_app(
# 307 redirect from ``/mcp/<name>`` to ``/mcp/<name>/`` that
# ``Mount`` produces when a child route lives at ``/``.
urls = {name: f"http://{host}:{port}/mcp/{name}/" for name in servers}
return app, urls
return app, urls, servers
def _build_server(spec: McpServerT) -> FastMCP: