Skip to main content
This guide covers testing strategies for MCP servers, including local development testing, using the MCP Inspector tool, and running automated tests.

Testing with a Local Development MCP Server

You can modify the settings of your MCP client to run your local server. Open your client json settings file and update it as needed. Example configuration:
{
  "mcpServers": {
    "oracle-oci-api-mcp-server": {
      "type": "stdio",
      "command": "uv",
      "args": [
        "run",
        "oracle.oci-api-mcp-server"
      ],
      "env": {
        "VIRTUAL_ENV": "<path to your cloned repo>/oci-mcp/.venv",
        "FASTMCP_LOG_LEVEL": "ERROR"
      }
    }
  }
}
Replace <path to your cloned repo> with the absolute path to your cloned repository, for example /Users/myuser/dev/oci-mcp.

Testing HTTP Transport Mode

To build and test servers running in HTTP transport mode:
make build
make install
Then start the server:
VIRTUAL_ENV=$(pwd)/.venv ORACLE_MCP_HOST=127.0.0.1 ORACLE_MCP_PORT=8888 uv run oracle.oci-api-mcp-server
Configure your MCP client to connect to the HTTP endpoint:
{
  "mcpServers": {
    "oracle-oci-api-mcp-server": {
      "type": "streamableHttp",
      "url": "http://127.0.0.1:8888/mcp"
    }
  }
}
The type attribute differs across MCP clients; some use http as the transport value while others (like Cline) expect streamableHttp.

Using the MCP Inspector

The Model Context Protocol (MCP) provides Inspector, a developer tool for testing and debugging MCP servers.

What is Inspector?

Inspector is an interactive debugging interface that allows you to:
  • Test MCP tools and resources
  • Inspect server capabilities
  • Debug request/response cycles
  • Validate server behavior
More information on Inspector can be found in the MCP documentation.

Running Inspector

The Inspector runs directly through npx without requiring installation. To inspect your locally developed server:
npx @modelcontextprotocol/inspector \
  uv \
  --directory <absolute path to your server code> \
  run \
  server.py
Example:
npx @modelcontextprotocol/inspector \
  uv \
  --directory /Users/myuser/dev/oci-mcp/src/oci-compute-mcp-server/oracle/oci_compute_mcp_server \
  run \
  server.py
Inspector will run your server on localhost (for instance: http://127.0.0.1:6274) which should automatically open the tool for debugging and development.

Running Automated Tests

Linting

Run linting checks across all servers:
make lint
This uses ruff to check code quality and style across all Python MCP servers.

Unit Tests

Run the full test suite:
make test
This command:
  1. Runs pytest in each server directory
  2. Collects code coverage data
  3. Generates coverage reports (HTML and terminal)
  4. Combines coverage across all servers
  5. Fails if coverage is below 69%

Test Output

The test command generates:
  • Terminal output: Shows test results and coverage summary
  • HTML coverage report: Available in htmlcov/index.html
  • Coverage data files: Individual .coverage.* files per server

Running Tests for a Specific Server

To test a single server:
cd src/oci-compute-mcp-server
uv run pytest --cov=. --cov-branch --cov-report=html --cov-report=term-missing

End-to-End Tests

Run end-to-end tests using Behave:
make e2e-tests
This command:
  1. Builds all servers (make build)
  2. Installs all servers (make install)
  3. Runs Behave tests from tests/e2e/features

Test Requirements

Test dependencies are defined in each server’s pyproject.toml:
[dependency-groups]
dev = [
    "pytest>=8.4.2",
    "pytest-asyncio>=1.2.0",
    "pytest-cov>=7.0.0",
]
These are installed automatically when you run uv sync or use the development commands.

Coverage Configuration

Coverage settings are defined in pyproject.toml:
[tool.coverage.run]
omit = [
    "**/__init__.py",
    "**/tests/*",
    "dist/*",
    ".venv/*",
]

[tool.coverage.report]
omit = [
    "**/__init__.py",
    "**/tests/*",
]
precision = 2
fail_under = 90
Individual servers should maintain at least 90% code coverage.

Writing Tests

When writing tests:
  1. Test file location: Place tests in oracle/<server_name>/tests/
  2. Test file naming: Use test_*.py pattern
  3. Test function naming: Use test_* pattern
  4. Use fixtures: Leverage pytest fixtures for common setup
  5. Mock external calls: Mock OCI API calls to avoid requiring live credentials
  6. Test error cases: Include tests for error handling and edge cases
Example test structure:
import pytest
from unittest.mock import Mock, patch

class TestListInstances:
    @patch('oracle.oci_compute_mcp_server.server.get_compute_client')
    def test_list_instances_success(self, mock_client):
        # Arrange
        mock_client.return_value.list_instances.return_value = Mock(
            data=[...],
            has_next_page=False
        )
        
        # Act
        result = list_instances(compartment_id="ocid1.compartment...")
        
        # Assert
        assert len(result) > 0
    
    def test_list_instances_invalid_compartment(self):
        # Test error handling
        with pytest.raises(Exception):
            list_instances(compartment_id="invalid")

Build docs developers (and LLMs) love