| English | 中文 |
A TypeScript tool for auditing all interactions with MCP (Model Context Protocol) servers. It intercepts and logs all I/O operations from MCP servers through a transparent proxy approach, generating comprehensive audit logs to help developers debug, monitor, and ensure compliance in MCP applications.
This tool supports two usage modes:
Use the MCPWrapper class in your TypeScript/Node.js code to wrap and call MCP servers.
Run as a standalone MCP server that can be connected to by Claude Desktop or other MCP clients.
👉 Detailed Server Documentation: See SERVER.md
mcp-auditor/
├── src/
│ ├── core/ # Core wrapper functionality
│ │ ├── wrapper.ts # Main MCPWrapper class
│ │ ├── logger.ts # Logger implementation
│ │ └── types.ts # TypeScript types
│ ├── server/ # Server-specific code
│ │ ├── server.ts # MCP server implementation
│ │ └── config.ts # Configuration loader
│ └── index.ts # Main entry point
├── examples/
│ ├── library/ # Library usage examples
│ └── server/ # Server usage examples
├── docs/ # Documentation
├── dist/ # Compiled output
└── logs/ # Log files
As a library (recommended):
npm install mcp-auditor
As a global CLI:
npm install -g mcp-auditor
From source:
git clone https://github.com/algovate/mcp-auditor.git
cd mcp-auditor
npm install
npm run build
# 1. Install dependencies and build
npm install
npm run build
# 2. Configure environment variables
export MCP_WRAPPED_SERVER_COMMAND=npx
export MCP_WRAPPED_SERVER_ARGS="-y,@modelcontextprotocol/server-filesystem,/tmp"
export MCP_LOG_FILE=./logs/mcp-server.log
# 3. Start the server
npm start
Then add to your Claude Desktop configuration:
{
"mcpServers": {
"wrapped-server": {
"command": "node",
"args": ["/path/to/mcp-auditor/dist/server/server.js"],
"env": {
"MCP_WRAPPED_SERVER_COMMAND": "npx",
"MCP_WRAPPED_SERVER_ARGS": "-y,@modelcontextprotocol/server-filesystem,/Users/yourname/Documents",
"MCP_LOG_FILE": "/Users/yourname/logs/mcp-wrapper.log"
}
}
}
}
📖 Complete Server Documentation: SERVER.md
import { MCPWrapper } from 'mcp-auditor';
// Create auditor instance
const wrapper = new MCPWrapper({
serverCommand: 'npx',
serverArgs: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
logFilePath: './logs/mcp-wrapper.log',
logToolCalls: true,
logToolResults: true
});
// Connect to MCP server
await wrapper.connect();
// Get available tools
const tools = wrapper.getTools();
console.log('Available tools:', tools.map(t => t.name));
// Call a tool
const result = await wrapper.callTool('read_file', {
path: '/tmp/example.txt'
});
// Disconnect
await wrapper.disconnect();
You can create an MCP server to wrap another MCP server:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { MCPWrapper } from 'mcp-auditor';
// Create auditor
const wrapper = new MCPWrapper({
serverCommand: 'your-mcp-server',
logFilePath: './logs/proxy.log'
});
await wrapper.connect();
// Create proxy server
const server = new Server({
name: 'mcp-proxy',
version: '1.0.0'
}, {
capabilities: { tools: {} }
});
// Expose wrapped server tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: wrapper.getTools() };
});
// Proxy tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
return await wrapper.callTool(
request.params.name,
request.params.arguments
);
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
interface MCPWrapperConfig {
/** MCP server command or executable path */
serverCommand: string;
/** Arguments to pass to the MCP server */
serverArgs?: string[];
/** Environment variables for the MCP server process */
serverEnv?: Record<string, string>;
/** Log file path */
logFilePath: string;
/** Whether to log tool calls (default: true) */
logToolCalls?: boolean;
/** Whether to log tool results (default: true) */
logToolResults?: boolean;
/** Whether to append to existing log file (default: true) */
logAppend?: boolean;
/** Log format: 'structured' or 'jsonrpc' (default: 'structured') */
logFormat?: 'structured' | 'jsonrpc';
}
Connection:
connect(): Promise<void> - Connect to the wrapped MCP serverdisconnect(): Promise<void> - Disconnect and close the loggerisConnected(): boolean - Check if connectedTools:
getTools(): Tool[] - Get a list of all available toolsgetTool(name: string): Tool | undefined - Get a specific tool by namehasTool(name: string): boolean - Check if a tool existscallTool(toolName: string, params?: Record<string, unknown>): Promise<CallToolResult> - Call a toolResources:
getResources(): Resource[] - Get a list of all available resourcesgetResource(uri: string): Resource | undefined - Get a specific resource by URIhasResource(uri: string): boolean - Check if a resource existsreadResource(uri: string): Promise<ReadResourceResult> - Read a resourcePrompts:
getPrompts(): Prompt[] - Get a list of all available promptsgetPromptDefinition(name: string): Prompt | undefined - Get a specific prompt definition by namehasPrompt(name: string): boolean - Check if a prompt existsgetPrompt(name: string, args?: Record<string, string>): Promise<GetPromptResult> - Get a prompt with argumentsLogging:
getLogger(): MCPLogger - Get the logger instance for custom loggingGeneral Logging:
logEntry(entry: LogEntry): void - Log a structured entrylog(level: 'info' | 'error' | 'debug', message: string, data?: any): void - Log a messagelogError(error: Error | string, context?: any): void - Log an errorclose(): Promise<void> - Close the loggerTool Logging:
logToolCall(toolName: string, params: any): void - Log a tool call requestlogToolResult(toolName: string, result: any, error?: any): void - Log a tool resultResource Logging:
logResourceListRequest(): void - Log a resource list requestlogResourceListResponse(resources: any[]): void - Log a resource list responselogResourceReadRequest(uri: string): void - Log a resource read requestlogResourceReadResponse(uri: string, result: any, error?: any): void - Log a resource read responsePrompt Logging:
logPromptListRequest(): void - Log a prompt list requestlogPromptListResponse(prompts: any[]): void - Log a prompt list responselogPromptGetRequest(name: string, args?: any): void - Log a prompt get requestlogPromptGetResponse(name: string, result: any, error?: any): void - Log a prompt get responseServer Logging:
logServerRequest(method: string, params?: any): void - Log a server requestlogServerResponse(method: string, result: any, error?: any): void - Log a server responseMCP Auditor supports two log formats:
Detailed audit logs with timestamps, direction, and metadata. Best for debugging and analysis.
const wrapper = new MCPWrapper({
serverCommand: 'npx',
serverArgs: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
logFilePath: './logs/audit.log',
logFormat: 'structured' // Default
});
Each entry contains:
interface LogEntry {
timestamp: string; // ISO 8601 timestamp
direction: 'input' | 'output'; // Data flow direction
type: 'tool_call' | 'tool_result' | 'resource_list' | 'resource_read' | 'prompt_list' | 'prompt_get' | 'server_request' | 'server_response' | 'error';
data: any; // Log data
}
{
"timestamp": "2024-01-15T10:30:00.000Z",
"direction": "input",
"type": "tool_call",
"data": {
"toolName": "read_file",
"params": {
"path": "/tmp/example.txt"
}
}
}
{
"timestamp": "2024-01-15T10:30:00.123Z",
"direction": "output",
"type": "tool_result",
"data": {
"toolName": "read_file",
"result": {
"content": [
{
"type": "text",
"text": "File contents here..."
}
]
}
}
}
{
"timestamp": "2024-01-15T10:30:05.000Z",
"direction": "input",
"type": "resource_list",
"data": {
"action": "list_resources"
}
}
{
"timestamp": "2024-01-15T10:30:05.123Z",
"direction": "output",
"type": "resource_list",
"data": {
"action": "list_resources",
"resourceCount": 3,
"resources": [
{
"uri": "file:///example.txt",
"name": "Example File",
"mimeType": "text/plain",
"description": "An example text file"
}
]
}
}
{
"timestamp": "2024-01-15T10:30:06.000Z",
"direction": "input",
"type": "resource_read",
"data": {
"action": "read_resource",
"uri": "file:///example.txt"
}
}
{
"timestamp": "2024-01-15T10:30:06.123Z",
"direction": "output",
"type": "resource_read",
"data": {
"action": "read_resource",
"uri": "file:///example.txt",
"result": {
"contentLength": 1,
"contentTypes": ["text/plain"]
}
}
}
{
"timestamp": "2024-01-15T10:30:07.000Z",
"direction": "input",
"type": "prompt_list",
"data": {
"action": "list_prompts"
}
}
{
"timestamp": "2024-01-15T10:30:07.123Z",
"direction": "output",
"type": "prompt_list",
"data": {
"action": "list_prompts",
"promptCount": 2,
"prompts": [
{
"name": "code-review",
"description": "Review code for best practices",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
]
}
}
{
"timestamp": "2024-01-15T10:30:08.000Z",
"direction": "input",
"type": "prompt_get",
"data": {
"action": "get_prompt",
"name": "code-review",
"arguments": {
"code": "function hello() { return 'world'; }"
}
}
}
{
"timestamp": "2024-01-15T10:30:08.123Z",
"direction": "output",
"type": "prompt_get",
"data": {
"action": "get_prompt",
"name": "code-review",
"result": {
"description": "Code review for provided code",
"messageCount": 2
}
}
}
Raw JSON-RPC protocol messages. Best for protocol debugging and network analysis.
const wrapper = new MCPWrapper({
serverCommand: 'npx',
serverArgs: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
logFilePath: './logs/jsonrpc.log',
logFormat: 'jsonrpc' // Raw JSON-RPC messages
});
Each line is a complete JSON-RPC message:
Request:
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}
Response:
{"jsonrpc":"2.0","id":1,"result":{"tools":["read_file","write_file"...]}}
Tool Call:
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"read_file","arguments":{"path":"/tmp/file.txt"}}}
Error:
{"jsonrpc":"2.0","id":2,"error":{"code":-32603,"message":"File not found","data":{"context":"readFile"}}}
The JSON-RPC format:
See the examples/ directory for more examples:
examples/library/basic-usage.ts - Basic usage exampleexamples/server/server-wrapper.ts - Example of creating a proxy serverRun examples:
npm run build
npm run dev examples/library/basic-usage.ts
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run watch
# Run examples
npm run dev examples/basic-usage.ts
MIT