|
| 1 | +## Testing and Debugging |
| 2 | + |
| 3 | +Before you begin testing your MCP server, it's important to understand the available tools and best practices for debugging. Effective testing ensures your server behaves as expected and helps you quickly identify and resolve issues. The following section outlines recommended approaches for validating your MCP implementation. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This lesson covers how to select the right testing approach and the most effective testing tool. |
| 8 | + |
| 9 | +## Learning Objectives |
| 10 | + |
| 11 | +By the end of this lesson, you will be able to: |
| 12 | + |
| 13 | +- Describe various approaches for testing. |
| 14 | +- Use different tools to effectively test your code. |
| 15 | + |
| 16 | + |
| 17 | +## Testing MCP Servers |
| 18 | + |
| 19 | +MCP provides tools to help you test and debug your servers: |
| 20 | + |
| 21 | +- **MCP Inspector**: A command line tool that can be run both as a CLI tool and as a visual tool. |
| 22 | +- **Manual testing**: You can use a tool like curl to run web requests, but any tool capabable of running HTTP will do. |
| 23 | +- **Unit testing**: It's possible to use your preferred testing framework to test the features of both server and client. |
| 24 | + |
| 25 | +### Using MCP Inspector |
| 26 | + |
| 27 | +We've describes the usage of this tool in previous lessons but let's talk about it a bit at high level. It's a tool built in Node.js and you can use it by calling the `npx` executable which will download and install the tool itself temporarily and will clean itself up once it's done running your request. |
| 28 | + |
| 29 | +The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) helps you: |
| 30 | + |
| 31 | +- **Discover Server Capabilities**: Automatically detect available resources, tools, and prompts |
| 32 | +- **Test Tool Execution**: Try different parameters and see responses in real-time |
| 33 | +- **View Server Metadata**: Examine server info, schemas, and configurations |
| 34 | + |
| 35 | +A typical run of the tool looks like so: |
| 36 | + |
| 37 | +```bash |
| 38 | +npx @modelcontextprotocol/inspector node build/index.js |
| 39 | +``` |
| 40 | + |
| 41 | +The above command starts an MCP and its visual interface and launches a local web interface in your browser. You can expect to see a dashboard displaying your registered MCP servers, their available tools, resources, and prompts. The interface allows you to interactively test tool execution, inspect server metadata, and view real-time responses, making it easier to validate and debug your MCP server implementations. |
| 42 | + |
| 43 | +Here's what it can look like:  |
| 44 | + |
| 45 | +You can also run this tool in CLI mode in which case you add `--cli` attribute. Here's an example of running the tool in "CLI" mode which lists all the tools on the server: |
| 46 | + |
| 47 | +```sh |
| 48 | +npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list |
| 49 | +``` |
| 50 | + |
| 51 | +### Manual Testing |
| 52 | + |
| 53 | +Apart from running the inspector tool to test server capabilities, another similar approach is to run a client capable of using HTTP lik for example curl. |
| 54 | + |
| 55 | +With curl, you can test MCP servers directly using HTTP requests: |
| 56 | + |
| 57 | +```bash |
| 58 | +# Example: Test server metadata |
| 59 | +curl http://localhost:3000/v1/metadata |
| 60 | + |
| 61 | +# Example: Execute a tool |
| 62 | +curl -X POST http://localhost:3000/v1/tools/execute \ |
| 63 | + -H "Content-Type: application/json" \ |
| 64 | + -d '{"name": "calculator", "parameters": {"expression": "2+2"}}' |
| 65 | +``` |
| 66 | + |
| 67 | +As you can see from above usage of curl, you use a POST request to invoke a tool using a payload consisting of the tools name and its parameters. Use the approach that fits you best. CLI tools in general tends to be faster to use and lends themselves to be scripted which can be useful in a CI/CD environment. |
| 68 | + |
| 69 | +### Unit Testing |
| 70 | + |
| 71 | +Create unit tests for your tools and resources to ensure they work as expected. Here's some example testing code. |
| 72 | + |
| 73 | +```python |
| 74 | +import pytest |
| 75 | + |
| 76 | +from mcp.server.fastmcp import FastMCP |
| 77 | +from mcp.shared.memory import ( |
| 78 | + create_connected_server_and_client_session as create_session, |
| 79 | +) |
| 80 | + |
| 81 | +# Mark the whole module for async tests |
| 82 | +pytestmark = pytest.mark.anyio |
| 83 | + |
| 84 | + |
| 85 | +async def test_list_tools_cursor_parameter(): |
| 86 | + """Test that the cursor parameter is accepted for list_tools. |
| 87 | +
|
| 88 | + Note: FastMCP doesn't currently implement pagination, so this test |
| 89 | + only verifies that the cursor parameter is accepted by the client. |
| 90 | + """ |
| 91 | + |
| 92 | + server = FastMCP("test") |
| 93 | + |
| 94 | + # Create a couple of test tools |
| 95 | + @server.tool(name="test_tool_1") |
| 96 | + async def test_tool_1() -> str: |
| 97 | + """First test tool""" |
| 98 | + return "Result 1" |
| 99 | + |
| 100 | + @server.tool(name="test_tool_2") |
| 101 | + async def test_tool_2() -> str: |
| 102 | + """Second test tool""" |
| 103 | + return "Result 2" |
| 104 | + |
| 105 | + async with create_session(server._mcp_server) as client_session: |
| 106 | + # Test without cursor parameter (omitted) |
| 107 | + result1 = await client_session.list_tools() |
| 108 | + assert len(result1.tools) == 2 |
| 109 | + |
| 110 | + # Test with cursor=None |
| 111 | + result2 = await client_session.list_tools(cursor=None) |
| 112 | + assert len(result2.tools) == 2 |
| 113 | + |
| 114 | + # Test with cursor as string |
| 115 | + result3 = await client_session.list_tools(cursor="some_cursor_value") |
| 116 | + assert len(result3.tools) == 2 |
| 117 | + |
| 118 | + # Test with empty string cursor |
| 119 | + result4 = await client_session.list_tools(cursor="") |
| 120 | + assert len(result4.tools) == 2 |
| 121 | + |
| 122 | +``` |
| 123 | + |
| 124 | +The preceding code does the following: |
| 125 | + |
| 126 | +- Leverages pytest framework which lets you create tests as functions and use assert statements. |
| 127 | +- Creates an MCP Server with two different tools. |
| 128 | +- Uses `assert` statement to check that certain conditions are fulfilled. |
| 129 | + |
| 130 | +Have a look at the [full file here](https://github.com/modelcontextprotocol/python-sdk/blob/main/tests/client/test_list_methods_cursor.py) |
| 131 | + |
| 132 | +Given the above file, you can test your own server to ensure capabilities are created as they should. |
| 133 | + |
| 134 | +All major SDKs have similar testing sections so you can adjust to your chosen runtime. |
| 135 | + |
| 136 | +## Samples |
| 137 | + |
| 138 | +- [Java Calculator](../samples/java/calculator/README.md) |
| 139 | +- [.Net Calculator](../samples/csharp/) |
| 140 | +- [JavaScript Calculator](../samples/javascript/README.md) |
| 141 | +- [TypeScript Calculator](../samples/typescript/README.md) |
| 142 | +- [Python Calculator](../samples/python/) |
| 143 | + |
| 144 | +## Additional Resources |
| 145 | + |
| 146 | +- [Python SDK](https://github.com/modelcontextprotocol/python-sdk) |
| 147 | + |
| 148 | +## What's Next |
| 149 | + |
| 150 | +- Next: [Deployment](/03-GettingStarted/08-deployment/README.md) |
0 commit comments