Krep MCP Server
by bmorphism
Verified
# MCP Protocol Compliance Guidelines
This document provides guidelines for ensuring proper compliance with the Model Context Protocol (MCP) when implemented in JavaScript-based tools. These guidelines are based on lessons learned while fixing compatibility issues between the `krep-mcp-server` and Claude Desktop/MCP Inspector.
## Common Issues and Solutions
### 1. JSON-RPC Message Formatting
The MCP protocol requires strict adherence to the JSON-RPC message format:
- **Content-Length Header**: Must be in the exact format `Content-Length: N\r\n\r\n` with precisely two carriage return + newline sequences.
- **No Extra Spaces**: There should be no extraneous spaces or characters in the header.
- **Buffer Handling**: Be careful with encodings - always use Buffer.from/toString with 'utf8' explicitly specified.
Solution:
```javascript
// Use this exact format for the header
const header = `Content-Length: ${contentLength}\r\n\r\n`;
// Use Buffer for proper encoding
const jsonMessage = JSON.stringify(message);
const messageBuffer = Buffer.from(jsonMessage, 'utf8');
const contentLength = messageBuffer.length;
// Write separately instead of using Buffer.concat to avoid issues
process.stdout.write(header);
process.stdout.write(jsonMessage);
```
### 2. Output Redirection
A critical requirement for MCP servers is to keep the stdout channel clean for JSON-RPC messages only:
- **Debug Logs**: All debug/log output MUST go to stderr, not stdout.
- **Startup Messages**: Even initial startup logs must use console.error().
Solution:
```javascript
// Instead of this (WRONG)
console.log('Server starting...');
// Use this (CORRECT)
console.error('Server starting...');
// For detailed logs, use a consistent format
console.error(`[MCP Server] ${message}`);
```
### 3. Buffer Management
Buffer handling is crucial for correct protocol implementation:
- **Chunk Accumulation**: When processing binary data, handle chunk accumulation carefully.
- **Character Encoding**: Always explicitly specify UTF-8 encoding.
- **Buffer Type Checking**: When using Buffer.concat, ensure all chunks are Buffer instances, not strings.
Solution:
```javascript
// Make sure each chunk is a buffer
const bufferChunks = chunks.map(c => typeof c === 'string' ? Buffer.from(c, 'utf8') : c);
const buffer = Buffer.concat(bufferChunks, totalLength).toString('utf8');
```
### 4. Error Recovery
Robust error handling prevents protocol desynchronization:
- **Partial Message Recovery**: Implement logic to recover when incomplete messages are received.
- **Buffer Clearing**: Include a recovery mechanism to clear the buffer if it grows too large.
- **Error Logging**: Send detailed error messages to stderr, not stdout.
Solution:
```javascript
try {
// Message processing code
} catch (error) {
console.error(`[MCP Server] Error processing input: ${error.message}`);
console.error(`[MCP Server] Stack trace: ${error.stack}`);
// Send error message following the protocol
this.sendErrorResponse(null, `Error processing request: ${error.message}`);
// Recovery logic
if (totalLength > 10000) {
console.error('[MCP Server] Buffer too large, clearing for recovery');
chunks = [];
totalLength = 0;
}
}
```
### 5. Message Parsing
Accurate message parsing is essential:
- **Header Format**: Strictly match the header pattern with `\r\n\r\n`.
- **Content Length**: Ensure the content length calculation is accurate, especially with Unicode characters.
- **String Conversion**: Convert binary buffers to strings explicitly with UTF-8 encoding.
Solution:
```javascript
// Look for Content-Length header with exact pattern
// For MCP Inspector compatibility, strictly require \r\n\r\n
const headerMatch = buffer.slice(startIdx).match(/Content-Length:\s*(\d+)\r\n\r\n/);
if (!headerMatch) {
// No complete header found, wait for more data
console.error('[MCP Server] No complete Content-Length header found in buffer');
break;
}
// Calculate where header ends and content begins
const headerMatchLength = headerMatch[0].length;
const headerMatchStart = startIdx + headerMatch.index;
const contentStart = headerMatchStart + headerMatchLength;
// Parse the content length
const contentLength = parseInt(headerMatch[1], 10);
```
## Testing MCP Compliance
### Testing with MCP Inspector
To verify compatibility with MCP Inspector:
1. Create a test script that simulates MCP Inspector's protocol handling
2. Test with the exact message format used by MCP Inspector
3. Verify initialization, function execution, and error handling
### Testing with Claude Desktop
For Claude Desktop compatibility:
1. Set the `CLAUDE_MCP` environment variable to true
2. Simulate the initialization and function execution sequence
3. Verify handling of Unicode characters and binary data
4. Check that error recovery works properly
## Reference Implementation
A fully compliant MCP server should:
1. Use stderr for all logging and debugging
2. Strictly adhere to the JSON-RPC message format
3. Properly handle UTF-8 and binary data
4. Implement robust error recovery mechanisms
5. Include tests for both MCP Inspector and Claude Desktop
---
By following these guidelines, MCP servers can ensure reliable operation with both Claude Desktop and debugging tools like MCP Inspector.