langroid 0.53.0__py3-none-any.whl → 0.53.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langroid/agent/tools/mcp/__init__.py +15 -3
- langroid/agent/tools/mcp/decorators.py +2 -2
- langroid/agent/tools/mcp/fastmcp_client.py +77 -11
- {langroid-0.53.0.dist-info → langroid-0.53.2.dist-info}/METADATA +17 -1
- {langroid-0.53.0.dist-info → langroid-0.53.2.dist-info}/RECORD +7 -7
- {langroid-0.53.0.dist-info → langroid-0.53.2.dist-info}/WHEEL +0 -0
- {langroid-0.53.0.dist-info → langroid-0.53.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,22 @@
|
|
1
1
|
from .decorators import mcp_tool
|
2
|
-
from .fastmcp_client import
|
2
|
+
from .fastmcp_client import (
|
3
|
+
FastMCPClient,
|
4
|
+
get_langroid_tool,
|
5
|
+
get_langroid_tool_async,
|
6
|
+
get_langroid_tools,
|
7
|
+
get_langroid_tools_async,
|
8
|
+
get_mcp_tool_async,
|
9
|
+
get_mcp_tools_async,
|
10
|
+
)
|
3
11
|
|
4
12
|
|
5
13
|
__all__ = [
|
6
14
|
"mcp_tool",
|
7
15
|
"FastMCPClient",
|
8
|
-
"
|
9
|
-
"
|
16
|
+
"get_langroid_tool",
|
17
|
+
"get_langroid_tool_async",
|
18
|
+
"get_langroid_tools",
|
19
|
+
"get_langroid_tools_async",
|
20
|
+
"get_mcp_tool_async",
|
21
|
+
"get_mcp_tools_async",
|
10
22
|
]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from typing import Callable, Type
|
2
2
|
|
3
3
|
from langroid.agent.tool_message import ToolMessage
|
4
|
-
from langroid.agent.tools.mcp.fastmcp_client import
|
4
|
+
from langroid.agent.tools.mcp.fastmcp_client import get_langroid_tool
|
5
5
|
|
6
6
|
|
7
7
|
def mcp_tool(
|
@@ -18,7 +18,7 @@ def mcp_tool(
|
|
18
18
|
|
19
19
|
def decorator(user_cls: Type[ToolMessage]) -> Type[ToolMessage]:
|
20
20
|
# build the “real” ToolMessage subclass for this server/tool
|
21
|
-
RealTool: Type[ToolMessage] =
|
21
|
+
RealTool: Type[ToolMessage] = get_langroid_tool(server, tool_name)
|
22
22
|
|
23
23
|
# copy user‐defined methods / attributes onto RealTool
|
24
24
|
for name, attr in user_cls.__dict__.items():
|
@@ -113,11 +113,14 @@ class FastMCPClient:
|
|
113
113
|
# Default fallback
|
114
114
|
return Any, Field(default=default, description=desc)
|
115
115
|
|
116
|
-
async def
|
117
|
-
"""
|
116
|
+
async def get_langroid_tool(self, tool_name: str) -> Type[ToolMessage]:
|
117
|
+
"""
|
118
|
+
Create a Langroid ToolMessage subclass from the MCP Tool
|
119
|
+
with the given `tool_name`.
|
120
|
+
"""
|
118
121
|
if not self.client:
|
119
122
|
raise RuntimeError("Client not initialized. Use async with FastMCPClient.")
|
120
|
-
target = await self.
|
123
|
+
target = await self.get_mcp_tool_async(tool_name)
|
121
124
|
if target is None:
|
122
125
|
raise ValueError(f"No tool named {tool_name}")
|
123
126
|
props = target.inputSchema.get("properties", {})
|
@@ -131,6 +134,24 @@ class FastMCPClient:
|
|
131
134
|
camel_case = "".join(part.capitalize() for part in parts)
|
132
135
|
model_name = f"{camel_case}Tool"
|
133
136
|
|
137
|
+
from langroid.agent.tool_message import ToolMessage as _BaseToolMessage
|
138
|
+
|
139
|
+
# IMPORTANT: Avoid clashes with reserved field names in Langroid ToolMessage!
|
140
|
+
# First figure out which field names are reserved
|
141
|
+
reserved = set(_BaseToolMessage.__annotations__.keys())
|
142
|
+
reserved.update(["recipient", "_handler"])
|
143
|
+
renamed: Dict[str, str] = {}
|
144
|
+
new_fields: Dict[str, Tuple[type, Any]] = {}
|
145
|
+
for fname, (ftype, fld) in fields.items():
|
146
|
+
if fname in reserved:
|
147
|
+
new_name = fname + "__"
|
148
|
+
renamed[fname] = new_name
|
149
|
+
new_fields[new_name] = (ftype, fld)
|
150
|
+
else:
|
151
|
+
new_fields[fname] = (ftype, fld)
|
152
|
+
# now replace fields with our renamed‐aware mapping
|
153
|
+
fields = new_fields
|
154
|
+
|
134
155
|
# create Langroid ToolMessage subclass, with expected fields.
|
135
156
|
tool_model = cast(
|
136
157
|
Type[ToolMessage],
|
@@ -143,6 +164,7 @@ class FastMCPClient:
|
|
143
164
|
),
|
144
165
|
)
|
145
166
|
tool_model._server = self.server # type: ignore[attr-defined]
|
167
|
+
tool_model._renamed_fields = renamed # type: ignore[attr-defined]
|
146
168
|
|
147
169
|
# 2) define an arg-free call_tool_async()
|
148
170
|
async def call_tool_async(self: ToolMessage) -> Any:
|
@@ -150,6 +172,12 @@ class FastMCPClient:
|
|
150
172
|
|
151
173
|
# pack up the payload
|
152
174
|
payload = self.dict(exclude=self.Config.schema_extra["exclude"])
|
175
|
+
|
176
|
+
# restore any renamed fields
|
177
|
+
for orig, new in self.__class__._renamed_fields.items(): # type: ignore
|
178
|
+
if new in payload:
|
179
|
+
payload[orig] = payload.pop(new)
|
180
|
+
|
153
181
|
# open a fresh client, call the tool, then close
|
154
182
|
async with FastMCPClient(self.__class__._server) as client: # type: ignore
|
155
183
|
return await client.call_mcp_tool(self.request, payload)
|
@@ -167,7 +195,7 @@ class FastMCPClient:
|
|
167
195
|
|
168
196
|
return tool_model
|
169
197
|
|
170
|
-
async def
|
198
|
+
async def get_langroid_tools(self) -> List[Type[ToolMessage]]:
|
171
199
|
"""
|
172
200
|
Get all available tools as Langroid ToolMessage classes,
|
173
201
|
handling nested schemas, with `handle_async` methods
|
@@ -177,11 +205,13 @@ class FastMCPClient:
|
|
177
205
|
resp = await self.client.list_tools()
|
178
206
|
tools: List[Type[ToolMessage]] = []
|
179
207
|
for t in resp:
|
180
|
-
tools.append(await self.
|
208
|
+
tools.append(await self.get_langroid_tool(t.name))
|
181
209
|
return tools
|
182
210
|
|
183
|
-
async def
|
184
|
-
"""Find the MCP Tool
|
211
|
+
async def get_mcp_tool_async(self, name: str) -> Optional[Tool]:
|
212
|
+
"""Find the "original" MCP Tool (i.e. of type mcp.types.Tool) on the server
|
213
|
+
matching `name`, or None if missing. This contains the metadata for the tool:
|
214
|
+
name, description, inputSchema, etc.
|
185
215
|
|
186
216
|
Args:
|
187
217
|
name: Name of the tool to look up.
|
@@ -240,10 +270,46 @@ class FastMCPClient:
|
|
240
270
|
return self._convert_tool_result(tool_name, result)
|
241
271
|
|
242
272
|
|
243
|
-
async def
|
273
|
+
async def get_langroid_tool_async(
|
274
|
+
server: str | ClientTransport,
|
275
|
+
tool_name: str,
|
276
|
+
) -> Type[ToolMessage]:
|
244
277
|
async with FastMCPClient(server) as client:
|
245
|
-
return await client.
|
278
|
+
return await client.get_langroid_tool(tool_name)
|
246
279
|
|
247
280
|
|
248
|
-
def
|
249
|
-
|
281
|
+
def get_langroid_tool(
|
282
|
+
server: str | ClientTransport,
|
283
|
+
tool_name: str,
|
284
|
+
) -> Type[ToolMessage]:
|
285
|
+
return asyncio.run(get_langroid_tool_async(server, tool_name))
|
286
|
+
|
287
|
+
|
288
|
+
async def get_langroid_tools_async(
|
289
|
+
server: str | ClientTransport,
|
290
|
+
) -> List[Type[ToolMessage]]:
|
291
|
+
async with FastMCPClient(server) as client:
|
292
|
+
return await client.get_langroid_tools()
|
293
|
+
|
294
|
+
|
295
|
+
def get_langroid_tools(
|
296
|
+
server: str | ClientTransport,
|
297
|
+
) -> List[Type[ToolMessage]]:
|
298
|
+
return asyncio.run(get_langroid_tools_async(server))
|
299
|
+
|
300
|
+
|
301
|
+
async def get_mcp_tool_async(
|
302
|
+
server: str | ClientTransport,
|
303
|
+
name: str,
|
304
|
+
) -> Optional[Tool]:
|
305
|
+
async with FastMCPClient(server) as client:
|
306
|
+
return await client.get_mcp_tool_async(name)
|
307
|
+
|
308
|
+
|
309
|
+
async def get_mcp_tools_async(
|
310
|
+
server: str | ClientTransport,
|
311
|
+
) -> List[Tool]:
|
312
|
+
async with FastMCPClient(server) as client:
|
313
|
+
if not client.client:
|
314
|
+
raise RuntimeError("Client not initialized. Use async with FastMCPClient.")
|
315
|
+
return await client.client.list_tools()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: langroid
|
3
|
-
Version: 0.53.
|
3
|
+
Version: 0.53.2
|
4
4
|
Summary: Harness LLMs with Multi-Agent Programming
|
5
5
|
Author-email: Prasad Chalasani <pchalasani@gmail.com>
|
6
6
|
License: MIT
|
@@ -338,6 +338,22 @@ teacher_task.run()
|
|
338
338
|
<details>
|
339
339
|
<summary> <b>Click to expand</b></summary>
|
340
340
|
|
341
|
+
- **Mar-Apr 2025:**
|
342
|
+
- [0.53.0](https://github.com/langroid/langroid/releases/tag/0.53.0) MCP Tools Support.
|
343
|
+
- [0.52.0](https://github.com/langroid/langroid/releases/tag/0.52.0) Multimodal support, i.e. allow PDF, image
|
344
|
+
inputs to LLM.
|
345
|
+
- [0.51.0](https://github.com/langroid/langroid/releases/tag/0.51.0) `LLMPdfParser`, generalizing
|
346
|
+
`GeminiPdfParser` to parse documents directly with LLM.
|
347
|
+
- [0.50.0](https://github.com/langroid/langroid/releases/tag/0.50.0) Structure-aware Markdown chunking with chunks
|
348
|
+
enriched by section headers.
|
349
|
+
- [0.49.0](https://github.com/langroid/langroid/releases/tag/0.49.0) Enable easy switch to LiteLLM Proxy-server
|
350
|
+
- [0.48.0](https://github.com/langroid/langroid/releases/tag/0.48.0) Exa Crawler, Markitdown Parser
|
351
|
+
- [0.47.0](https://github.com/langroid/langroid/releases/tag/0.47.0) Support Firecrawl URL scraper/crawler -
|
352
|
+
thanks @abab-dev
|
353
|
+
- [0.46.0](https://github.com/langroid/langroid/releases/tag/0.46.0) Support LangDB LLM Gateway - thanks @MrunmayS.
|
354
|
+
- [0.45.0](https://github.com/langroid/langroid/releases/tag/0.45.0) Markdown parsing with `Marker` - thanks @abab-dev
|
355
|
+
- [0.44.0](https://github.com/langroid/langroid/releases/tag/0.44.0) Late imports to reduce startup time. Thanks
|
356
|
+
@abab-dev
|
341
357
|
- **Feb 2025:**
|
342
358
|
- [0.43.0](https://github.com/langroid/langroid/releases/tag/0.43.0): `GeminiPdfParser` for parsing PDF using
|
343
359
|
Gemini LLMs - Thanks @abab-dev.
|
@@ -54,9 +54,9 @@ langroid/agent/tools/retrieval_tool.py,sha256=zcAV20PP_6VzSd-UE-IJcabaBseFL_QNz5
|
|
54
54
|
langroid/agent/tools/rewind_tool.py,sha256=XAXL3BpNhCmBGYq_qi_sZfHJuIw7NY2jp4wnojJ7WRs,5606
|
55
55
|
langroid/agent/tools/segment_extract_tool.py,sha256=__srZ_VGYLVOdPrITUM8S0HpmX4q7r5FHWMDdHdEv8w,1440
|
56
56
|
langroid/agent/tools/tavily_search_tool.py,sha256=soI-j0HdgVQLf09wRQScaEK4b5RpAX9C4cwOivRFWWI,1903
|
57
|
-
langroid/agent/tools/mcp/__init__.py,sha256=
|
58
|
-
langroid/agent/tools/mcp/decorators.py,sha256=
|
59
|
-
langroid/agent/tools/mcp/fastmcp_client.py,sha256=
|
57
|
+
langroid/agent/tools/mcp/__init__.py,sha256=cQb3gYxXk0YZ23QCqbVNMbMeCeWCJj6w3gqGnvyqv7w,459
|
58
|
+
langroid/agent/tools/mcp/decorators.py,sha256=mWnlTjyI9PMNi750PWzC_2B6V5K_XdxH0Co9kE2yAj0,1145
|
59
|
+
langroid/agent/tools/mcp/fastmcp_client.py,sha256=ffOV0lJOtE3DLfA6y3Fib28jyACySJPgbqjNJpSAEQA,11815
|
60
60
|
langroid/cachedb/__init__.py,sha256=G2KyNnk3Qkhv7OKyxTOnpsxfDycx3NY0O_wXkJlalNY,96
|
61
61
|
langroid/cachedb/base.py,sha256=ztVjB1DtN6pLCujCWnR6xruHxwVj3XkYniRTYAKKqk0,1354
|
62
62
|
langroid/cachedb/redis_cachedb.py,sha256=7kgnbf4b5CKsCrlL97mHWKvdvlLt8zgn7lc528jEpiE,5141
|
@@ -132,7 +132,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
|
|
132
132
|
langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
|
133
133
|
langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
|
134
134
|
langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
|
135
|
-
langroid-0.53.
|
136
|
-
langroid-0.53.
|
137
|
-
langroid-0.53.
|
138
|
-
langroid-0.53.
|
135
|
+
langroid-0.53.2.dist-info/METADATA,sha256=t3on9Riu1tK0c1icC8e3mhsCFEjTU4a7SkMGI1kV4bY,64823
|
136
|
+
langroid-0.53.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
137
|
+
langroid-0.53.2.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
138
|
+
langroid-0.53.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|