Skip to content

Commit 3e87754

Browse files
committed
improve ux
1 parent b945fdf commit 3e87754

File tree

2 files changed

+46
-17
lines changed

2 files changed

+46
-17
lines changed

README.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def multiply(a: int, b: int) -> int:
4646
return a * b
4747

4848
if __name__ == "__main__":
49-
mcp.run()
49+
mcp.run(transport="stdio")
5050
```
5151

5252
### Client
@@ -103,7 +103,11 @@ async def get_weather(location: str) -> int:
103103
return "It's always sunny in New York"
104104

105105
if __name__ == "__main__":
106-
mcp.run()
106+
mcp.run(transport="sse")
107+
```
108+
109+
```bash
110+
python weather_server.py
107111
```
108112

109113
### Client
@@ -115,19 +119,21 @@ from langgraph.prebuilt import create_react_agent
115119
from langchain_openai import ChatOpenAI
116120
model = ChatOpenAI(model="gpt-4o")
117121

118-
async with MultiServerMCPClient() as client:
119-
await client.connect_to_server(
120-
"math",
121-
command="python",
122-
# Make sure to update to the full absolute path to your math_server.py file
123-
args=["/path/to/math_server.py"],
124-
)
125-
await client.connect_to_server(
126-
"weather",
127-
command="python",
128-
# Make sure to update to the full absolute path to your weather_server.py file
129-
args=["/path/to/weather_server.py"],
130-
)
122+
async with MultiServerMCPClient(
123+
{
124+
"math": {
125+
"command": "python",
126+
# Make sure to update to the full absolute path to your math_server.py file
127+
"args": ["/path/to/math_server.py"],
128+
"transport": "stdio",
129+
},
130+
"weather": {
131+
# make sure you start your weather server on port 8000
132+
"url": "http://localhost:8000/sse",
133+
"transport": "sse",
134+
}
135+
}
136+
) as client:
131137
agent = create_react_agent(model, client.get_tools())
132138
math_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
133139
weather_response = await agent.ainvoke({"messages": "what is the weather in nyc?"})

langchain_mcp_adapters/client.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from contextlib import AsyncExitStack
22
from types import TracebackType
3-
from typing import Literal, cast
3+
from typing import Literal, TypedDict, cast
44

55
from langchain_core.tools import BaseTool
66
from mcp import ClientSession, StdioServerParameters
@@ -13,10 +13,25 @@
1313
DEFAULT_ENCODING_ERROR_HANDLER = "strict"
1414

1515

16+
class StdioConnection(TypedDict):
17+
transport: Literal["stdio"]
18+
command: str
19+
args: list[str]
20+
env: dict[str, str] | None
21+
encoding: str
22+
encoding_error_handler: Literal["strict", "ignore", "replace"]
23+
24+
25+
class SSEConnection(TypedDict):
26+
transport: Literal["sse"]
27+
url: str
28+
29+
1630
class MultiServerMCPClient:
1731
"""Client for connecting to multiple MCP servers and loading LangChain-compatible tools from them."""
1832

19-
def __init__(self) -> None:
33+
def __init__(self, connections: dict[str, StdioConnection | SSEConnection] = None) -> None:
34+
self.connections = connections
2035
self.exit_stack = AsyncExitStack()
2136
self.sessions: dict[str, ClientSession] = {}
2237
self.server_name_to_tools: dict[str, list[BaseTool]] = {}
@@ -151,6 +166,14 @@ def get_tools(self) -> list[BaseTool]:
151166
return all_tools
152167

153168
async def __aenter__(self) -> "MultiServerMCPClient":
169+
connections = self.connections or {}
170+
for server_name, connection in connections.items():
171+
connection_dict = connection.copy()
172+
transport = connection_dict.pop("transport")
173+
if transport == "stdio":
174+
await self.connect_to_server_via_stdio(server_name, **connection_dict)
175+
elif transport == "sse":
176+
await self.connect_to_server_via_sse(server_name, **connection_dict)
154177
return self
155178

156179
async def __aexit__(

0 commit comments

Comments
 (0)