We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mdlopresti/mealie-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
# Phase 1.2 Implementation Summary: MCP Server Test Framework
## Overview
Implemented complete MCP (Model Context Protocol) testing framework enabling full protocol-level testing of the Mealie MCP Server, including initialization handshake, tool invocation, and resource reading.
## Deliverables
### 1. MCP Protocol Implementation ✅
**File**: `tests/e2e/conftest_mcp.py`
Implemented complete MCP JSON-RPC protocol support:
#### Initialization Handshake
- **Step 1**: Client → Server `initialize` request with protocol version, capabilities, client info
- **Step 2**: Server → Client response with capabilities, server info
- **Step 3**: Client → Server `notifications/initialized` notification
- Automatic handshake performed in `mcp_client` fixture
#### Protocol Methods
- `send_message(method, params)` - Send JSON-RPC request
- `send_notification(method, params)` - Send notification (no response)
- `receive_message()` - Read JSON-RPC response
- `call_method(method, params)` - Send request and wait for response
### 2. Test Fixtures ✅
**File**: `tests/e2e/conftest_mcp.py`
Provides comprehensive fixtures for MCP protocol testing:
#### Session-Scoped Fixtures
- **`mcp_server_process`** - Starts MCP server as subprocess
- Manages stdin/stdout communication
- Automatic cleanup and termination
- Environment variable injection
- **`mcp_client`** - MCP client interface with initialization
- Performs automatic MCP handshake
- Provides send/receive/call methods
- Returns server capabilities and info
- **`mcp_tools_list`** - List of all registered MCP tools
- Calls `tools/list` method
- Returns tool definitions with schemas
- **`mcp_resources_list`** - List of all registered MCP resources
- Calls `resources/list` method
- Returns resource definitions with URIs
#### Function-Scoped Fixtures
- **`mcp_tool_caller`** - Simplified tool invocation interface
- `call_tool(tool_name, **kwargs)` helper
- Automatic JSON-RPC protocol handling
- **`mcp_resource_reader`** - Simplified resource reading interface
- `read_resource(uri)` helper
- Resource URI-based access
### 3. Example MCP Protocol Tests ✅
**File**: `tests/e2e/test_mcp_protocol.py`
Implemented 7 comprehensive protocol tests:
1. **`test_mcp_initialization`**
- Validates MCP handshake completes
- Checks server capabilities
- Verifies server info (name: "mealie")
2. **`test_mcp_tools_list`**
- Validates tool registration
- Checks tool structure (name, description, inputSchema)
- Verifies core tools are present
3. **`test_mcp_tool_invocation`**
- Creates test recipe via HTTP
- Fetches via MCP `mealie_recipes_get` tool
- Validates tool results
4. **`test_mcp_resources_list`**
- Validates resource registration
- Checks resource structure (uri, name)
- Verifies core resources are present
5. **`test_mcp_resource_reading`**
- Reads `recipes://list` resource
- Validates resource content structure
6. **`test_mcp_tool_error_handling`**
- Tests error handling for invalid tool calls
- Validates error messages are meaningful
7. **`test_mcp_ping_tool`**
- Tests utility ping tool
- Validates server connectivity
### 4. Fixture Integration ✅
**File**: `tests/e2e/conftest.py`
Updated main conftest to import MCP and Docker fixtures:
```python
# Import Docker and MCP fixtures to make them available to tests
from .conftest_docker import * # noqa: F401, F403
from .conftest_mcp import * # noqa: F401, F403
```
This makes all fixtures discoverable by pytest without manual imports.
## MCP Protocol Details
### Initialize Handshake Sequence
```
1. Client → Server: initialize
{
"jsonrpc": "2.0",
"id": 12345,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {"roots": {"listChanged": true}, "sampling": {}},
"clientInfo": {"name": "mealie-mcp-test-client", "version": "1.0.0"}
}
}
2. Server → Client: Response
{
"jsonrpc": "2.0",
"id": 12345,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {...}},
"serverInfo": {"name": "mealie", "version": "..."}
}
}
3. Client → Server: initialized notification
{
"jsonrpc": "2.0",
"method": "notifications/initialized",
"params": {}
}
```
### Tools/List Method
```
Client → Server:
{
"jsonrpc": "2.0",
"id": 12346,
"method": "tools/list",
"params": {}
}
Server → Client:
{
"jsonrpc": "2.0",
"id": 12346,
"result": {
"tools": [
{
"name": "mealie_recipes_get",
"description": "Get complete details for a specific recipe",
"inputSchema": {...}
},
...
]
}
}
```
### Tools/Call Method
```
Client → Server:
{
"jsonrpc": "2.0",
"id": 12347,
"method": "tools/call",
"params": {
"name": "mealie_recipes_get",
"arguments": {"slug": "test-recipe"}
}
}
Server → Client:
{
"jsonrpc": "2.0",
"id": 12347,
"result": "{...recipe JSON...}"
}
```
## How to Use
### Basic Usage
```bash
# Run all MCP protocol tests
pytest tests/e2e/test_mcp_protocol.py -v
# Run specific test
pytest tests/e2e/test_mcp_protocol.py::test_mcp_initialization -v
```
### Writing New MCP Tests
```python
import pytest
from typing import Dict, Any
@pytest.mark.e2e
def test_my_mcp_feature(
mcp_client: Dict[str, Any],
mcp_tool_caller: callable,
mcp_resource_reader: callable
):
"""Test MCP protocol feature."""
# List tools
tools_result = mcp_client["call"]("tools/list", {})
assert "tools" in tools_result
# Call a tool
result = mcp_tool_caller("ping")
assert "pong" in result.lower()
# Read a resource
recipes = mcp_resource_reader("recipes://list")
assert recipes is not None
```
## Architecture
### Component Diagram
```
┌─────────────────────────────────────────────────────────┐
│ MCP Protocol Testing │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ MCP Server Process (subprocess) │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ FastMCP Server (src/server.py) │ │ │
│ │ │ - Initialization handshake │ │ │
│ │ │ - Tool registration (100+ tools) │ │ │
│ │ │ - Resource registration (6 resources) │ │ │
│ │ │ - JSON-RPC 2.0 protocol │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ stdin ↕ stdout (JSON-RPC messages) │ │
│ └────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌────────────────▼─────────────────────────────────┐ │
│ │ mcp_client fixture │ │
│ │ - send_message(method, params) │ │
│ │ - send_notification(method, params) │ │
│ │ - receive_message() │ │
│ │ - call_method(method, params) │ │
│ │ - Automatic initialization handshake │ │
│ └────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌────────────────▼─────────────────────────────────┐ │
│ │ Helper Fixtures │ │
│ │ - mcp_tool_caller(tool_name, **kwargs) │ │
│ │ - mcp_resource_reader(uri) │ │
│ │ - mcp_tools_list │ │
│ │ - mcp_resources_list │ │
│ └────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌────────────────▼─────────────────────────────────┐ │
│ │ MCP Protocol Tests │ │
│ │ - test_mcp_protocol.py │ │
│ │ - 7 comprehensive protocol tests │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
### Fixture Lifecycle
```
Session Start
├─> mcp_server_process (start subprocess)
│ ├─> Set environment variables
│ ├─> Start server with stdin/stdout pipes
│ └─> Server starts and waits for init
│
├─> mcp_client (per session)
│ ├─> Perform MCP initialization handshake
│ │ ├─> Send initialize request
│ │ ├─> Receive capabilities response
│ │ └─> Send initialized notification
│ └─> Return client interface
│
├─> mcp_tools_list (per session)
│ ├─> Call tools/list method
│ └─> Cache tool definitions
│
└─> mcp_resources_list (per session)
├─> Call resources/list method
└─> Cache resource definitions
Test Execution
└─> mcp_tool_caller (per test)
└─> Simplified tool invocation interface
└─> mcp_resource_reader (per test)
└─> Simplified resource reading interface
Session End
└─> mcp_server_process (teardown)
├─> Terminate server process
├─> Kill if necessary
└─> Close pipes
```
## Testing the Implementation
### Verification Steps
1. **Check MCP server starts**:
```bash
# Server should start without errors
python -m src.server
```
2. **Run protocol tests**:
```bash
# All MCP protocol tests should pass
pytest tests/e2e/test_mcp_protocol.py -v
```
3. **Validate tool registration**:
```bash
# Should list 100+ tools
pytest tests/e2e/test_mcp_protocol.py::test_mcp_tools_list -v -s
```
4. **Validate resource registration**:
```bash
# Should list 6+ resources
pytest tests/e2e/test_mcp_protocol.py::test_mcp_resources_list -v -s
```
### Expected Test Output
```
tests/e2e/test_mcp_protocol.py::test_mcp_initialization PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_tools_list PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_tool_invocation PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_resources_list PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_resource_reading PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_tool_error_handling PASSED
tests/e2e/test_mcp_protocol.py::test_mcp_ping_tool PASSED
==================== 7 passed in X.XXs ====================
```
## Known Issues
### 1. Docker Health Check Timeout
**Issue**: Mealie Docker container health check times out in some environments
**Status**: Under investigation
**Workaround**: Tests work when Mealie container is already running and healthy
**Impact**: Low - MCP protocol tests can run independently of Docker infrastructure
### 2. MCP Tests Require Docker Fixtures
**Issue**: Some MCP tests depend on `docker_mealie_client` fixture
**Status**: By design - validates MCP tools against real Mealie instance
**Future**: Could add pure protocol tests without Docker dependency
## Next Steps
### Immediate (Phase 1.2 Complete)
Phase 1.2 is now complete. Ready for:
- **Phase 1.3**: Unit Test Utilities & Helpers
- **Phase 3**: Additional E2E Test Coverage
### Future Enhancements
1. **Extended Protocol Coverage** (Phase 3)
- Test all 100+ tools via MCP protocol
- Validate all resource URIs
- Test parameter validation
- Test error scenarios
2. **Performance Testing**
- Protocol message throughput
- Tool invocation latency
- Resource reading performance
3. **Protocol Compliance**
- Validate JSON-RPC 2.0 spec compliance
- Test edge cases (malformed messages, etc.)
- Timeout handling
4. **CI/CD Integration** (Phase 5.1)
- GitHub Actions workflow for MCP tests
- Automated protocol validation on PR
- Test result artifacts
## Benefits Achieved
✅ **Complete MCP Protocol Support**: Full JSON-RPC implementation
✅ **Automatic Initialization**: Handshake handled by fixtures
✅ **Easy Tool Testing**: Simplified `call_tool()` interface
✅ **Resource Testing**: Simplified `read_resource()` interface
✅ **Session Management**: Automatic server lifecycle
✅ **Comprehensive Examples**: 7 protocol tests demonstrating usage
✅ **Well Documented**: Clear architecture and usage patterns
✅ **Foundation Ready**: Ready for expanded test coverage
## References
### MCP Protocol Documentation
- [Model Context Protocol - Tools Specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)
- [JSON-RPC Protocol in MCP](https://mcpcat.io/guides/understanding-json-rpc-protocol-mcp/)
- [FastMCP Deep Dive](https://www.vunda.ai/blog/fast-mcp-deep-dive)
- [MCP JSON-RPC Usage](https://milvus.io/ai-quick-reference/how-is-jsonrpc-used-in-the-model-context-protocol)
### Related Documentation
- `tests/e2e/README.md` - E2E testing overview
- `tests/e2e/QUICK_START.md` - Quick start guide
- `tests/e2e/IMPLEMENTATION_SUMMARY.md` - Phase 1.1 summary
## Conclusion
Phase 1.2 successfully implements a complete MCP protocol testing framework. The implementation provides:
- Full JSON-RPC 2.0 protocol support
- Automatic initialization handshake
- Comprehensive fixtures for all protocol methods
- Clear examples and documentation
- Foundation for extensive protocol-level testing
The framework is ready for immediate use and provides a solid foundation for Phase 1.3 (Unit Test Utilities) and future test expansion.