Files
javis_bot/tests/test_mcp_integration.py
javis-bot c4abf63f38
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
Add Discord-native hybrid front-end for Jarvis (bot + bridge)
Transform isair/jarvis into a Discord-controlled voice assistant running on
the Ubuntu VNC desktop, keeping the mature ~39k-line Python brain intact.

- bot/ (Node + bun, discord.js): /자비스 slash commands (ephemeral),
  voice channel join + voice receive/playback, pluggable VNC screen broadcast
  (selfbot live / noVNC / screenshot)
- bridge/ (Python, Flask): wraps jarvis STT + run_reply_engine + Piper TTS
  behind a thin localhost HTTP API
- .env.example, scripts/ (start_bridge/start_bot/dev), README rewrite,
  docs/language-comparison.md and docs/vnc-xfce-setup.md

Language decision: hybrid (Python brain + Node/bun Discord layer) because
Discord blocks bot video; native screen broadcast only works via a Node
selfbot library.
2026-06-09 14:51:05 +09:00

123 lines
4.0 KiB
Python

"""
Integration tests for MCP tools in the reply engine.
These tests require more complex setup and may not run in basic CI environments.
They can be run locally or in development environments with git hooks.
"""
import pytest
from unittest.mock import Mock, patch
@pytest.mark.integration
def test_mcp_tools_integrated_with_reply_engine():
"""Test that MCP tools are properly integrated with the reply engine's tool discovery."""
from jarvis.tools.registry import discover_mcp_tools, generate_tools_description, BUILTIN_TOOLS
# Mock MCP client
class FakeMCPClient:
def __init__(self, config):
pass
def list_tools(self, server_name):
if server_name == "test-server":
return [
{"name": "tool1", "description": "Test tool 1"},
{"name": "tool2", "description": "Test tool 2"}
]
return []
with patch('jarvis.tools.registry.MCPClient', FakeMCPClient):
# Test discovery
mcps_config = {"test-server": {"command": "fake"}}
mcp_tools, _errors = discover_mcp_tools(mcps_config)
# Test tool registration (simulate what reply engine does)
allowed_tools = list(BUILTIN_TOOLS.keys())
for mcp_tool_name in mcp_tools.keys():
if mcp_tool_name not in allowed_tools:
allowed_tools.append(mcp_tool_name)
# Test tool descriptions include MCP tools
description = generate_tools_description(allowed_tools, mcp_tools)
# Assertions
assert "test-server__tool1" in allowed_tools
assert "test-server__tool2" in allowed_tools
assert "test-server__tool1" in description
assert "test-server__tool2" in description
@pytest.mark.integration
def test_mcp_tool_execution_in_context():
"""Test MCP tool execution with proper context and error handling."""
from jarvis.tools.registry import run_tool_with_retries, ToolExecutionResult
class MockDB:
pass
class MockConfig:
def __init__(self):
self.mcps = {"test-server": {"command": "fake"}}
self.voice_debug = False
# Mock successful execution
class FakeMCPClient:
def __init__(self, config):
pass
def invoke_tool(self, server_name, tool_name, arguments):
return {"text": f"Executed {tool_name} on {server_name}", "isError": False}
with patch('jarvis.tools.registry.MCPClient', FakeMCPClient):
result = run_tool_with_retries(
db=MockDB(),
cfg=MockConfig(),
tool_name="test-server__example_tool",
tool_args={"param": "value"},
system_prompt="test",
original_prompt="test",
redacted_text="test",
max_retries=0
)
assert result.success is True
assert "Executed example_tool on test-server" in result.reply_text
@pytest.mark.integration
def test_mcp_error_handling_in_context():
"""Test that MCP errors are properly handled in execution context."""
from jarvis.tools.registry import run_tool_with_retries
class MockDB:
pass
class MockConfig:
def __init__(self):
self.mcps = {"test-server": {"command": "fake"}}
self.voice_debug = False
# Mock failing execution
class FailingMCPClient:
def __init__(self, config):
pass
def invoke_tool(self, server_name, tool_name, arguments):
return {"text": "Tool failed", "isError": True}
with patch('jarvis.tools.registry.MCPClient', FailingMCPClient):
result = run_tool_with_retries(
db=MockDB(),
cfg=MockConfig(),
tool_name="test-server__failing_tool",
tool_args={},
system_prompt="test",
original_prompt="test",
redacted_text="test",
max_retries=0
)
assert result.success is False
assert result.error_message == "Tool failed"