Skip to main content
Glama
test_server.py9.18 kB
from __future__ import annotations from enum import Enum import pytest import pytest_asyncio from django.conf import settings from django.test import override_settings from fastmcp import Client from mcp_django.server import mcp pytestmark = pytest.mark.asyncio class Tool(str, Enum): SHELL = "shell" LIST_ROUTES = "project_list_routes" @pytest_asyncio.fixture(autouse=True) async def initialize_and_clear(): await mcp.initialize() async with Client(mcp.server) as client: await client.call_tool("shell_clear_history") async def test_instructions_exist(): instructions = mcp.server.instructions assert instructions is not None assert len(instructions) > 100 assert "Django ecosystem" in instructions assert "## Available Toolsets" in instructions assert "### Shell" in instructions assert "### djangopackages.org" in instructions async def test_tool_listing(): async with Client(mcp.server) as client: tools = await client.list_tools() tool_names = [tool.name for tool in tools] for tool_name in [ "djangopackages_get_grid", "djangopackages_get_package", "djangopackages_search", "management_execute_command", "management_list_commands", "project_get_project_info", "project_list_apps", "project_list_models", "project_list_routes", "project_get_setting", "shell_execute", "shell_clear_history", "shell_export_history", ]: assert tool_name in tool_names async def test_get_apps_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/apps") assert result is not None assert len(result) > 0 async def test_get_models_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/models") assert result is not None assert len(result) > 0 async def test_get_project_info_tool(): async with Client(mcp.server) as client: result = await client.call_tool("project_get_project_info", {}) assert result.data is not None assert hasattr(result.data, "python") assert hasattr(result.data, "django") assert result.data.python is not None assert result.data.django is not None assert result.data.django.version is not None @override_settings( INSTALLED_APPS=settings.INSTALLED_APPS + [ "django.contrib.auth", "django.contrib.contenttypes", ] ) async def test_get_project_info_tool_with_auth(): async with Client(mcp.server) as client: result = await client.call_tool("project_get_project_info", {}) assert result.data is not None assert result.data.django.auth_user_model is not None async def test_list_routes_tool_returns_routes(): async with Client(mcp.server) as client: result = await client.call_tool("project_list_routes", {}) assert isinstance(result.data, list) assert len(result.data) > 0 async def test_list_routes_tool_with_filters(): async with Client(mcp.server) as client: all_routes = await client.call_tool("project_list_routes", {}) get_routes = await client.call_tool("project_list_routes", {"method": "GET"}) assert len(get_routes.data) > 0 assert len(get_routes.data) <= len(all_routes.data) if all_routes.data: pattern_routes = await client.call_tool( "project_list_routes", {"pattern": all_routes.data[0]["pattern"][:3]} ) assert isinstance(pattern_routes.data, list) async def test_list_apps_tool(): async with Client(mcp.server) as client: result = await client.call_tool("project_list_apps", {}) assert isinstance(result.data, list) assert len(result.data) > 0 # Should have at least the 'tests' app app_labels = [app["label"] for app in result.data] assert "tests" in app_labels async def test_list_models_tool(): async with Client(mcp.server) as client: result = await client.call_tool("project_list_models", {}) assert isinstance(result.data, list) assert len(result.data) > 0 # Should have at least AModel from tests model_names = [model["model_class"] for model in result.data] assert "AModel" in model_names async def test_list_models_with_scope_project(): async with Client(mcp.server) as client: result = await client.call_tool("project_list_models", {"scope": "project"}) assert isinstance(result.data, list) assert len(result.data) > 0 # Should have project models, e.g. our test models model_names = [model["model_class"] for model in result.data] assert "AModel" in model_names # Should NOT have Django models (they're in site-packages) # This test might be limited if Django apps aren't installed assert "User" not in model_names or "auth" not in model_names @override_settings( INSTALLED_APPS=settings.INSTALLED_APPS + [ "django.contrib.auth", "django.contrib.contenttypes", ] ) async def test_list_models_with_scope_all(): """Test that scope='all' returns all models including Django contrib.""" async with Client(mcp.server) as client: result = await client.call_tool("project_list_models", {"scope": "all"}) assert isinstance(result.data, list) assert len(result.data) > 0 model_names = [model["model_class"] for model in result.data] assert "AModel" in model_names assert "User" in model_names assert "ContentType" in model_names @override_settings( INSTALLED_APPS=settings.INSTALLED_APPS + [ "django.contrib.auth", "django.contrib.contenttypes", ] ) async def test_list_models_with_include(): """Test that include parameter filters to specific apps.""" async with Client(mcp.server) as client: result = await client.call_tool( "project_list_models", {"include": ["auth", "tests"]} ) assert isinstance(result.data, list) assert len(result.data) > 0 model_names = [model["model_class"] for model in result.data] app_labels = [model["import_path"].split(".")[0] for model in result.data] # should include auth and tests models assert "AModel" in model_names assert "User" in model_names # should not have anything else, e.g. from the contenttypes app assert "ContentType" not in model_names for label in app_labels: assert label in ["tests", "django"], f"Unexpected app: {label}" @override_settings( INSTALLED_APPS=settings.INSTALLED_APPS + [ "django.contrib.auth", "django.contrib.contenttypes", ] ) async def test_list_models_include_overrides_scope(): async with Client(mcp.server) as client: # Even with scope='project', include should override result = await client.call_tool( "project_list_models", {"include": ["auth"], "scope": "project"} ) assert isinstance(result.data, list) assert len(result.data) > 0 model_names = [model["model_class"] for model in result.data] # Should ONLY have auth models (include overrides scope) assert "User" in model_names assert "Group" in model_names # Should NOT have project models despite scope='project' assert "AModel" not in model_names async def test_get_setting_tool(): async with Client(mcp.server) as client: result = await client.call_tool("project_get_setting", {"key": "DEBUG"}) assert result.data is not None assert result.data.key == "DEBUG" assert result.data.value_type == "bool" assert isinstance(result.data.value, bool) async def test_get_app_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/app/tests") assert result is not None assert len(result) > 0 async def test_get_app_models_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/app/tests/models") assert result is not None assert len(result) > 0 async def test_get_model_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/model/tests/AModel") assert result is not None assert len(result) > 0 async def test_get_route_by_pattern_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/route/home") assert result is not None assert len(result) > 0 async def test_get_setting_resource(): async with Client(mcp.server) as client: result = await client.read_resource("django://project/setting/DEBUG") assert result is not None assert len(result) > 0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/joshuadavidthomas/mcp-django'

If you have feedback or need assistance with the MCP directory API, please join our Discord server