-
Notifications
You must be signed in to change notification settings - Fork 0
test(fetch_tools): add MCP mock server for integration testing #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR replaces monkeypatched test mocks with a real MCP protocol integration test setup. The tests now use an actual MCP mock server imported from the stackone-ai-node submodule, providing end-to-end validation of MCP protocol communication instead of testing stubbed method calls.
Key Changes
- Added stackone-ai-node as a Git submodule to access its MCP mock server implementation
- Created pytest fixtures that automatically start a Bun-based HTTP server for integration tests
- Rewrote all fetch_tools tests to use real MCP protocol communication instead of monkeypatching
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vendor/stackone-ai-node | Added submodule reference to the Node SDK containing the MCP mock server |
| tests/test_toolset_mcp.py | Removed old monkeypatched tests |
| tests/test_fetch_tools.py | New integration tests using real MCP server communication |
| tests/mocks/serve.ts | TypeScript server that imports from the submodule and exposes MCP endpoints |
| tests/conftest.py | Pytest configuration with session-scoped fixture for starting the mock server |
| pyproject.toml | Added integration test marker |
| flake.nix | Added bun, pnpm, and typescript-go to support running the mock server |
| .gitmodules | Configured the stackone-ai-node submodule |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Node.js for MCP mock server | ||
| bun | ||
| pnpm | ||
| typescript-go |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package name 'typescript-go' appears unusual for TypeScript tooling. Verify this is the correct package name in nixpkgs. The standard TypeScript package is typically named 'typescript' or 'nodePackages.typescript'.
| typescript-go | |
| typescript |
|
|
||
| @pytest.fixture | ||
| def mcp_server_url(mcp_mock_server: str) -> str: | ||
| """Alias for mcp_mock_server for clearer test naming.""" | ||
| return mcp_mock_server |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fixture 'mcp_server_url' is defined but never used in the test files. This creates an unnecessary alias that duplicates the 'mcp_mock_server' fixture without adding value. Consider removing this fixture to reduce code duplication.
| @pytest.fixture | |
| def mcp_server_url(mcp_mock_server: str) -> str: | |
| """Alias for mcp_mock_server for clearer test naming.""" | |
| return mcp_mock_server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 issues found across 8 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="flake.nix">
<violation number="1" location="flake.nix:99">
P3: Misleading comment: Bun is not Node.js. Consider updating the comment to reflect that Bun (a separate JavaScript runtime) is being used, e.g., `# Bun runtime for MCP mock server`.</violation>
</file>
<file name="tests/conftest.py">
<violation number="1" location="tests/conftest.py:20">
P3: `SO_REUSEADDR` is set after `bind()`, making it ineffective. Socket options must be set before binding. Since this function just finds a free port (binding to port 0), the `SO_REUSEADDR` line is unnecessary and can be removed.</violation>
</file>
Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR
| # security | ||
| gitleaks | ||
|
|
||
| # Node.js for MCP mock server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Misleading comment: Bun is not Node.js. Consider updating the comment to reflect that Bun (a separate JavaScript runtime) is being used, e.g., # Bun runtime for MCP mock server.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At flake.nix, line 99:
<comment>Misleading comment: Bun is not Node.js. Consider updating the comment to reflect that Bun (a separate JavaScript runtime) is being used, e.g., `# Bun runtime for MCP mock server`.</comment>
<file context>
@@ -95,6 +95,11 @@
# security
gitleaks
+
+ # Node.js for MCP mock server
+ bun
+ pnpm
</file context>
| # Node.js for MCP mock server | |
| # Bun runtime for MCP mock server |
| """Find a free port on localhost.""" | ||
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||
| s.bind(("", 0)) | ||
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: SO_REUSEADDR is set after bind(), making it ineffective. Socket options must be set before binding. Since this function just finds a free port (binding to port 0), the SO_REUSEADDR line is unnecessary and can be removed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/conftest.py, line 20:
<comment>`SO_REUSEADDR` is set after `bind()`, making it ineffective. Socket options must be set before binding. Since this function just finds a free port (binding to port 0), the `SO_REUSEADDR` line is unnecessary and can be removed.</comment>
<file context>
@@ -0,0 +1,116 @@
+ """Find a free port on localhost."""
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.bind(("", 0))
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ return s.getsockname()[1]
+
</file context>
48ad92b to
006432d
Compare
Add the Node.js version of stackone-ai SDK as a submodule in vendor/stackone-ai-node. This provides access to the MCP mock server implementation for testing Python SDK's fetch_tools functionality against a real MCP protocol server.
Add Node.js tooling required to run the MCP mock server for testing: - bun: Fast JavaScript runtime used to run the mock server - pnpm: Package manager for installing Node dependencies - typescript-go: TypeScript compiler
Add pytest fixtures and Hono-based MCP mock server for testing fetch_tools against a real MCP protocol implementation: - tests/conftest.py: Session-scoped fixture that starts bun server automatically when tests require mcp_mock_server - tests/mocks/serve.ts: Standalone HTTP server importing createMcpApp from stackone-ai-node submodule, exposes /mcp and /actions/rpc The server is started once per test session and provides the same tool configurations as the Node SDK tests for consistency.
Replace monkeypatch-based tests with integration tests using the actual MCP protocol via the Hono mock server. This provides more realistic coverage of the fetch_tools() implementation. Changes: - Rename test_toolset_mcp.py to test_fetch_tools.py for clarity - Use mcp_mock_server fixture for most tests (real MCP protocol) - Keep monkeypatch tests only for schema normalisation logic - Add integration marker for MCP server tests - Add tests for MCP headers, tool creation, and RPC execution The tests now exercise the full MCP client flow including _fetch_mcp_tools(), header building, and tool response parsing.
- Add automatic pnpm install for vendor/stackone-ai-node in shellHook - Update submodule to latest commit - Fix pnpm version reference (pnpm -> pnpm_10)
006432d to
a4367cf
Compare
- Add submodules: true to CI checkout step - Fix shellHook to check for package.json instead of directory - Format tests/mocks/serve.ts with oxfmt
glebedel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Summary
What Changed
vendor/stackone-ai-nodeprovides the MCP mock server implementationpnpm installfor the submodule when neededtests/conftest.pywith session-scopedmcp_mock_serverfixturetests/mocks/serve.tsimports from Node SDK and exposes/mcpand/actions/rpctest_toolset_mcp.py→test_fetch_tools.py, now uses real MCP serverWhy
The previous tests used monkeypatch to mock
_fetch_mcp_tools, which didn't test the actual MCP protocol communication. This change provides integration tests that exercise the full flow through the MCP SDK, improving confidence in the implementation.Coverage remains at 97% with more realistic test coverage of the MCP client code paths.
Testing
All 208 tests pass (26 in test_fetch_tools.py).
Commits
chore: add stackone-ai-node as git submodulebuild(nix): add bun, pnpm, and typescript-go to devShelltest: add MCP mock server infrastructuretest(fetch_tools): rewrite tests to use real MCP mock serverbuild(nix): add shellHook for MCP mock server dependencies