fix(mcp): hoist sse/http imports, annotate auto-detection heuristic, restore field comments

This commit is contained in:
Re-bin
2026-03-05 14:44:45 +00:00
parent 2306d4c11c
commit b71c1bdca7
3 changed files with 12 additions and 12 deletions

View File

@@ -14,9 +14,9 @@
🐈 **nanobot** is an **ultra-lightweight** personal AI assistant inspired by [OpenClaw](https://github.com/openclaw/openclaw) 🐈 **nanobot** is an **ultra-lightweight** personal AI assistant inspired by [OpenClaw](https://github.com/openclaw/openclaw)
⚡️ Delivers core agent functionality in just **~4,000** lines of code — **99% smaller** than Clawdbot's 430k+ lines. ⚡️ Delivers core agent functionality with **99% fewer lines of code** than OpenClaw, making it more customizable and understandable.
📏 Real-time line count: **3,935 lines** (run `bash core_agent_lines.sh` to verify anytime) 📏 Real-time line count: run `bash core_agent_lines.sh` to verify anytime
## 📢 News ## 📢 News

View File

@@ -58,7 +58,9 @@ async def connect_mcp_servers(
) -> None: ) -> None:
"""Connect to configured MCP servers and register their tools.""" """Connect to configured MCP servers and register their tools."""
from mcp import ClientSession, StdioServerParameters from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client
from mcp.client.stdio import stdio_client from mcp.client.stdio import stdio_client
from mcp.client.streamable_http import streamable_http_client
for name, cfg in mcp_servers.items(): for name, cfg in mcp_servers.items():
try: try:
@@ -67,6 +69,7 @@ async def connect_mcp_servers(
if cfg.command: if cfg.command:
transport_type = "stdio" transport_type = "stdio"
elif cfg.url: elif cfg.url:
# Convention: URLs ending with /sse use SSE transport; others use streamableHttp
transport_type = ( transport_type = (
"sse" if cfg.url.rstrip("/").endswith("/sse") else "streamableHttp" "sse" if cfg.url.rstrip("/").endswith("/sse") else "streamableHttp"
) )
@@ -80,8 +83,6 @@ async def connect_mcp_servers(
) )
read, write = await stack.enter_async_context(stdio_client(params)) read, write = await stack.enter_async_context(stdio_client(params))
elif transport_type == "sse": elif transport_type == "sse":
from mcp.client.sse import sse_client
def httpx_client_factory( def httpx_client_factory(
headers: dict[str, str] | None = None, headers: dict[str, str] | None = None,
timeout: httpx.Timeout | None = None, timeout: httpx.Timeout | None = None,
@@ -99,7 +100,6 @@ async def connect_mcp_servers(
sse_client(cfg.url, httpx_client_factory=httpx_client_factory) sse_client(cfg.url, httpx_client_factory=httpx_client_factory)
) )
elif transport_type == "streamableHttp": elif transport_type == "streamableHttp":
from mcp.client.streamable_http import streamable_http_client
# Always provide an explicit httpx client so MCP HTTP transport does not # Always provide an explicit httpx client so MCP HTTP transport does not
# inherit httpx's default 5s timeout and preempt the higher-level tool timeout. # inherit httpx's default 5s timeout and preempt the higher-level tool timeout.
http_client = await stack.enter_async_context( http_client = await stack.enter_async_context(

View File

@@ -329,13 +329,13 @@ class ExecToolConfig(Base):
class MCPServerConfig(Base): class MCPServerConfig(Base):
"""MCP server connection configuration (stdio or HTTP).""" """MCP server connection configuration (stdio or HTTP)."""
type: Literal["stdio", "sse", "streamableHttp"] | None = None type: Literal["stdio", "sse", "streamableHttp"] | None = None # auto-detected if omitted
command: str = "" command: str = "" # Stdio: command to run (e.g. "npx")
args: list[str] = Field(default_factory=list) args: list[str] = Field(default_factory=list) # Stdio: command arguments
env: dict[str, str] = Field(default_factory=dict) env: dict[str, str] = Field(default_factory=dict) # Stdio: extra env vars
url: str = "" url: str = "" # HTTP/SSE: endpoint URL
headers: dict[str, str] = Field(default_factory=dict) headers: dict[str, str] = Field(default_factory=dict) # HTTP/SSE: custom headers
tool_timeout: int = 30 tool_timeout: int = 30 # seconds before a tool call is cancelled
class ToolsConfig(Base): class ToolsConfig(Base):