Production MCP Systems

Testing and Best Practices

5 min read

Comprehensive testing ensures your MCP server works correctly in all scenarios.

Test Categories

TypePurposeTools
UnitTest individual functionspytest
IntegrationTest components togetherpytest-asyncio
E2EFull system testsMCP Inspector

Unit Testing Tools

import pytest
from unittest.mock import AsyncMock, patch

from server import WeatherTool

class TestWeatherTool:
    def test_get_definition(self):
        tool = WeatherTool()
        definition = tool.get_tool_definition()

        assert definition["name"] == "get_weather"
        assert "city" in definition["inputSchema"]["properties"]

    def test_validate_valid_input(self):
        tool = WeatherTool()
        assert tool.validate({"city": "London"}) == True

    def test_validate_empty_city(self):
        tool = WeatherTool()
        with pytest.raises(ValueError, match="City is required"):
            tool.validate({"city": ""})

    @pytest.mark.asyncio
    async def test_execute(self):
        tool = WeatherTool()
        result = await tool.execute({"city": "London"})

        assert "temperature" in result
        assert "condition" in result

Integration Testing

import pytest
from httpx import AsyncClient
from server import app

@pytest.fixture
async def client():
    async with AsyncClient(app=app, base_url="http://test") as ac:
        yield ac

@pytest.mark.asyncio
async def test_mcp_endpoint(client):
    response = await client.post("/mcp", json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/list"
    })

    assert response.status_code == 200
    data = response.json()
    assert "tools" in data

@pytest.mark.asyncio
async def test_tool_call(client):
    response = await client.post("/mcp", json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "get_weather",
            "arguments": {"city": "Tokyo"}
        }
    })

    assert response.status_code == 200
    assert response.json()["result"]

Mocking External Services

@pytest.mark.asyncio
async def test_weather_api_failure():
    with patch("server.fetch_weather", new_callable=AsyncMock) as mock:
        mock.side_effect = Exception("API unavailable")

        tool = WeatherTool()
        with pytest.raises(McpError) as exc:
            await tool.execute({"city": "London"})

        assert "unavailable" in str(exc.value)

Best Practices Summary

PracticeBenefit
Use environment variablesSecurity, flexibility
Implement health checksReliability monitoring
Add request timeoutsPrevent hanging
Log structured dataEasy debugging
Version your APIBackwards compatibility
Document tools clearlyBetter AI usage
Test edge casesRobust handling

Production Checklist

  • All secrets in environment variables
  • Health check endpoint implemented
  • Prometheus metrics exposed
  • Structured logging configured
  • Rate limiting enabled
  • CORS properly configured
  • SSL/TLS enabled
  • Error handling comprehensive
  • Tests passing in CI/CD

Congratulations! You've completed the MCP Mastery course. :::

Quiz

Module 5 Quiz: Production MCP Systems

Take Quiz
Was this lesson helpful?

Sign in to rate

FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.