Does swarm support mcp tool?

Hi,

I would like to know if the prebuilt create_swarm supports mcp tools ?

My code looks like below:

async def swarm():

    # get MCP tools
    mcp_client = MultiServerMCPClient(
        {
            "math_tools":{
            "url": "http://localhost:8000/sse",
            "transport": "sse"
            },
        }
    )
    mcp_tools = await mcp_client.get_tools()

    alice = create_react_agent(
        model,
        [mcp_tools, create_handoff_tool(agent_name="Bob")],
        prompt="You are Alice, an math expert.",
        name="Alice",
    )

    bob = create_react_agent(
        model,
        [create_handoff_tool(agent_name="Alice", description="Transfer to Alice, she can help with math")],
        prompt="You are Bob, you speak like a pirate.",
        name="Bob",
    )

    workflow = create_swarm(
        [alice, bob],
        default_active_agent="Alice"
    )
    return await workflow.compile()

where one the tool looks like this:

@mcp.tool()
async def multiply(a: int, b: int) -> int:
    """multiply 2 numbers

    Args:
        a (int): the first number to multiply
        b (int): the second number to multiply

    Returns:
        int: the multiplication of a and b
    """
    print(colored("multiplication tool", "cyan"))
    print(colored(f"{a=}, {b=}", "cyan"))
    return a*b


if __name__ == "__main__":
    print(colored("starting math mcp server ...", "cyan"))
    mcp.run(transport="sse")

When running langgraph dev, I got the following error:

ValueError: The first argument must be a string or a callable with a name for tool decorator. Got <class ‘list’>

Is there a conflict between the create_handoff_tool and those from the mcp server ?

thanks,

Jonathan

I think this line is the problem, you can’t pass a list here, you need to unpack it first. I am not sure if it will actually work, but that is where the error is originating from I believe.

thanks @Isaac ,

I appreciate the fast reply.

I took example from Langgraph demo

alice = create_react_agent(
    model,
    [add, create_handoff_tool(agent_name="Bob")],
    prompt="You are Alice, an addition expert.",
    name="Alice",
)

but yeah, in this example add is a function whereas in mine I tried to pass a list of langchain_core.tools.structured.StructuredTool

I’ll try your suggestion.

update: there might be a cleaner way to do that but the issue was indeed that I was passing a list.

updated code

mcp_tools = await mcp_client.get_tools()
tools = mcp_tools.copy()
tools.append(create_handoff_tool(agent_name="Bob",description="Transfer to Bob, he talks like a pirate"))

alice = create_react_agent(
        model=model,
        # [mcp_tools, create_handoff_tool(agent_name="Bob")],
        tools=tools,
        prompt="You are Alice, a math expert.",
        name="Alice",
    )

    bob = create_react_agent(
        model=model,
        tools=[create_handoff_tool(agent_name="Alice", description="Transfer to Alice, she can help with math")],
        prompt="You are Bob, you speak like a pirate.",
        name="Bob",
    )

    workflow = create_swarm(
        [alice, bob],
        default_active_agent="Alice"
    )
    app = workflow.compile()
    return app

I think it works because create_handoff_tool is just a wrapper for a tool decorator

def create_handoff_tool(*, agent_name: str, description: str | None = None):
    name = f"transfer_to_{agent_name}"
    description = description or f"Transfer to {agent_name}"

    @tool(name, description=description)
    def handoff_tool(
        state: Annotated[MessagesState, InjectedState], 
        tool_call_id: Annotated[str, InjectedToolCallId],
    ) -> Command:

so at the end I’m just adding another @tool in the tools list.