Running an Agent Locally using MCP Tools

This is an example of how to run an agent that leverages MCP tools locally.

Prerequisites

This example specifically requires:

Running The Code

All the code used in the following examples can be found in our GitHub repository gen-ai-examples/custom-tool-and-agent.

git clone https://github.com/GDP-ADMIN/gen-ai-examples.git
cd gen-ai-examples/examples/custom-tool-and-agent

Set up your OPENAI_API_KEY

Get your OpenAI API key from https://platform.openai.com/api-keys.

  • Environment Variable Option

    export OPENAI_API_KEY="sk-..."

  • Environment File (.env) Option

    echo 'OPENAI_API_KEY="sk-..."' > .env

Execute the script

./run_example_stdio.sh

​The script will do the following:

  1. Spawn a Math MCP Server that has a couple of math tools (add, subtract, multiply, etc).

Show me some code.
...

mcp = FastMCP("Math_Tools")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers.

    Args:
        a: The first number.
        b: The second number.
    Returns:
        int: The sum of the two numbers.
    """
    return a + b

...

For complete code, see math_tools_stdio.py or math_tools_sse.py.

  1. Create an agent with an MCP Client connecting to the Math MCP Server.

Show me some code.
...

async def main():
    async with MCPClient(mcp_config_sse) as client:
        tools = client.get_tools()
        
        llm = ChatOpenAI(model="gpt-4.1")
        agent = Agent(
            name="MathAgent",
            instruction="You are a helpful assistant that can calculate math problems using the provided tools.",
            llm=llm,
            tools=tools,
            verbose=True
        )

...

For complete code, see hello_agent_mcp_stdio_example.py or hello_agent_mcp_sse_example.py.

  1. Execute query What is the square root of ((2 + 3 * 2) ^ 2)?.

Show me some code.
...

async def main():
    async with MCPClient(mcp_config_sse) as client:
        ...
        
        query = "What is the square root of ((2 + 3 * 2) ^ 2)?"
        response = await agent.arun(query)
        
        print(response)

if __name__ == "__main__":
    asyncio.run(main())

For complete code, see hello_agent_mcp_stdio_example.py or hello_agent_mcp_sse_example.py.

With verbose=True, you will see the agent's thinking process, which may look like this:

Available tools: ['add', 'subtract', 'multiply', 'divide', 'square_root', 'power'] Running agent with prompt: What is the square root of ((2 + 3 * 2) ^ 2)? > Entering new AgentExecutor chain... Invoking: `multiply` with `{'a': 3, 'b': 2}` Processing request of type CallToolRequest 6 Invoking: `add` with `{'a': 2, 'b': 6}` Processing request of type CallToolRequest 8 Invoking: `power` with `{'a': 8, 'b': 2}` Processing request of type CallToolRequest 64 Invoking: `square_root` with `{'a': 64}` Processing request of type CallToolRequest 8.0 The square root of ((2 + 3 * 2) ^ 2) is 8. > Finished chain. {'input': 'What is the square root of ((2 + 3 * 2) ^ 2)?', 'output': 'The square root of ((2 + 3 * 2) ^ 2) is 8.'}

The key indicators of success:

  • The agent initialization completes without errors

  • The verbose output shows the tool being invoked

  • The final output shows {'input': 'What is the square root of ((2 + 3 * 2) ^ 2)?', 'output': 'The square root of ((2 + 3 * 2) ^ 2) is 8.'}

Customizing MCP Servers

In the mcp_configs/configs.py file, you can customize the MCP servers. You can add or remove MCP Servers as per your requirements.

Defining an MCP Server requires the transport to be defined. It is one of:

  • stdio

  • sse

STDIO Server

An STDIO server is a server that uses the standard input and output to communicate with the MCP.

{
    "tool_name": {
        "command": "python",
        "args": ["mcp_tools/tool_name.py"],
        "transport": "stdio",
    }
}

command can be one of (but not limited to):

  • python

  • npx

  • docker

args is a list of arguments to pass to the command.

SSE Servers

An SSE server is a server that uses the Server-Sent Events (SSE) to communicate with the MCP. It simply needs a URL to the SSE endpoint. Typically, this ends in /sse.

{
    "tool_name": {
        "url": "http://localhost:8000/sse",
        "transport": "sse",
    }
}

Example

An example of multiple MCP servers is as follows:

mcp_config = {
    "math_tools": {
        "command": "python",
        "args": ["mcp_tools/math_tools_stdio.py"],
        "transport": "stdio",
    },
    "bosa_github": {
        "url": "https://api.bosa.id/sse/github",
        "transport": "sse",
    },
}

Last updated