feat: implement mcp frontend
This commit is contained in:
@@ -16,8 +16,11 @@ from fastmcp import Client
|
||||
from fastmcp.client.transports import StdioTransport, StreamableHttpTransport
|
||||
from fastmcp.server import create_proxy
|
||||
|
||||
from beaver_gateway.mcp.lenient import LenientStdioTransport
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.client.transports.base import ClientTransport
|
||||
|
||||
from beaver_gateway.mcp.types import HttpMcp, StdioMcp
|
||||
|
||||
@@ -27,22 +30,37 @@ def build_stdio_proxy(spec: StdioMcp) -> FastMCP:
|
||||
|
||||
``spec.command`` is a non-empty tuple; the first element is the
|
||||
executable and the rest are CLI args. ``StdioTransport`` keeps the
|
||||
subprocess alive across calls.
|
||||
subprocess alive across calls. When ``spec.lenient`` is set we
|
||||
swap in :class:`LenientStdioTransport`, which silently drops
|
||||
non-JSON-RPC stdout lines instead of forwarding them as exceptions
|
||||
(lets us ingest MCPs that print ``Processing...`` chatter on stdout
|
||||
without leaking warnings to downstream UIs).
|
||||
"""
|
||||
if not spec.command:
|
||||
msg = f"stdio MCP {spec.name!r} has empty command"
|
||||
raise ValueError(msg)
|
||||
command, *args = spec.command
|
||||
transport = StdioTransport(
|
||||
command=command,
|
||||
args=list(args),
|
||||
env=spec.env,
|
||||
cwd=str(spec.cwd) if spec.cwd is not None else None,
|
||||
)
|
||||
cwd = str(spec.cwd) if spec.cwd is not None else None
|
||||
transport: ClientTransport
|
||||
if spec.lenient:
|
||||
transport = LenientStdioTransport(
|
||||
command=command, args=list(args), env=spec.env, cwd=cwd
|
||||
)
|
||||
else:
|
||||
transport = StdioTransport(
|
||||
command=command, args=list(args), env=spec.env, cwd=cwd
|
||||
)
|
||||
return create_proxy(Client(transport, name=spec.name))
|
||||
|
||||
|
||||
def build_http_proxy(spec: HttpMcp) -> FastMCP:
|
||||
"""Wrap a remote streamable-HTTP MCP into a mountable ``FastMCPProxy``."""
|
||||
transport = StreamableHttpTransport(url=spec.url, auth=spec.auth)
|
||||
"""Wrap a remote streamable-HTTP MCP into a mountable ``FastMCPProxy``.
|
||||
|
||||
``spec.headers`` are folded into the upstream client; pass per-call
|
||||
auth (e.g. ``X-Api-Key``) here rather than as ``auth`` when the
|
||||
upstream rejects Bearer headers.
|
||||
"""
|
||||
transport = StreamableHttpTransport(
|
||||
url=spec.url, auth=spec.auth, headers=spec.headers
|
||||
)
|
||||
return create_proxy(Client(transport, name=spec.name))
|
||||
|
||||
Reference in New Issue
Block a user