This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a production-ready TypeScript template for building Model Context Protocol (MCP) servers and clients following the MCP 2025-03-26 specification. It provides a comprehensive foundation with built-in utilities, authentication, error handling, and service integrations.
Key Stats:
- 57 TypeScript source files
- 32 directories in src/
- Supports both stdio and HTTP (SSE) transports
- Built-in authentication (JWT/OAuth)
- Comprehensive error handling and logging
- Ready-to-use DuckDB and OpenRouter integrations
npm run build- Build TypeScript and make executablenpm run rebuild- Clean build (removes node_modules, logs, dist)npm start- Run the built server (stdio transport)npm run start:stdio- Run server with stdio transport and debug loggingnpm run start:http- Run server with HTTP transport and debug logging
npm run format- Format code with Prettiernpm run docs:generate- Generate TypeDoc documentationnpm run tree- Generate project structure treenpm run inspector- Launch MCP inspector for debuggingnpm run depcheck- Check for unused dependenciesnpm run fetch-spec- Fetch OpenAPI specificationnpm run db:duckdb-example- Run DuckDB example with debug logging
Important: No specific test framework is configured. Before adding tests:
- Check README or search codebase for testing approach
- Ask user for preferred test framework if not found
- Always run linting after code changes
Entry Point (src/index.ts):
- Main application entry with graceful shutdown handling
- Initializes logger and configuration
- Starts appropriate transport (stdio/HTTP)
- Handles process signals and unhandled errors
Configuration (src/config/index.ts):
- Environment variable validation with Zod schemas
- Project root detection and directory creation
- Comprehensive config object with defaults
- Supports development and production environments
MCP Server (src/mcp-server/):
server.ts- Core server initialization and transport selectioncreateMcpServerInstance()- Factory for McpServer instances- Per-session instances for HTTP, singleton for stdio
- Automatic tool and resource registration
MCP Client (src/mcp-client/):
- Modular client implementation for connecting to external MCP servers
core/clientManager.ts- Connection lifecycle managementclient-config/configLoader.ts- Configuration validation- Support for both stdio and HTTP transports
- Connection caching and automatic reconnection
Stdio Transport (src/mcp-server/transports/stdioTransport.ts):
- Single server instance communicating via stdin/stdout
- Simple process-based communication
- No authentication required
HTTP Transport (src/mcp-server/transports/httpTransport.ts):
- Hono-based web server with Server-Sent Events
- Per-session MCP server instances
- CORS support and port retry logic
- Session management with in-memory store
- Rate limiting and security headers
Authentication (src/mcp-server/transports/auth/):
- JWT mode: Self-contained tokens for development
- OAuth mode: External authorization server integration
- Middleware-based authentication
- Configurable auth strategies
Error Handling (src/utils/internal/errorHandler.ts):
- Centralized
ErrorHandlerclass with pattern-based classification - Automatic error code determination
- Consistent logging and context tracking
tryCatchhelper for robust error handling- Support for custom error mappings
Logging (src/utils/internal/logger.ts):
- Winston-based structured logging
- File rotation and MCP notifications
- Context-aware logging with request correlation
- Multiple log levels and output formats
Request Context (src/utils/internal/requestContext.ts):
- Request/operation tracking across the application
- Correlation ID generation and management
- Context inheritance and merging
Security (src/utils/security/):
- Input sanitization and validation
- Rate limiting with configurable limits
- ID generation (UUIDs and prefixed IDs)
- Log redaction for sensitive data
Parsing (src/utils/parsing/):
- Natural language date parsing with chrono-node
- Partial JSON parsing with error handling
- Think block extraction from LLM responses
Metrics (src/utils/metrics/):
- Token counting with tiktoken
- Performance and usage tracking utilities
Network (src/utils/network/):
- HTTP requests with timeout support
- Fetch utilities with error handling
DuckDB Service (src/services/duck-db/):
- Complete DuckDB integration with connection management
- Query execution, streaming, and transaction support
- Extension loading and prepared statements
- Type-safe query interfaces
OpenRouter Provider (src/services/llm-providers/openRouterProvider.ts):
- LLM integration via OpenRouter API
- OpenAI SDK compatibility
- Configurable models and parameters
Supabase Client (src/services/supabase/supabaseClient.ts):
- Supabase integration with authentication
- Database and storage access
Error Types (src/types-global/errors.ts):
BaseErrorCodeenum for standardized error classificationMcpErrorclass extending native Error with additional context- Type-safe error handling patterns
Tools (src/mcp-server/tools/):
echoTool/- Simple message formatting and repetitioncatFactFetcher/- Async API fetching exampleimageTest/- Image processing demonstration
Resources (src/mcp-server/resources/):
echoResource/- Basic resource implementation example
src/
├── config/ # Environment and configuration management
├── index.ts # Main application entry point
├── mcp-client/ # MCP client implementation
│ ├── client-config/ # Configuration loading and validation
│ ├── core/ # Core client logic and caching
│ └── transports/ # Client transport implementations
├── mcp-server/ # MCP server implementation
│ ├── resources/ # MCP resources (data sources)
│ ├── server.ts # Server initialization and setup
│ ├── tools/ # MCP tools (executable functions)
│ └── transports/ # Server transport implementations
├── services/ # External service integrations
│ ├── duck-db/ # DuckDB database service
│ ├── llm-providers/ # LLM provider integrations
│ └── supabase/ # Supabase service integration
├── storage/ # Data storage examples
├── types-global/ # Shared TypeScript type definitions
└── utils/ # Utility functions and helpers
├── internal/ # Core utilities (logging, errors, context)
├── metrics/ # Performance and usage metrics
├── network/ # Network and HTTP utilities
├── parsing/ # Data parsing utilities
└── security/ # Security and validation utilities
- Centralized Processing: All errors flow through
ErrorHandler - Pattern-Based Classification: Automatic error code assignment
- Context Preservation: Request context tracking throughout
- Structured Logging: Consistent error logging with correlation IDs
- Safe Execution:
tryCatchwrapper for robust error handling
Example Usage:
return ErrorHandler.tryCatch(
async () => {
// Your logic here
},
{
operation: "operationName",
context,
errorCode: BaseErrorCode.VALIDATION_ERROR,
critical: true,
},
);- Environment-Driven: All config from environment variables
- Validation: Zod schemas ensure type safety
- Defaults: Sensible defaults for development
- Security: Separate auth modes (JWT/OAuth)
- Directory Management: Automatic directory creation with validation
- Pluggable Design: Easy to add new transport types
- Per-Session State: HTTP transport maintains session isolation
- Authentication: Middleware-based auth for HTTP
- Error Handling: Consistent error responses across transports
- Schema-First: Zod validation for all inputs
- Modular Structure: Separate logic, registration, and exports
- Error Handling: Integrated with centralized error system
- Documentation: JSDoc comments throughout
CRITICAL PATTERN: This is the cornerstone of the error-handling strategy.
- Core Logic (
logic.ts): Contains pure business logic. Must throw structuredMcpErroron failure. Never usetry...catchblocks in logic files. - Handlers (
registration.ts, Transports): Wrap all logic calls intry...catch. Only place where errors are caught and formatted into responses.
Every operation must be traceable through structured logging and context propagation.
RequestContext: Create usingrequestContextService.createRequestContext()and pass through all function callsLogger: All logging through centralizedloggerwithRequestContext
Tools Structure: src/mcp-server/tools/toolName/
toolName/
├── index.ts # Barrel file, exports only register function
├── logic.ts # Core business logic, schemas, types
└── registration.ts # MCP server registration and error handling
Resources Structure: src/mcp-server/resources/resourceName/ (same pattern)
For Tools (follow echoTool as canonical example):
-
Define Schema and Logic (
logic.ts):// 1. Export Zod schema with .describe() on all fields export const ToolInputSchema = z.object({...}); // 2. Export TypeScript types export type ToolInput = z.infer<typeof ToolInputSchema>; export interface ToolResponse {...} // 3. Export core logic function export async function toolLogic( params: ToolInput, context: RequestContext ): Promise<ToolResponse> { // Pure business logic - throws on error }
-
Register Tool and Handle Errors (
registration.ts):export const registerTool = async (server: McpServer): Promise<void> => { server.tool(toolName, description, schema.shape, async (params) => { const context = requestContextService.createRequestContext({...}); try { const result = await toolLogic(params, context); return { content: [...], isError: false }; } catch (error) { const handledError = ErrorHandler.handleError(error, {...}); return { content: [...], isError: true }; } }); };
-
Export from Barrel (
index.ts):export { registerTool } from "./registration.js";
Core Configuration:
MCP_TRANSPORT_TYPE- "stdio" or "http" (default: stdio)MCP_HTTP_PORT- HTTP server port (default: 3010)MCP_HTTP_HOST- HTTP server host (default: 127.0.0.1)MCP_LOG_LEVEL- Logging level (default: debug)NODE_ENV- Environment (default: development)
Authentication (HTTP Transport):
MCP_AUTH_SECRET_KEY- JWT signing key (required for HTTP)MCP_AUTH_MODE- "jwt" or "oauth" (default: jwt)OAUTH_ISSUER_URL- OAuth issuer URL (for oauth mode)OAUTH_AUDIENCE- OAuth audience (for oauth mode)
Service Integrations:
OPENROUTER_API_KEY- OpenRouter API keyLLM_DEFAULT_MODEL- Default LLM modelSUPABASE_URL- Supabase project URLSUPABASE_ANON_KEY- Supabase anonymous key
- Create Tool Directory:
src/mcp-server/tools/yourTool/ - Implement Logic: Create
logic.tswith Zod schemas - Add Registration: Create
registration.tsusing SDK patterns - Export Module: Create
index.tsbarrel file - Register in Server: Add to
src/mcp-server/server.ts
File Structure:
src/mcp-server/tools/yourTool/
├── index.ts # Barrel exports
├── logic.ts # Core implementation with schemas
└── registration.ts # MCP server registration
Same pattern as tools but in src/mcp-server/resources/yourResource/
- Use ErrorHandler.tryCatch: For all async operations
- Provide Context: Include operation name and relevant data
- Choose Appropriate Error Codes: Use
BaseErrorCodeenum - Log Appropriately: Use structured logging with context
- Handle Gracefully: Always provide meaningful error messages
- Input Validation: Always use Zod schemas for external input
- Sanitization: Use
sanitizeInputForLoggingfor sensitive data - Authentication: Required for HTTP transport in production
- Rate Limiting: Built-in rate limiting for HTTP endpoints
- CORS: Configure allowed origins for HTTP transport
- Connection Caching: Client connections are cached automatically
- Session Management: HTTP transport uses per-session servers
- Logging: Structured logging with appropriate levels
- Error Handling: Efficient error classification with patterns
Current State: No testing framework is currently configured.
Before Adding Tests:
- Check existing documentation for testing preferences
- Search codebase for any existing test files
- Confirm with user their preferred testing approach
- Common options: Jest, Vitest, Node.js built-in test runner
Recommended Test Structure:
tests/
├── unit/ # Unit tests for utilities and services
├── integration/ # Integration tests for MCP operations
└── e2e/ # End-to-end tests for full workflows