Skip to content

Commit b103913

Browse files
committed
add an agent to call mcp tools
1 parent 70fffb6 commit b103913

File tree

4 files changed

+120
-0
lines changed

4 files changed

+120
-0
lines changed

.vscode/mcp.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"servers": {
3+
"math_server": {
4+
"command": "uv",
5+
"args": ["run", "python", "template_langgraph/mcps/math_server.py"]
6+
},
37
"playwright": {
48
"command": "npx",
59
"args": ["-y", "@playwright/mcp@latest", "--caps=vision"]

scripts/mcp_operator.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import asyncio
2+
import logging
3+
from logging import basicConfig
4+
5+
import typer
6+
from dotenv import load_dotenv
7+
from langchain_mcp_adapters.client import MultiServerMCPClient
8+
from langgraph.graph import START, MessagesState, StateGraph
9+
from langgraph.prebuilt import ToolNode, tools_condition
10+
11+
from template_langgraph.llms.azure_openais import AzureOpenAiWrapper
12+
from template_langgraph.loggers import get_logger
13+
14+
# Initialize the Typer application
15+
app = typer.Typer(
16+
add_completion=False,
17+
help="MCP operator CLI",
18+
)
19+
20+
# Set up logging
21+
logger = get_logger(__name__)
22+
23+
24+
def set_verbose_logging(verbose: bool):
25+
if verbose:
26+
logger.setLevel(logging.DEBUG)
27+
basicConfig(level=logging.DEBUG)
28+
logging.basicConfig(level=logging.DEBUG)
29+
30+
31+
async def run_agent(query: str) -> dict:
32+
client = MultiServerMCPClient(
33+
{
34+
"math": {
35+
"command": "python",
36+
# Make sure to update to the full absolute path to your math_server.py file
37+
"args": ["./template_langgraph/mcps/math_server.py"],
38+
"transport": "stdio",
39+
},
40+
}
41+
)
42+
tools = await client.get_tools()
43+
llm = AzureOpenAiWrapper().chat_model
44+
45+
def call_model(state: MessagesState):
46+
response = llm.bind_tools(tools).invoke(state["messages"])
47+
return {"messages": response}
48+
49+
builder = StateGraph(MessagesState)
50+
builder.add_node(call_model)
51+
builder.add_node(ToolNode(tools))
52+
builder.add_edge(START, "call_model")
53+
builder.add_conditional_edges(
54+
"call_model",
55+
tools_condition,
56+
)
57+
builder.add_edge("tools", "call_model")
58+
graph = builder.compile()
59+
return await graph.ainvoke({"messages": query})
60+
61+
62+
@app.command()
63+
def chat(
64+
query: str = typer.Option(
65+
"What's (3 + 5) x 12?",
66+
"--query",
67+
"-q",
68+
help="Input query to the chatbot",
69+
),
70+
verbose: bool = typer.Option(
71+
False,
72+
"--verbose",
73+
"-v",
74+
help="Enable verbose output",
75+
),
76+
):
77+
set_verbose_logging(verbose)
78+
logger.info("Running...")
79+
logger.info(f"Query: {query}")
80+
response = asyncio.run(run_agent(query=query))
81+
for k, v in response.items():
82+
logger.info(f"{k}: {v}")
83+
logger.info(response.get("messages")[-1].content)
84+
85+
86+
if __name__ == "__main__":
87+
load_dotenv(
88+
override=True,
89+
verbose=True,
90+
)
91+
app()

template_langgraph/mcps/__init__.py

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from mcp.server.fastmcp import FastMCP
2+
3+
from template_langgraph.loggers import get_logger
4+
5+
logger = get_logger(__name__)
6+
logger.setLevel("DEBUG")
7+
8+
mcp = FastMCP("Math")
9+
10+
11+
@mcp.tool()
12+
def add(a: int, b: int) -> int:
13+
"""Add two numbers"""
14+
return a + b
15+
16+
17+
@mcp.tool()
18+
def multiply(a: int, b: int) -> int:
19+
"""Multiply two numbers"""
20+
return a * b
21+
22+
23+
if __name__ == "__main__":
24+
logger.info("Starting Math MCP server...")
25+
mcp.run(transport="stdio")

0 commit comments

Comments
 (0)