Initial DocsMCP stack

This commit is contained in:
george
2026-06-05 23:02:55 +01:00
commit 421b6f973a
51 changed files with 7414 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
"""
Tests for mcp-server/server.py
These are pure unit tests that don't require any external dependencies.
They test:
- The strip_local_prefix() function directly (no network)
- MCP server tool definitions and structure
"""
import pytest
class TestStripLocalPrefix:
"""Tests for the strip_local_prefix() function."""
def test_strips_prefix_from_full_id(self):
"""Should strip /local/ prefix from full library ID."""
from mcp_server.server import strip_local_prefix
input_id = "/local/foundryvtt"
expected_output = "foundryvtt"
result = strip_local_prefix(input_id)
assert result == expected_output
def test_preserves_id_without_prefix(self):
"""Should preserve ID that doesn't have /local/ prefix."""
from mcp_server.server import strip_local_prefix
input_id = "foundryvtt"
result = strip_local_prefix(input_id)
assert result == input_id # Should be unchanged
def test_strips_from_multiple_local_prefixes(self):
"""Should handle edge case of multiple prefixes."""
from mcp_server.server import strip_local_prefix
input_id = "/local//local/foundryvtt"
result = strip_local_prefix(input_id)
# Should only strip first occurrence
assert result == "/local/foundryvtt"
def test_empty_string(self):
"""Empty string should remain empty."""
from mcp_server.server import strip_local_prefix
input_id = ""
result = strip_local_prefix(input_id)
assert result == input_id # Should be unchanged
def test_whitespace_only(self):
"""Whitespace only should remain whitespace (no /local/ to strip)."""
from mcp_server.server import strip_local_prefix
input_id = " \t\n"
result = strip_local_prefix(input_id)
assert result == input_id
def test_case_sensitive_prefix(self):
"""Prefix matching is case-sensitive."""
from mcp_server.server import strip_local_prefix
# Lowercase - should strip
result1 = strip_local_prefix("/local/test")
assert result1 == "test"
# Uppercase - should NOT strip (not a match)
result2 = strip_local_prefix("/LOCAL/test")
assert result2 == "/LOCAL/test" # Unchanged
def test_partial_match_does_not_strip(self):
"""Only exact /local/ prefix is stripped, not partial matches."""
from mcp_server.server import strip_local_prefix
# Partial match - should NOT strip
input_id = "/local-docs/test"
result = strip_local_prefix(input_id)
assert result == input_id # Unchanged
# Different separator - should NOT strip
input_id2 = "/localdocs/test"
result2 = strip_local_prefix(input_id2)
assert result2 == input_id2
def test_prefix_with_trailing_slash(self):
"""Should handle trailing slash in ID."""
from mcp_server.server import strip_local_prefix
input_id = "/local/foundryvtt/"
expected_output = "foundryvtt/"
result = strip_local_prefix(input_id)
assert result == expected_output
class TestMcpServerStructure:
"""Tests for MCP server tool structure (without starting the server)."""
def test_import_fastmcp(self):
"""Should be able to import FastMCP."""
try:
from fastmcp import FastMCP
# Import successful
except ImportError as e:
pytest.skip(f"fastmcp not installed: {e}")
class TestMcpServerToolsExistence:
"""Tests to verify MCP server has expected tools defined."""
def test_mcp_instance_created(self):
"""MCP instance should be created with tools."""
from mcp_server.server import mcp
assert mcp is not None
def test_resolve_library_id_tool_exists(self):
"""resolve-library-id tool should be registered."""
from mcp_server.server import mcp
# Check if the tool exists by trying to access it
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "resolve_library_id" in tool_names
def test_get_library_docs_tool_exists(self):
"""get-library-docs tool should be registered."""
from mcp_server.server import mcp
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "get_library_docs" in tool_names
def test_list_libraries_tool_exists(self):
"""list-libraries tool should be registered."""
from mcp_server.server import mcp
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "list_libraries" in tool_names
def test_search_docs_tool_exists(self):
"""search-docs tool should be registered."""
from mcp_server.server import mcp
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "search_docs" in tool_names
def test_refresh_library_tool_exists(self):
"""refresh-library tool should be registered."""
from mcp_server.server import mcp
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "refresh_library" in tool_names
def test_sync_sources_tool_exists(self):
"""sync-sources tool should be registered."""
from mcp_server.server import mcp
if hasattr(mcp, 'tools'):
tool_names = [t.name for t in mcp.tools]
assert "sync_sources" in tool_names
class TestMcpServerStripPrefixIntegration:
"""Integration tests for strip_prefix usage in MCP server functions."""
def test_resolve_library_id_calls_strip_prefix(self):
"""resolve_library_id should handle /local/ prefix in responses."""
# This test verifies that the tool is available and uses the prefix correctly
from mcp_server.server import strip_local_prefix
# Verify the function exists and works
assert callable(strip_local_prefix)
# Test with sample IDs
test_ids = [
"/local/foundryvtt",
"/local/pytest",
"/local/mydocs/reference",
]
for lib_id in test_ids:
stripped = strip_local_prefix(lib_id)
assert not stripped.startswith("/local/")
class TestMcpServerPrefixHandlingVariations:
"""Additional tests for prefix handling variations."""
def test_long_library_id(self):
"""Should handle long library IDs with /local/ prefix."""
from mcp_server.server import strip_local_prefix
input_id = "/local/very-long-library-id-with-many-chars-in-name"
expected_output = "very-long-library-id-with-many-chars-in-name"
result = strip_local_prefix(input_id)
assert result == expected_output
def test_special_characters_in_id(self):
"""Should handle special characters in library ID."""
from mcp_server.server import strip_local_prefix
# IDs can have underscores, dashes, numbers
input_id = "/local/my-doc_v2-3_test"
result = strip_local_prefix(input_id)
assert result == "my-doc_v2-3_test"
def test_unicode_in_stripped_name(self):
"""Stripped name should preserve unicode characters."""
from mcp_server.server import strip_local_prefix
# Library IDs sometimes have unicode in them
input_id = "/local/世界文档" # Chinese characters
result = strip_local_prefix(input_id)
assert result == "世界文档"
def test_mixed_case_stripped_name(self):
"""Stripped name can have mixed case."""
from mcp_server.server import strip_local_prefix
input_id = "/local/FoundryVTT"
result = strip_local_prefix(input_id)
assert result == "FoundryVTT"
# =============================================================================
# FIXTURES
# =============================================================================
@pytest.fixture
def sample_library_ids():
"""Sample library IDs for testing prefix stripping."""
return [
"/local/foundryvtt",
"/local/pytest",
"/local/mydocs/reference/guide.md",
"/local/my-app",
"/local/documentation/tutorial/getting-started",
]
@pytest.fixture
def expected_stripped_ids(sample_library_ids):
"""Expected stripped versions of sample library IDs."""
return [
"foundryvtt",
"pytest",
"mydocs/reference/guide.md",
"my-app",
"documentation/tutorial/getting-started",
]