langchain-mcp-tools 0.0.15__tar.gz → 0.0.17__tar.gz
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.
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/PKG-INFO +9 -9
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/README.md +8 -6
- {langchain_mcp_tools-0.0.15/src → langchain_mcp_tools-0.0.17}/langchain_mcp_tools/langchain_mcp_tools.py +3 -2
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/langchain_mcp_tools.egg-info/PKG-INFO +9 -9
- langchain_mcp_tools-0.0.17/langchain_mcp_tools.egg-info/SOURCES.txt +11 -0
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/langchain_mcp_tools.egg-info/requires.txt +0 -2
- langchain_mcp_tools-0.0.17/langchain_mcp_tools.egg-info/top_level.txt +2 -0
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/pyproject.toml +1 -3
- langchain_mcp_tools-0.0.15/langchain_mcp_tools.egg-info/SOURCES.txt +0 -13
- langchain_mcp_tools-0.0.15/langchain_mcp_tools.egg-info/top_level.txt +0 -3
- langchain_mcp_tools-0.0.15/src/tests/__init__.py +0 -2
- langchain_mcp_tools-0.0.15/src/tests/test_langchain_mcp_tools.py +0 -163
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/LICENSE +0 -0
- {langchain_mcp_tools-0.0.15/src → langchain_mcp_tools-0.0.17}/langchain_mcp_tools/__init__.py +0 -0
- {langchain_mcp_tools-0.0.15/src → langchain_mcp_tools-0.0.17}/langchain_mcp_tools/py.typed +0 -0
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/langchain_mcp_tools.egg-info/dependency_links.txt +0 -0
- {langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: langchain-mcp-tools
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.17
|
4
4
|
Summary: Model Context Protocol (MCP) To LangChain Tools Conversion Utility
|
5
5
|
Project-URL: Bug Tracker, https://github.com/hideya/langchain-mcp-tools-py/issues
|
6
6
|
Project-URL: Source Code, https://github.com/hideya/langchain-mcp-tools-py
|
@@ -18,8 +18,6 @@ Requires-Dist: mcp>=1.2.0
|
|
18
18
|
Requires-Dist: pyjson5>=1.6.8
|
19
19
|
Requires-Dist: pympler>=1.1
|
20
20
|
Requires-Dist: python-dotenv>=1.0.1
|
21
|
-
Requires-Dist: pytest>=8.3.4
|
22
|
-
Requires-Dist: pytest-asyncio>=0.25.2
|
23
21
|
Provides-Extra: dev
|
24
22
|
Requires-Dist: twine>=6.0.1; extra == "dev"
|
25
23
|
|
@@ -72,11 +70,12 @@ and is expressed as a `dict`, e.g.:
|
|
72
70
|
)
|
73
71
|
```
|
74
72
|
|
75
|
-
|
76
|
-
and returns LangChain Tools
|
77
|
-
|
78
|
-
|
79
|
-
|
73
|
+
This utility function initializes all specified MCP servers in parallel,
|
74
|
+
and returns [LangChain Tools](https://python.langchain.com/api_reference/core/tools.html)
|
75
|
+
(`tools: List[BaseTool]`)
|
76
|
+
by gathering available MCP tools from the servers,
|
77
|
+
and by wrapping them into LangChain tools.
|
78
|
+
It also returns an async callback function (`cleanup: McpServerCleanupFn`)
|
80
79
|
to be invoked to close all MCP server sessions when finished.
|
81
80
|
|
82
81
|
The returned tools can be used with LangChain, e.g.:
|
@@ -157,7 +156,8 @@ Any comments pointing out something I am missing would be greatly appreciated!
|
|
157
156
|
|
158
157
|
3. Task Lifecycle:
|
159
158
|
|
160
|
-
The following illustrates how
|
159
|
+
The following task lifecyle diagram illustrates how the above strategy
|
160
|
+
was impelemented:
|
161
161
|
```
|
162
162
|
[Task starts]
|
163
163
|
↓
|
@@ -47,11 +47,12 @@ and is expressed as a `dict`, e.g.:
|
|
47
47
|
)
|
48
48
|
```
|
49
49
|
|
50
|
-
|
51
|
-
and returns LangChain Tools
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
This utility function initializes all specified MCP servers in parallel,
|
51
|
+
and returns [LangChain Tools](https://python.langchain.com/api_reference/core/tools.html)
|
52
|
+
(`tools: List[BaseTool]`)
|
53
|
+
by gathering available MCP tools from the servers,
|
54
|
+
and by wrapping them into LangChain tools.
|
55
|
+
It also returns an async callback function (`cleanup: McpServerCleanupFn`)
|
55
56
|
to be invoked to close all MCP server sessions when finished.
|
56
57
|
|
57
58
|
The returned tools can be used with LangChain, e.g.:
|
@@ -132,7 +133,8 @@ Any comments pointing out something I am missing would be greatly appreciated!
|
|
132
133
|
|
133
134
|
3. Task Lifecycle:
|
134
135
|
|
135
|
-
The following illustrates how
|
136
|
+
The following task lifecyle diagram illustrates how the above strategy
|
137
|
+
was impelemented:
|
136
138
|
```
|
137
139
|
[Task starts]
|
138
140
|
↓
|
@@ -46,7 +46,7 @@ The key aspects are:
|
|
46
46
|
- Resources management for `stdio_client` and `ClientSession` seems
|
47
47
|
to require relying exclusively on `asynccontextmanager` for cleanup,
|
48
48
|
with no manual cleanup options
|
49
|
-
(based on
|
49
|
+
(based on the mcp python-sdk impl as of Jan 14, 2025)
|
50
50
|
- Initializing multiple MCP servers in parallel requires a dedicated
|
51
51
|
`asyncio.Task` per server
|
52
52
|
- Need to keep sessions alive for later use by different tasks
|
@@ -75,7 +75,8 @@ The key aspects are:
|
|
75
75
|
|
76
76
|
3. Task Lifecycle:
|
77
77
|
|
78
|
-
The following illustrates how
|
78
|
+
The following task lifecyle diagram illustrates how the above strategy
|
79
|
+
was impelemented:
|
79
80
|
```
|
80
81
|
[Task starts]
|
81
82
|
↓
|
{langchain_mcp_tools-0.0.15 → langchain_mcp_tools-0.0.17}/langchain_mcp_tools.egg-info/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: langchain-mcp-tools
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.17
|
4
4
|
Summary: Model Context Protocol (MCP) To LangChain Tools Conversion Utility
|
5
5
|
Project-URL: Bug Tracker, https://github.com/hideya/langchain-mcp-tools-py/issues
|
6
6
|
Project-URL: Source Code, https://github.com/hideya/langchain-mcp-tools-py
|
@@ -18,8 +18,6 @@ Requires-Dist: mcp>=1.2.0
|
|
18
18
|
Requires-Dist: pyjson5>=1.6.8
|
19
19
|
Requires-Dist: pympler>=1.1
|
20
20
|
Requires-Dist: python-dotenv>=1.0.1
|
21
|
-
Requires-Dist: pytest>=8.3.4
|
22
|
-
Requires-Dist: pytest-asyncio>=0.25.2
|
23
21
|
Provides-Extra: dev
|
24
22
|
Requires-Dist: twine>=6.0.1; extra == "dev"
|
25
23
|
|
@@ -72,11 +70,12 @@ and is expressed as a `dict`, e.g.:
|
|
72
70
|
)
|
73
71
|
```
|
74
72
|
|
75
|
-
|
76
|
-
and returns LangChain Tools
|
77
|
-
|
78
|
-
|
79
|
-
|
73
|
+
This utility function initializes all specified MCP servers in parallel,
|
74
|
+
and returns [LangChain Tools](https://python.langchain.com/api_reference/core/tools.html)
|
75
|
+
(`tools: List[BaseTool]`)
|
76
|
+
by gathering available MCP tools from the servers,
|
77
|
+
and by wrapping them into LangChain tools.
|
78
|
+
It also returns an async callback function (`cleanup: McpServerCleanupFn`)
|
80
79
|
to be invoked to close all MCP server sessions when finished.
|
81
80
|
|
82
81
|
The returned tools can be used with LangChain, e.g.:
|
@@ -157,7 +156,8 @@ Any comments pointing out something I am missing would be greatly appreciated!
|
|
157
156
|
|
158
157
|
3. Task Lifecycle:
|
159
158
|
|
160
|
-
The following illustrates how
|
159
|
+
The following task lifecyle diagram illustrates how the above strategy
|
160
|
+
was impelemented:
|
161
161
|
```
|
162
162
|
[Task starts]
|
163
163
|
↓
|
@@ -0,0 +1,11 @@
|
|
1
|
+
LICENSE
|
2
|
+
README.md
|
3
|
+
pyproject.toml
|
4
|
+
langchain_mcp_tools/__init__.py
|
5
|
+
langchain_mcp_tools/langchain_mcp_tools.py
|
6
|
+
langchain_mcp_tools/py.typed
|
7
|
+
langchain_mcp_tools.egg-info/PKG-INFO
|
8
|
+
langchain_mcp_tools.egg-info/SOURCES.txt
|
9
|
+
langchain_mcp_tools.egg-info/dependency_links.txt
|
10
|
+
langchain_mcp_tools.egg-info/requires.txt
|
11
|
+
langchain_mcp_tools.egg-info/top_level.txt
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "langchain-mcp-tools"
|
3
|
-
version = "0.0.
|
3
|
+
version = "0.0.17"
|
4
4
|
description = "Model Context Protocol (MCP) To LangChain Tools Conversion Utility"
|
5
5
|
readme = "README.md"
|
6
6
|
requires-python = ">=3.11"
|
@@ -16,8 +16,6 @@ dependencies = [
|
|
16
16
|
"pyjson5>=1.6.8",
|
17
17
|
"pympler>=1.1",
|
18
18
|
"python-dotenv>=1.0.1",
|
19
|
-
"pytest>=8.3.4",
|
20
|
-
"pytest-asyncio>=0.25.2",
|
21
19
|
]
|
22
20
|
|
23
21
|
[project.optional-dependencies]
|
@@ -1,13 +0,0 @@
|
|
1
|
-
LICENSE
|
2
|
-
README.md
|
3
|
-
pyproject.toml
|
4
|
-
langchain_mcp_tools.egg-info/PKG-INFO
|
5
|
-
langchain_mcp_tools.egg-info/SOURCES.txt
|
6
|
-
langchain_mcp_tools.egg-info/dependency_links.txt
|
7
|
-
langchain_mcp_tools.egg-info/requires.txt
|
8
|
-
langchain_mcp_tools.egg-info/top_level.txt
|
9
|
-
src/langchain_mcp_tools/__init__.py
|
10
|
-
src/langchain_mcp_tools/langchain_mcp_tools.py
|
11
|
-
src/langchain_mcp_tools/py.typed
|
12
|
-
src/tests/__init__.py
|
13
|
-
src/tests/test_langchain_mcp_tools.py
|
@@ -1,163 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
from unittest.mock import AsyncMock, MagicMock, patch
|
3
|
-
from langchain_core.tools import BaseTool
|
4
|
-
from langchain_mcp_tools.langchain_mcp_tools import (
|
5
|
-
convert_mcp_to_langchain_tools,
|
6
|
-
)
|
7
|
-
|
8
|
-
# Fix the asyncio mark warning by installing pytest-asyncio
|
9
|
-
pytest_plugins = ('pytest_asyncio',)
|
10
|
-
|
11
|
-
|
12
|
-
@pytest.fixture
|
13
|
-
def mock_stdio_client():
|
14
|
-
with patch('langchain_mcp_tools.langchain_mcp_tools.stdio_client') as mock:
|
15
|
-
mock.return_value.__aenter__.return_value = (AsyncMock(), AsyncMock())
|
16
|
-
yield mock
|
17
|
-
|
18
|
-
|
19
|
-
@pytest.fixture
|
20
|
-
def mock_client_session():
|
21
|
-
with patch('langchain_mcp_tools.langchain_mcp_tools.ClientSession') as mock:
|
22
|
-
session = AsyncMock()
|
23
|
-
# Mock the list_tools response
|
24
|
-
session.list_tools.return_value = MagicMock(
|
25
|
-
tools=[
|
26
|
-
MagicMock(
|
27
|
-
name="tool1",
|
28
|
-
description="Test tool",
|
29
|
-
inputSchema={"type": "object", "properties": {}}
|
30
|
-
)
|
31
|
-
]
|
32
|
-
)
|
33
|
-
mock.return_value.__aenter__.return_value = session
|
34
|
-
yield mock
|
35
|
-
|
36
|
-
|
37
|
-
@pytest.mark.asyncio
|
38
|
-
async def test_convert_mcp_to_langchain_tools_empty():
|
39
|
-
server_configs = {}
|
40
|
-
tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
|
41
|
-
assert isinstance(tools, list)
|
42
|
-
assert len(tools) == 0
|
43
|
-
await cleanup()
|
44
|
-
|
45
|
-
|
46
|
-
"""
|
47
|
-
@pytest.mark.asyncio
|
48
|
-
async def test_convert_mcp_to_langchain_tools_invalid_config():
|
49
|
-
server_configs = {"invalid": {"command": "nonexistent"}}
|
50
|
-
with pytest.raises(Exception):
|
51
|
-
await convert_mcp_to_langchain_tools(server_configs)
|
52
|
-
"""
|
53
|
-
|
54
|
-
|
55
|
-
"""
|
56
|
-
@pytest.mark.asyncio
|
57
|
-
async def test_convert_single_mcp_success(
|
58
|
-
mock_stdio_client,
|
59
|
-
mock_client_session
|
60
|
-
):
|
61
|
-
# Test data
|
62
|
-
server_name = "test_server"
|
63
|
-
server_config = {
|
64
|
-
"command": "test_command",
|
65
|
-
"args": ["--test"],
|
66
|
-
"env": {"TEST_ENV": "value"}
|
67
|
-
}
|
68
|
-
langchain_tools = []
|
69
|
-
ready_event = asyncio.Event()
|
70
|
-
cleanup_event = asyncio.Event()
|
71
|
-
|
72
|
-
# Create task
|
73
|
-
task = asyncio.create_task(
|
74
|
-
convert_single_mcp_to_langchain_tools(
|
75
|
-
server_name,
|
76
|
-
server_config,
|
77
|
-
langchain_tools,
|
78
|
-
ready_event,
|
79
|
-
cleanup_event
|
80
|
-
)
|
81
|
-
)
|
82
|
-
|
83
|
-
# Wait for ready event
|
84
|
-
await asyncio.wait_for(ready_event.wait(), timeout=1.0)
|
85
|
-
|
86
|
-
# Verify tools were created
|
87
|
-
assert len(langchain_tools) == 1
|
88
|
-
assert isinstance(langchain_tools[0], BaseTool)
|
89
|
-
assert langchain_tools[0].name == "tool1"
|
90
|
-
|
91
|
-
# Trigger cleanup
|
92
|
-
cleanup_event.set()
|
93
|
-
await task
|
94
|
-
"""
|
95
|
-
|
96
|
-
|
97
|
-
@pytest.mark.asyncio
|
98
|
-
async def test_convert_mcp_to_langchain_tools_multiple_servers(
|
99
|
-
mock_stdio_client,
|
100
|
-
mock_client_session
|
101
|
-
):
|
102
|
-
server_configs = {
|
103
|
-
"server1": {"command": "cmd1", "args": []},
|
104
|
-
"server2": {"command": "cmd2", "args": []}
|
105
|
-
}
|
106
|
-
|
107
|
-
tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
|
108
|
-
|
109
|
-
# Verify correct number of tools created
|
110
|
-
assert len(tools) == 2 # One tool per server
|
111
|
-
assert all(isinstance(tool, BaseTool) for tool in tools)
|
112
|
-
|
113
|
-
# Test cleanup
|
114
|
-
await cleanup()
|
115
|
-
|
116
|
-
|
117
|
-
"""
|
118
|
-
@pytest.mark.asyncio
|
119
|
-
async def test_tool_execution(mock_stdio_client, mock_client_session):
|
120
|
-
server_configs = {
|
121
|
-
"test_server": {"command": "test", "args": []}
|
122
|
-
}
|
123
|
-
|
124
|
-
# Mock the tool execution response
|
125
|
-
session = mock_client_session.return_value.__aenter__.return_value
|
126
|
-
session.call_tool.return_value = MagicMock(
|
127
|
-
isError=False,
|
128
|
-
content={"result": "success"}
|
129
|
-
)
|
130
|
-
|
131
|
-
tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
|
132
|
-
|
133
|
-
# Test tool execution
|
134
|
-
result = await tools[0]._arun(test_param="value")
|
135
|
-
assert result == {"result": "success"}
|
136
|
-
|
137
|
-
# Verify tool was called with correct parameters
|
138
|
-
session.call_tool.assert_called_once_with("tool1", {"test_param": "value"})
|
139
|
-
|
140
|
-
await cleanup()
|
141
|
-
"""
|
142
|
-
|
143
|
-
|
144
|
-
@pytest.mark.asyncio
|
145
|
-
async def test_tool_execution_error(mock_stdio_client, mock_client_session):
|
146
|
-
server_configs = {
|
147
|
-
"test_server": {"command": "test", "args": []}
|
148
|
-
}
|
149
|
-
|
150
|
-
# Mock error response
|
151
|
-
session = mock_client_session.return_value.__aenter__.return_value
|
152
|
-
session.call_tool.return_value = MagicMock(
|
153
|
-
isError=True,
|
154
|
-
content="Error message"
|
155
|
-
)
|
156
|
-
|
157
|
-
tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
|
158
|
-
|
159
|
-
# Test tool execution error
|
160
|
-
with pytest.raises(Exception):
|
161
|
-
await tools[0]._arun(test_param="value")
|
162
|
-
|
163
|
-
await cleanup()
|
File without changes
|
{langchain_mcp_tools-0.0.15/src → langchain_mcp_tools-0.0.17}/langchain_mcp_tools/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|