mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-25 07:04:44 +08:00
fix: env parameters exception when configuring SSE or HTTP MCP server (#513)
* fix: _create_streamable_http_session() got an unexpected keyword argument 'env' fix unit error * update md --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
@@ -46,7 +46,18 @@ For `sse` type:
|
|||||||
{
|
{
|
||||||
"transport": "sse",
|
"transport": "sse",
|
||||||
"url": "http://localhost:3000/sse",
|
"url": "http://localhost:3000/sse",
|
||||||
"env": {
|
"headers": {
|
||||||
|
"API_KEY": "value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For `streamable_http` type:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": "streamable_http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
"API_KEY": "value"
|
"API_KEY": "value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ async def _setup_and_execute_agent_step(
|
|||||||
mcp_servers[server_name] = {
|
mcp_servers[server_name] = {
|
||||||
k: v
|
k: v
|
||||||
for k, v in server_config.items()
|
for k, v in server_config.items()
|
||||||
if k in ("transport", "command", "args", "url", "env")
|
if k in ("transport", "command", "args", "url", "env", "headers")
|
||||||
}
|
}
|
||||||
for tool_name in server_config["enabled_tools"]:
|
for tool_name in server_config["enabled_tools"]:
|
||||||
enabled_tools[tool_name] = server_name
|
enabled_tools[tool_name] = server_name
|
||||||
|
|||||||
@@ -552,6 +552,7 @@ async def mcp_server_metadata(request: MCPServerMetadataRequest):
|
|||||||
args=request.args,
|
args=request.args,
|
||||||
url=request.url,
|
url=request.url,
|
||||||
env=request.env,
|
env=request.env,
|
||||||
|
headers=request.headers,
|
||||||
timeout_seconds=timeout,
|
timeout_seconds=timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -562,6 +563,7 @@ async def mcp_server_metadata(request: MCPServerMetadataRequest):
|
|||||||
args=request.args,
|
args=request.args,
|
||||||
url=request.url,
|
url=request.url,
|
||||||
env=request.env,
|
env=request.env,
|
||||||
|
headers=request.headers,
|
||||||
tools=tools,
|
tools=tools,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ class MCPServerMetadataRequest(BaseModel):
|
|||||||
"""Request model for MCP server metadata."""
|
"""Request model for MCP server metadata."""
|
||||||
|
|
||||||
transport: str = Field(
|
transport: str = Field(
|
||||||
..., description="The type of MCP server connection (stdio or sse)"
|
...,
|
||||||
|
description=(
|
||||||
|
"The type of MCP server connection (stdio or sse or streamable_http)"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
command: Optional[str] = Field(
|
command: Optional[str] = Field(
|
||||||
None, description="The command to execute (for stdio type)"
|
None, description="The command to execute (for stdio type)"
|
||||||
@@ -21,7 +24,12 @@ class MCPServerMetadataRequest(BaseModel):
|
|||||||
url: Optional[str] = Field(
|
url: Optional[str] = Field(
|
||||||
None, description="The URL of the SSE server (for sse type)"
|
None, description="The URL of the SSE server (for sse type)"
|
||||||
)
|
)
|
||||||
env: Optional[Dict[str, str]] = Field(None, description="Environment variables")
|
env: Optional[Dict[str, str]] = Field(
|
||||||
|
None, description="Environment variables (for stdio type)"
|
||||||
|
)
|
||||||
|
headers: Optional[Dict[str, str]] = Field(
|
||||||
|
None, description="HTTP headers (for sse/streamable_http type)"
|
||||||
|
)
|
||||||
timeout_seconds: Optional[int] = Field(
|
timeout_seconds: Optional[int] = Field(
|
||||||
None, description="Optional custom timeout in seconds for the operation"
|
None, description="Optional custom timeout in seconds for the operation"
|
||||||
)
|
)
|
||||||
@@ -31,7 +39,10 @@ class MCPServerMetadataResponse(BaseModel):
|
|||||||
"""Response model for MCP server metadata."""
|
"""Response model for MCP server metadata."""
|
||||||
|
|
||||||
transport: str = Field(
|
transport: str = Field(
|
||||||
..., description="The type of MCP server connection (stdio or sse)"
|
...,
|
||||||
|
description=(
|
||||||
|
"The type of MCP server connection (stdio or sse or streamable_http)"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
command: Optional[str] = Field(
|
command: Optional[str] = Field(
|
||||||
None, description="The command to execute (for stdio type)"
|
None, description="The command to execute (for stdio type)"
|
||||||
@@ -42,7 +53,12 @@ class MCPServerMetadataResponse(BaseModel):
|
|||||||
url: Optional[str] = Field(
|
url: Optional[str] = Field(
|
||||||
None, description="The URL of the SSE server (for sse type)"
|
None, description="The URL of the SSE server (for sse type)"
|
||||||
)
|
)
|
||||||
env: Optional[Dict[str, str]] = Field(None, description="Environment variables")
|
env: Optional[Dict[str, str]] = Field(
|
||||||
|
None, description="Environment variables (for stdio type)"
|
||||||
|
)
|
||||||
|
headers: Optional[Dict[str, str]] = Field(
|
||||||
|
None, description="HTTP headers (for sse/streamable_http type)"
|
||||||
|
)
|
||||||
tools: List = Field(
|
tools: List = Field(
|
||||||
default_factory=list, description="Available tools from the MCP server"
|
default_factory=list, description="Available tools from the MCP server"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,17 +47,19 @@ async def load_mcp_tools(
|
|||||||
args: Optional[List[str]] = None,
|
args: Optional[List[str]] = None,
|
||||||
url: Optional[str] = None,
|
url: Optional[str] = None,
|
||||||
env: Optional[Dict[str, str]] = None,
|
env: Optional[Dict[str, str]] = None,
|
||||||
|
headers: Optional[Dict[str, str]] = None,
|
||||||
timeout_seconds: int = 60, # Longer default timeout for first-time executions
|
timeout_seconds: int = 60, # Longer default timeout for first-time executions
|
||||||
) -> List:
|
) -> List:
|
||||||
"""
|
"""
|
||||||
Load tools from an MCP server.
|
Load tools from an MCP server.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
server_type: The type of MCP server connection (stdio or sse)
|
server_type: The type of MCP server connection (stdio, sse, or streamable_http)
|
||||||
command: The command to execute (for stdio type)
|
command: The command to execute (for stdio type)
|
||||||
args: Command arguments (for stdio type)
|
args: Command arguments (for stdio type)
|
||||||
url: The URL of the SSE server (for sse type)
|
url: The URL of the SSE/HTTP server (for sse/streamable_http type)
|
||||||
env: Environment variables
|
env: Environment variables (for stdio type)
|
||||||
|
headers: HTTP headers (for sse/streamable_http type)
|
||||||
timeout_seconds: Timeout in seconds (default: 60 for first-time executions)
|
timeout_seconds: Timeout in seconds (default: 60 for first-time executions)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -90,7 +92,7 @@ async def load_mcp_tools(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await _get_tools_from_client_session(
|
return await _get_tools_from_client_session(
|
||||||
sse_client(url=url), timeout_seconds
|
sse_client(url=url, headers=headers, timeout=timeout_seconds), timeout_seconds
|
||||||
)
|
)
|
||||||
|
|
||||||
elif server_type == "streamable_http":
|
elif server_type == "streamable_http":
|
||||||
@@ -100,7 +102,7 @@ async def load_mcp_tools(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await _get_tools_from_client_session(
|
return await _get_tools_from_client_session(
|
||||||
streamablehttp_client(url=url), timeout_seconds
|
streamablehttp_client(url=url, headers=headers, timeout=timeout_seconds), timeout_seconds,
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -87,10 +87,15 @@ async def test_load_mcp_tools_sse_success(mock_sse_client, mock_get_tools):
|
|||||||
result = await mcp_utils.load_mcp_tools(
|
result = await mcp_utils.load_mcp_tools(
|
||||||
server_type="sse",
|
server_type="sse",
|
||||||
url="http://localhost:1234",
|
url="http://localhost:1234",
|
||||||
|
headers={"Authorization": "Bearer 1234567890"},
|
||||||
timeout_seconds=7,
|
timeout_seconds=7,
|
||||||
)
|
)
|
||||||
assert result == ["toolB"]
|
assert result == ["toolB"]
|
||||||
mock_sse_client.assert_called_once_with(url="http://localhost:1234")
|
mock_sse_client.assert_called_once_with(
|
||||||
|
url="http://localhost:1234",
|
||||||
|
headers={"Authorization": "Bearer 1234567890"},
|
||||||
|
timeout=7,
|
||||||
|
)
|
||||||
mock_get_tools.assert_awaited_once_with(mock_client, 7)
|
mock_get_tools.assert_awaited_once_with(mock_client, 7)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export interface GenericMCPServerMetadata<T extends string> {
|
|||||||
transport: T;
|
transport: T;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
env?: Record<string, string>;
|
env?: Record<string, string>;
|
||||||
|
headers?: Record<string, string>;
|
||||||
tools: MCPToolMetadata[];
|
tools: MCPToolMetadata[];
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
updatedAt: number;
|
updatedAt: number;
|
||||||
@@ -28,8 +29,9 @@ export type SimpleStdioMCPServerMetadata = Omit<
|
|||||||
"enabled" | "tools" | "createdAt" | "updatedAt"
|
"enabled" | "tools" | "createdAt" | "updatedAt"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export interface SSEMCPServerMetadata extends GenericMCPServerMetadata<"sse"|"streamable_http"> {
|
export interface SSEMCPServerMetadata
|
||||||
transport: "sse"|"streamable_http"
|
extends GenericMCPServerMetadata<"sse" | "streamable_http"> {
|
||||||
|
transport: "sse" | "streamable_http";
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export const getChatStreamSettings = () => {
|
|||||||
if (mcpServers.length > 0) {
|
if (mcpServers.length > 0) {
|
||||||
mcpSettings = {
|
mcpSettings = {
|
||||||
servers: mcpServers.reduce((acc, cur) => {
|
servers: mcpServers.reduce((acc, cur) => {
|
||||||
const { transport, env } = cur;
|
const { transport, env, headers } = cur;
|
||||||
let server: SimpleMCPServerMetadata;
|
let server: SimpleMCPServerMetadata;
|
||||||
if (transport === "stdio") {
|
if (transport === "stdio") {
|
||||||
server = {
|
server = {
|
||||||
@@ -108,7 +108,7 @@ export const getChatStreamSettings = () => {
|
|||||||
server = {
|
server = {
|
||||||
name: cur.name,
|
name: cur.name,
|
||||||
transport,
|
transport,
|
||||||
env,
|
headers,
|
||||||
url: cur.url,
|
url: cur.url,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user