mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
feat: add _meta field to CallToolRequestParams per MCP protocol
Support the protocol-reserved `_meta` parameter for tool invocations, enabling metadata (e.g., progressToken, identityToken) transmission as specified in MCP spec. See: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/basic/index.mdx#general-fields
This commit is contained in:
parent
4819e324da
commit
72f635e4e3
@ -174,7 +174,7 @@ class MCPClientWithAuthRetry(MCPClient):
|
|||||||
"""
|
"""
|
||||||
return self._execute_with_retry(super().list_tools)
|
return self._execute_with_retry(super().list_tools)
|
||||||
|
|
||||||
def invoke_tool(self, tool_name: str, tool_args: dict[str, Any]) -> CallToolResult:
|
def invoke_tool(self, tool_name: str, tool_args: dict[str, Any], _meta: dict[str, Any]) -> CallToolResult:
|
||||||
"""
|
"""
|
||||||
Invoke a tool on the MCP server with auth retry.
|
Invoke a tool on the MCP server with auth retry.
|
||||||
|
|
||||||
@ -188,4 +188,4 @@ class MCPClientWithAuthRetry(MCPClient):
|
|||||||
Raises:
|
Raises:
|
||||||
MCPAuthError: If authentication fails after retries
|
MCPAuthError: If authentication fails after retries
|
||||||
"""
|
"""
|
||||||
return self._execute_with_retry(super().invoke_tool, tool_name, tool_args)
|
return self._execute_with_retry(super().invoke_tool, tool_name, tool_args, _meta)
|
||||||
|
|||||||
@ -96,11 +96,11 @@ class MCPClient:
|
|||||||
response = self._session.list_tools()
|
response = self._session.list_tools()
|
||||||
return response.tools
|
return response.tools
|
||||||
|
|
||||||
def invoke_tool(self, tool_name: str, tool_args: dict[str, Any]) -> CallToolResult:
|
def invoke_tool(self, tool_name: str, tool_args: dict[str, Any], _meta: dict[str, Any]) -> CallToolResult:
|
||||||
"""Call a tool"""
|
"""Call a tool"""
|
||||||
if not self._session:
|
if not self._session:
|
||||||
raise ValueError("Session not initialized.")
|
raise ValueError("Session not initialized.")
|
||||||
return self._session.call_tool(tool_name, tool_args)
|
return self._session.call_tool(tool_name, tool_args, _meta=_meta)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
"""Clean up resources"""
|
"""Clean up resources"""
|
||||||
|
|||||||
@ -248,6 +248,7 @@ class ClientSession(
|
|||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
arguments: dict[str, Any] | None = None,
|
arguments: dict[str, Any] | None = None,
|
||||||
|
_meta: dict[str, Any] | None = None,
|
||||||
read_timeout_seconds: timedelta | None = None,
|
read_timeout_seconds: timedelta | None = None,
|
||||||
) -> types.CallToolResult:
|
) -> types.CallToolResult:
|
||||||
"""Send a tools/call request."""
|
"""Send a tools/call request."""
|
||||||
@ -256,7 +257,7 @@ class ClientSession(
|
|||||||
types.ClientRequest(
|
types.ClientRequest(
|
||||||
types.CallToolRequest(
|
types.CallToolRequest(
|
||||||
method="tools/call",
|
method="tools/call",
|
||||||
params=types.CallToolRequestParams(name=name, arguments=arguments),
|
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=_meta),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
types.CallToolResult,
|
types.CallToolResult,
|
||||||
|
|||||||
@ -855,6 +855,7 @@ class CallToolRequestParams(RequestParams):
|
|||||||
|
|
||||||
name: str
|
name: str
|
||||||
arguments: dict[str, Any] | None = None
|
arguments: dict[str, Any] | None = None
|
||||||
|
_meta: dict[str, Any] | None = None
|
||||||
model_config = ConfigDict(extra="allow")
|
model_config = ConfigDict(extra="allow")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -49,13 +49,7 @@ class MCPTool(Tool):
|
|||||||
message_id: str | None = None,
|
message_id: str | None = None,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
) -> Generator[ToolInvokeMessage, None, None]:
|
) -> Generator[ToolInvokeMessage, None, None]:
|
||||||
# If inputs is provided, flatten its key/value pairs into the tool_parameters.
|
result = self.invoke_remote_mcp_tool(tool_parameters, _meta=inputs)
|
||||||
# This is a conservative merge: only add a key from inputs if it does not already exist in tool_parameters.
|
|
||||||
if inputs:
|
|
||||||
for key, value in inputs.items():
|
|
||||||
if key not in tool_parameters:
|
|
||||||
tool_parameters[key] = value
|
|
||||||
result = self.invoke_remote_mcp_tool(tool_parameters)
|
|
||||||
# handle dify tool output
|
# handle dify tool output
|
||||||
for content in result.content:
|
for content in result.content:
|
||||||
if isinstance(content, TextContent):
|
if isinstance(content, TextContent):
|
||||||
@ -139,7 +133,7 @@ class MCPTool(Tool):
|
|||||||
if value is not None and not (isinstance(value, str) and value.strip() == "")
|
if value is not None and not (isinstance(value, str) and value.strip() == "")
|
||||||
}
|
}
|
||||||
|
|
||||||
def invoke_remote_mcp_tool(self, tool_parameters: dict[str, Any]) -> CallToolResult:
|
def invoke_remote_mcp_tool(self, tool_parameters: dict[str, Any], _meta: dict[str, Any]) -> CallToolResult:
|
||||||
headers = self.headers.copy() if self.headers else {}
|
headers = self.headers.copy() if self.headers else {}
|
||||||
tool_parameters = self._handle_none_parameter(tool_parameters)
|
tool_parameters = self._handle_none_parameter(tool_parameters)
|
||||||
|
|
||||||
@ -174,7 +168,8 @@ class MCPTool(Tool):
|
|||||||
sse_read_timeout=self.sse_read_timeout,
|
sse_read_timeout=self.sse_read_timeout,
|
||||||
provider_entity=provider_entity,
|
provider_entity=provider_entity,
|
||||||
) as mcp_client:
|
) as mcp_client:
|
||||||
return mcp_client.invoke_tool(tool_name=self.entity.identity.name, tool_args=tool_parameters)
|
return mcp_client.invoke_tool(tool_name=self.entity.identity.name, tool_args=tool_parameters,
|
||||||
|
_meta=_meta)
|
||||||
except MCPConnectionError as e:
|
except MCPConnectionError as e:
|
||||||
raise ToolInvokeError(f"Failed to connect to MCP server: {e}") from e
|
raise ToolInvokeError(f"Failed to connect to MCP server: {e}") from e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user