7070 BetaInputJSONDelta ,
7171 BetaMCPToolResultBlock ,
7272 BetaMCPToolUseBlock ,
73+ BetaMCPToolUseBlockParam ,
7374 BetaMemoryTool20250818Param ,
7475 BetaMessage ,
7576 BetaMessageParam ,
@@ -268,8 +269,7 @@ async def _messages_create(
268269 ) -> BetaMessage | AsyncStream [BetaRawMessageStreamEvent ]:
269270 # standalone function to make it easier to override
270271 tools = self ._get_tools (model_request_parameters )
271- tools , beta_features = self ._add_builtin_tools (tools , model_request_parameters )
272- mcp_servers , beta_features = self ._get_mcp_servers (model_request_parameters , beta_features )
272+ tools , mcp_servers , beta_features = self ._add_builtin_tools (tools , model_request_parameters )
273273
274274 tool_choice : BetaToolChoiceParam | None
275275
@@ -325,8 +325,6 @@ def _process_response(self, response: BetaMessage) -> ModelResponse:
325325 """Process a non-streamed response, and prepare a message to return."""
326326 items : list [ModelResponsePart ] = []
327327 for item in response .content :
328- from anthropic .types .beta import BetaMCPToolUseBlock
329-
330328 if isinstance (item , BetaTextBlock ):
331329 items .append (TextPart (content = item .text ))
332330 elif isinstance (item , BetaServerToolUseBlock ):
@@ -395,8 +393,9 @@ def _get_tools(self, model_request_parameters: ModelRequestParameters) -> list[B
395393
396394 def _add_builtin_tools (
397395 self , tools : list [BetaToolUnionParam ], model_request_parameters : ModelRequestParameters
398- ) -> tuple [list [BetaToolUnionParam ], list [str ]]:
396+ ) -> tuple [list [BetaToolUnionParam ], list [BetaRequestMCPServerURLDefinitionParam ], list [ str ]]:
399397 beta_features : list [str ] = []
398+ mcp_servers : list [BetaRequestMCPServerURLDefinitionParam ] = []
400399 for tool in model_request_parameters .builtin_tools :
401400 if isinstance (tool , WebSearchTool ):
402401 user_location = UserLocation (type = 'approximate' , ** tool .user_location ) if tool .user_location else None
@@ -420,36 +419,26 @@ def _add_builtin_tools(
420419 tools = [tool for tool in tools if tool ['name' ] != 'memory' ]
421420 tools .append (BetaMemoryTool20250818Param (name = 'memory' , type = 'memory_20250818' ))
422421 beta_features .append ('context-management-2025-06-27' )
423- elif isinstance (tool , MCPServerTool ):
424- # Anthropic MCP servers are a separate parameter in the API call
425- pass
422+ if isinstance (tool , MCPServerTool ) and tool .url :
423+ tool_configuration = BetaRequestMCPServerToolConfigurationParam (
424+ enabled = True ,
425+ allowed_tools = tool .allowed_tools ,
426+ )
427+ mcp_servers .append (
428+ BetaRequestMCPServerURLDefinitionParam (
429+ type = 'url' ,
430+ name = tool .label ,
431+ url = tool .url ,
432+ authorization_token = tool .authorization ,
433+ tool_configuration = tool_configuration ,
434+ )
435+ )
436+ beta_features .append ('mcp-client-2025-04-04' )
426437 else : # pragma: no cover
427438 raise UserError (
428439 f'`{ tool .__class__ .__name__ } ` is not supported by `AnthropicModel`. If it should be, please file an issue.'
429440 )
430- return tools , beta_features
431-
432- def _get_mcp_servers (
433- self , model_request_parameters : ModelRequestParameters , beta_features : list [str ]
434- ) -> tuple [list [BetaRequestMCPServerURLDefinitionParam ], list [str ]]:
435- mcp_servers : list [BetaRequestMCPServerURLDefinitionParam ] = []
436- for tool in model_request_parameters .builtin_tools :
437- if isinstance (tool , MCPServerTool ):
438- tool_configuration = BetaRequestMCPServerToolConfigurationParam (
439- enabled = True ,
440- allowed_tools = tool .allowed_tools ,
441- )
442- mcp_servers .append (
443- BetaRequestMCPServerURLDefinitionParam (
444- type = 'url' ,
445- name = tool .server_label ,
446- url = tool .server_url ,
447- authorization_token = tool .authorization ,
448- tool_configuration = tool_configuration ,
449- )
450- )
451- beta_features .append ('mcp-client-2025-04-04' )
452- return mcp_servers , beta_features
441+ return tools , mcp_servers , beta_features
453442
454443 async def _map_message (self , messages : list [ModelMessage ]) -> tuple [str , list [BetaMessageParam ]]: # noqa: C901
455444 """Just maps a `pydantic_ai.Message` to a `anthropic.types.MessageParam`."""
@@ -495,6 +484,8 @@ async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[Be
495484 | BetaCodeExecutionToolResultBlockParam
496485 | BetaThinkingBlockParam
497486 | BetaRedactedThinkingBlockParam
487+ | BetaMCPToolUseBlockParam
488+ | BetaMCPToolResultBlock
498489 ] = []
499490 for response_part in m .parts :
500491 if isinstance (response_part , TextPart ):
@@ -553,6 +544,16 @@ async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[Be
553544 input = response_part .args_as_dict (),
554545 )
555546 assistant_content_params .append (server_tool_use_block_param )
547+ elif response_part .tool_name == MCPServerTool .kind : # pragma: no branch
548+ args = response_part .args_as_dict ()
549+ mcp_tool_use_block_param = BetaMCPToolUseBlockParam (
550+ id = tool_use_id ,
551+ type = 'mcp_tool_use' ,
552+ name = response_part .tool_name ,
553+ server_name = cast (str , args .get ('server_name' )),
554+ input = args .get ('input' ),
555+ )
556+ assistant_content_params .append (mcp_tool_use_block_param )
556557 elif isinstance (response_part , BuiltinToolReturnPart ):
557558 if response_part .provider_name == self .system :
558559 tool_use_id = _guard_tool_call_id (t = response_part )
@@ -584,6 +585,21 @@ async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[Be
584585 ),
585586 )
586587 )
588+ elif response_part .tool_name in ( # pragma: no branch
589+ MCPServerTool .kind ,
590+ 'mcp_tool_result' , # Backward compatibility
591+ ) and isinstance (response_part .content , str | list ):
592+ assistant_content_params .append (
593+ BetaMCPToolResultBlock (
594+ tool_use_id = tool_use_id ,
595+ type = 'mcp_tool_result' ,
596+ content = cast (
597+ str | list [BetaTextBlock ],
598+ response_part .content , # pyright: ignore[reportUnknownMemberType]
599+ ),
600+ is_error = False ,
601+ )
602+ )
587603 elif isinstance (response_part , FilePart ): # pragma: no cover
588604 # Files generated by models are not sent back to models that don't themselves generate files.
589605 pass
@@ -870,7 +886,7 @@ def _map_mcp_server_use_block(item: BetaMCPToolUseBlock, provider_name: str) ->
870886 return BuiltinToolCallPart (
871887 provider_name = provider_name ,
872888 tool_name = MCPServerTool .kind ,
873- args = cast (dict [str , Any ], item .input ) or None ,
889+ args = cast (dict [str , Any ], { 'input' : item .input , 'server_name' : item . server_name } ) or None ,
874890 tool_call_id = item .id ,
875891 )
876892
@@ -883,7 +899,7 @@ def _map_mcp_server_use_block(item: BetaMCPToolUseBlock, provider_name: str) ->
883899def _map_mcp_server_result_block (item : BetaMCPToolResultBlock , provider_name : str ) -> BuiltinToolReturnPart :
884900 return BuiltinToolReturnPart (
885901 provider_name = provider_name ,
886- tool_name = CodeExecutionTool .kind ,
902+ tool_name = MCPServerTool .kind ,
887903 content = mcp_server_result_content_ta .dump_python (item .content , mode = 'json' ),
888904 tool_call_id = item .tool_use_id ,
889905 )
0 commit comments