Skip to content

Commit 94610bd

Browse files
committed
Fix tests. Add test GHA. Improve publish action.
1 parent 27777dc commit 94610bd

File tree

6 files changed

+819
-19
lines changed

6 files changed

+819
-19
lines changed

.github/workflows/publish.yml

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
name: Publish Python Package
1+
name: Publish Python Package and GitHub Release
22

33
on:
4-
release:
5-
types: [created]
6-
7-
permissions:
8-
contents: read
4+
push:
5+
tags:
6+
- '**'
97

108
jobs:
11-
#call-test:
12-
# uses: ./.github/workflows/test.yml
9+
call-test:
10+
uses: ./.github/workflows/test.yml
1311

1412
build:
13+
name: Build distribution package
1514
runs-on: ubuntu-latest
16-
#needs: [call-test]
15+
needs: [call-test]
1716
steps:
1817
- uses: actions/checkout@v4
1918
- name: Install uv
@@ -26,7 +25,13 @@ jobs:
2625
with:
2726
python-version: "3.12"
2827
- name: Install dependencies
29-
run: uv sync --dev --python 3.12 --python-preference only-system
28+
run: |
29+
uv sync --locked --dev --python 3.12 --python-preference only-system
30+
version=$(uv run --locked python -c 'from importlib.metadata import version; print(version("langchain_mcp"))')
31+
if [ "$version" != "${{ github.ref_name }}" ]; then
32+
echo "Built version $version does not match tag ${{ github.ref_name }}, aborting"
33+
exit 1
34+
fi
3035
- name: Build
3136
run: |
3237
uv build
@@ -36,7 +41,8 @@ jobs:
3641
name: python-package-distribution
3742
path: dist/
3843

39-
deploy:
44+
publish:
45+
name: Publish Python distribution package to PyPI
4046
runs-on: ubuntu-latest
4147
needs:
4248
- build
@@ -51,3 +57,39 @@ jobs:
5157
path: dist/
5258
- name: Publish to PyPI
5359
uses: pypa/gh-action-pypi-publish@release/v1
60+
61+
github-release:
62+
name: Sign the Python distribution package with Sigstore and upload to GitHub Release
63+
needs:
64+
- publish
65+
runs-on: ubuntu-latest
66+
permissions:
67+
contents: write
68+
id-token: write
69+
steps:
70+
- name: Download dists
71+
uses: actions/download-artifact@v4
72+
with:
73+
name: python-package-distribution
74+
path: dist/
75+
- name: Sign with Sigstore
76+
uses: sigstore/[email protected]
77+
with:
78+
inputs: >-
79+
./dist/*.tar.gz
80+
./dist/*.whl
81+
- name: Create GitHub Release
82+
env:
83+
GITHUB_TOKEN: ${{ github.token }}
84+
run: >-
85+
gh release create
86+
'${{ github.ref_name }}'
87+
--repo '${{ github.repository }}'
88+
--notes ""
89+
- name: Upload artifact signatures to GitHub Release
90+
env:
91+
GITHUB_TOKEN: ${{ github.token }}
92+
run: >-
93+
gh release upload
94+
'${{ github.ref_name }}' dist/**
95+
--repo '${{ github.repository }}'

.github/workflows/test.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Test
2+
3+
on: [push, pull_request, workflow_call]
4+
5+
permissions:
6+
contents: read
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
python-version: ["3.10", "3.11", "3.12", "3.13"]
15+
steps:
16+
- uses: actions/checkout@v4
17+
- name: Install uv
18+
uses: astral-sh/setup-uv@v2
19+
with:
20+
enable-cache: true
21+
cache-dependency-glob: "uv.lock"
22+
- name: Set up Python ${{ matrix.python-version }}
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
- name: Run tests
27+
run: uv run --isolated --locked --python ${{ matrix.python-version }} --python-preference only-system pytest
28+
- name: Lint
29+
run: |
30+
uv run --python ${{ matrix.python-version }} --python-preference only-system ruff format --check
31+
uv run --python ${{ matrix.python-version }} --python-preference only-system ruff check

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "langchain-mcp"
3-
version = "0.0.0"
4-
description = "Placholder, coming soon"
3+
version = "0.1.0a1"
4+
description = "Model Context Protocol tool calling support for LangChain"
55
readme = "README.md"
66
authors = [
77
{ name = "Andrew Wason", email = "[email protected]" }
@@ -10,7 +10,7 @@ requires-python = ">=3.10"
1010
dependencies = [
1111
"langchain-core~=0.3.21",
1212
"mcp~=1.0.0",
13-
"pydantic>=2.10.2",
13+
"pydantic~=2.10.2",
1414
]
1515
classifiers = [
1616
"License :: OSI Approved :: MIT License",
@@ -69,4 +69,4 @@ select = [
6969

7070
[tool.pytest.ini_options]
7171
asyncio_mode = "auto"
72-
asyncio_default_fixture_loop_scope = "session"
72+
asyncio_default_fixture_loop_scope = "class"

src/langchain_mcp/toolkit.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# Copyright (C) 2024 Andrew Wason
22
# SPDX-License-Identifier: MIT
33

4+
import asyncio
45
import typing as t
6+
import warnings
57
from collections.abc import Callable
68

79
import pydantic
810
import pydantic_core
9-
from langchain_core.tools.base import BaseTool, BaseToolkit, InjectedToolArg, ToolException
11+
from langchain_core.tools.base import BaseTool, BaseToolkit, ToolException
1012
from mcp import ClientSession
1113

1214

@@ -68,7 +70,10 @@ class MCPTool(BaseTool):
6870
handle_tool_error: bool | str | Callable[[ToolException], str] | None = True
6971

7072
def _run(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
71-
raise NotImplementedError("Must invoke tool asynchronously")
73+
warnings.warn(
74+
"Invoke this tool asynchronousely using `ainvoke`. This method exists only to satisfy tests.", stacklevel=1
75+
)
76+
return asyncio.run(self._arun(*args, **kwargs))
7277

7378
async def _arun(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
7479
result = await self.session.call_tool(self.name, arguments=kwargs)

tests/integration_tests/test_tool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# SPDX-License-Identifier: MIT
33

44
import pytest
5-
from langchain_tests.unit_tests import ToolsUnitTests
5+
from langchain_tests.integration_tests import ToolsIntegrationTests
66

77

88
@pytest.mark.usefixtures("mcptool")
9-
class TestMCPToolIntegration(ToolsUnitTests):
9+
class TestMCPToolIntegration(ToolsIntegrationTests):
1010
@property
1111
def tool_constructor(self):
1212
return self.tool

0 commit comments

Comments
 (0)