mirror of https://github.com/langgenius/dify.git
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)
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -188,4 +188,4 @@ class MCPClientWithAuthRetry(MCPClient):
|
|||
Raises:
|
||||
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()
|
||||
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"""
|
||||
if not self._session:
|
||||
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):
|
||||
"""Clean up resources"""
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ class ClientSession(
|
|||
self,
|
||||
name: str,
|
||||
arguments: dict[str, Any] | None = None,
|
||||
_meta: dict[str, Any] | None = None,
|
||||
read_timeout_seconds: timedelta | None = None,
|
||||
) -> types.CallToolResult:
|
||||
"""Send a tools/call request."""
|
||||
|
|
@ -256,7 +257,7 @@ class ClientSession(
|
|||
types.ClientRequest(
|
||||
types.CallToolRequest(
|
||||
method="tools/call",
|
||||
params=types.CallToolRequestParams(name=name, arguments=arguments),
|
||||
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=_meta),
|
||||
)
|
||||
),
|
||||
types.CallToolResult,
|
||||
|
|
|
|||
|
|
@ -855,6 +855,7 @@ class CallToolRequestParams(RequestParams):
|
|||
|
||||
name: str
|
||||
arguments: dict[str, Any] | None = None
|
||||
_meta: dict[str, Any] | None = None
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,7 @@ class MCPTool(Tool):
|
|||
message_id: str | None = None,
|
||||
inputs: dict[str, Any] | None = None,
|
||||
) -> Generator[ToolInvokeMessage, None, None]:
|
||||
# If inputs is provided, flatten its key/value pairs into the tool_parameters.
|
||||
# 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)
|
||||
result = self.invoke_remote_mcp_tool(tool_parameters, _meta=inputs)
|
||||
# handle dify tool output
|
||||
for content in result.content:
|
||||
if isinstance(content, TextContent):
|
||||
|
|
@ -139,7 +133,7 @@ class MCPTool(Tool):
|
|||
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 {}
|
||||
tool_parameters = self._handle_none_parameter(tool_parameters)
|
||||
|
||||
|
|
@ -174,7 +168,8 @@ class MCPTool(Tool):
|
|||
sse_read_timeout=self.sse_read_timeout,
|
||||
provider_entity=provider_entity,
|
||||
) 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:
|
||||
raise ToolInvokeError(f"Failed to connect to MCP server: {e}") from e
|
||||
except Exception as e:
|
||||
|
|
|
|||
Loading…
Reference in New Issue