Skip to main content

Server SDK Reference

This document provides a comprehensive reference for the MCP Server SDK, which allows you to build and deploy Model Context Protocol servers.

Overview

The MCP Server SDK is a JavaScript/TypeScript library that helps you create MCP-compliant servers. It provides everything you need to handle client requests, manage conversation contexts, process AI model responses, and implement tools and resources.

Installation

npm / yarn

# Using npm
npm install @trmx/server

# Using yarn
yarn add @trmx/server

Basic Usage

Creating a Simple MCP Server

// Import the SDK
import { MCPServer } from '@trmx/server';

// Create a server instance
const server = new MCPServer({
port: 3000,
});

// Start the server
server.start()
.then(() => {
console.log('MCP server running on port 3000');
})
.catch(error => {
console.error('Failed to start server:', error);
});

With Express Integration

import express from 'express';
import { MCPServer } from '@trmx/server';

// Create Express app
const app = express();

// Add custom middleware
app.use(express.static('public'));
app.use((req, res, next) => {
console.log(`Request: ${req.method} ${req.path}`);
next();
});

// Create MCP server with custom Express app
const server = new MCPServer({
app,
port: 3000,
});

// Start the server
server.start().then(() => {
console.log('MCP server running on port 3000');
});

Server Configuration

The MCPServer constructor accepts a configuration object with these options:

const server = new MCPServer({
// Core settings
port: 3000, // Server port (default: 3000)
host: '0.0.0.0', // Server host (default: '0.0.0.0')
app: expressApp, // Optional Express app instance

// AI model configuration
model: {
provider: 'openai', // AI provider (default: 'openai')
apiKey: process.env.OPENAI_API_KEY, // Provider API key
modelName: 'gpt-4', // Model name (default: 'gpt-4')
options: { // Provider-specific options
temperature: 0.7,
maxTokens: 1000,
},
},

// Features
tools: [...tools], // Array of tool definitions
resources: [...resources], // Array of resource definitions
prompts: [...prompts], // Array of prompt templates

// Context settings
contextStore: customContextStore, // Custom context store implementation
contextSettings: {
strategy: 'smart-truncation', // Context management strategy
maxTokens: 4000, // Maximum tokens for context
summarizeThreshold: 20, // When to summarize older messages
},

// Middleware and custom handlers
middleware: [...middleware], // Array of middleware functions
cors: corsOptions, // CORS options
errorHandler: customErrorHandler, // Custom error handler

// Authentication
auth: {
enabled: true, // Enable authentication
apiKey: process.env.API_KEY, // API key for authentication
customAuth: customAuthFunction, // Custom auth handler
},

// Security
httpsOptions: { // HTTPS configuration
key: fs.readFileSync('path/to/key.pem'),
cert: fs.readFileSync('path/to/cert.pem'),
},

// Advanced options
logger: customLogger, // Custom logger implementation
bodyParserOptions: {}, // Options for body-parser
metrics: {
enabled: true,
provider: 'prometheus',
},
});

Tools

Defining Tools

Tools are functions that models can call to perform actions or retrieve information:

// src/tools/calculator.js
export const calculatorTool = {
name: 'calculator', // Tool name
description: 'Performs basic arithmetic operations', // Tool description

// Parameters schema (JSON Schema format)
parameters: {
type: 'object',
properties: {
operation: {
type: 'string',
enum: ['add', 'subtract', 'multiply', 'divide'],
description: 'The operation to perform',
},
a: {
type: 'number',
description: 'First operand',
},
b: {
type: 'number',
description: 'Second operand',
},
},
required: ['operation', 'a', 'b'],
},

// Tool implementation
execute: async ({ operation, a, b }) => {
switch (operation) {
case 'add': return { result: a + b };
case 'subtract': return { result: a - b };
case 'multiply': return { result: a * b };
case 'divide':
if (b === 0) throw new Error('Division by zero');
return { result: a / b };
default:
throw new Error(`Unknown operation: ${operation}`);
}
},
};

Registering Tools

// src/tools/index.js
import { calculatorTool } from './calculator';
import { weatherTool } from './weather';

export const tools = [
calculatorTool,
weatherTool,
];

// In your server setup
import { tools } from './tools';

const server = new MCPServer({
port: 3000,
tools,
});

Advanced Tool Configuration

const advancedTool = {
name: 'advanced_tool',
description: 'An advanced tool with additional configuration',

// Standard parameters schema
parameters: {
// ...parameter definitions
},

// Access control
permissions: ['admin', 'power-user'], // Required permissions
rateLimit: {
maxRequests: 10,
windowMs: 60000, // 1 minute
},

// Execution options
timeout: 5000, // 5 seconds timeout
retry: {
maxRetries: 3,
initialDelay: 100,
},

// Tool implementation
execute: async (params, context) => {
// Access user information from context
const { userId, permissions } = context;

// Implement tool logic
// ...

return { result: 'Tool execution result' };
},
};

Resources

Defining Resources

Resources provide models with access to external data sources:

// src/resources/knowledge-base.js
export const knowledgeBaseResource = {
name: 'knowledge_base', // Resource name
description: 'Access to company knowledge base articles', // Resource description

// Resource implementation
fetch: async (query, context) => {
// Search knowledge base for relevant information
const results = await knowledgeBaseService.search(query);

// Return matching articles
return results.map(article => ({
id: article.id,
title: article.title,
content: article.content,
url: article.url,
lastUpdated: article.updatedAt,
}));
},
};

Registering Resources

// src/resources/index.js
import { knowledgeBaseResource } from './knowledge-base';
import { productCatalogResource } from './product-catalog';

export const resources = [
knowledgeBaseResource,
productCatalogResource,
];

// In your server setup
import { resources } from './resources';

const server = new MCPServer({
port: 3000,
resources,
});

Advanced Resource Configuration

const advancedResource = {
name: 'advanced_resource',
description: 'An advanced resource with additional configuration',

// Access control
permissions: ['user'], // Required permissions
rateLimit: {
maxRequests: 20,
windowMs: 60000, // 1 minute
},

// Cache configuration
cache: {
enabled: true,
ttl: 3600, // 1 hour
maxSize: 100, // Maximum items to cache
},

// Fetch implementation
fetch: async (query, context) => {
// Access user information from context
const { userId, permissions } = context;

// Implement resource logic
// ...

return [/* resource results */];
},
};

Prompt Templates

Defining Prompt Templates

Prompt templates help you create reusable, parameterized prompts:

// src/prompts/greeting.js
export const greetingPrompt = {
name: 'greeting', // Template name
description: 'A friendly greeting template', // Template description

// Template content
template: `
You are a helpful assistant for {{company_name}}.

Always greet the user by their name, {{user_name}}, if available.
Be friendly but professional in your responses.

If the user asks about {{company_name}}'s products or services, provide helpful information.
`,

// Parameters schema
parameters: {
company_name: {
type: 'string',
description: 'The company name',
},
user_name: {
type: 'string',
description: 'The user\'s name',
required: false,
},
},
};

Registering Prompt Templates

// src/prompts/index.js
import { greetingPrompt } from './greeting';
import { supportPrompt } from './support';

export const prompts = [
greetingPrompt,
supportPrompt,
];

// In your server setup
import { prompts } from './prompts';

const server = new MCPServer({
port: 3000,
prompts,
});

Context Management

Default Context Store

By default, MCP Server uses an in-memory context store, which is good for development but not for production:

// Default in-memory context store
const server = new MCPServer({
port: 3000,
// Uses default in-memory store
});

Custom Context Stores

For production, you should use a persistent context store:

// MongoDB context store
import { MongoContextStore } from '@trmx/context-mongodb';

const contextStore = new MongoContextStore({
uri: process.env.MONGODB_URI,
database: 'mcp',
collection: 'contexts',
});

const server = new MCPServer({
port: 3000,
contextStore,
});

// Redis context store
import { RedisContextStore } from '@trmx/context-redis';

const contextStore = new RedisContextStore({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD,
});

const server = new MCPServer({
port: 3000,
contextStore,
});

Custom Context Management

You can implement your own context management logic:

import { ContextManager } from '@trmx/server';

class CustomContextManager extends ContextManager {
async prepareContext(contextId, newMessage) {
// Get existing context
const context = await this.store.getContext(contextId);

// Apply custom logic for context preparation
if (context.messages.length > 20) {
// Create a summary of older messages
const oldMessages = context.messages.slice(0, 10);
const summary = await this.createSummary(oldMessages);

// Replace older messages with summary
context.messages = [
{ role: 'system', content: `Conversation summary: ${summary}` },
...context.messages.slice(10)
];
}

// Add the new message
context.messages.push(newMessage);

// Save updated context
await this.store.updateContext(contextId, context);

return context;
}

async createSummary(messages) {
// Custom logic to create a summary of messages
// This might call an AI model to generate a summary
return "Summary of previous conversation...";
}
}

// Use custom context manager in server setup
const server = new MCPServer({
contextManager: new CustomContextManager({
store: contextStore,
}),
});

Authentication

API Key Authentication

The simplest authentication method is API key-based:

const server = new MCPServer({
port: 3000,
auth: {
enabled: true,
apiKey: process.env.API_KEY, // Single API key
// Or multiple keys
apiKeys: [process.env.API_KEY_1, process.env.API_KEY_2],
},
});

Custom Authentication

You can implement custom authentication:

const server = new MCPServer({
port: 3000,
auth: {
enabled: true,
customAuth: async (req, res, next) => {
const authHeader = req.headers.authorization;

if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Unauthorized' });
}

const token = authHeader.split(' ')[1];

try {
// Verify token with your auth service
const user = await authService.verifyToken(token);

// Add user info to request for later use
req.user = user;

next();
} catch (error) {
return res.status(401).json({ error: 'Invalid token' });
}
},
},
});

OAuth Integration

For OAuth authentication, you'll typically set up middleware:

import passport from 'passport';
import { Strategy as OAuth2Strategy } from 'passport-oauth2';
import session from 'express-session';

// Create Express app
const app = express();

// Configure session
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
}));

// Initialize Passport
app.use(passport.initialize());
app.use(passport.session());

// Configure OAuth2 strategy
passport.use(new OAuth2Strategy({
authorizationURL: 'https://auth-provider.com/oauth2/authorize',
tokenURL: 'https://auth-provider.com/oauth2/token',
clientID: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
callbackURL: 'https://your-mcp-server.com/auth/callback',
}, (accessToken, refreshToken, profile, done) => {
// Verify user and call done(null, user)
}));

// Serialize user to session
passport.serializeUser((user, done) => {
done(null, user.id);
});

// Deserialize user from session
passport.deserializeUser(async (id, done) => {
try {
const user = await userService.findById(id);
done(null, user);
} catch (error) {
done(error);
}
});

// Set up auth routes
app.get('/auth/login', passport.authenticate('oauth2'));
app.get('/auth/callback', passport.authenticate('oauth2', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure',
}));

// Create MCP server with the app
const server = new MCPServer({
app,
port: 3000,
auth: {
enabled: true,
customAuth: (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.status(401).json({ error: 'Unauthorized' });
},
},
});

Error Handling

Default Error Handler

The SDK provides a default error handler that formats errors according to the MCP protocol:

// Default error handling
const server = new MCPServer({
port: 3000,
// Uses default error handler
});

Custom Error Handler

You can implement custom error handling:

const server = new MCPServer({
port: 3000,
errorHandler: (err, req, res, next) => {
// Log the error
console.error('Error:', err);

// Format error response
const statusCode = err.statusCode || 500;
const errorMessage = err.message || 'Internal Server Error';

// Format MCP protocol error response
res.status(statusCode).json({
error: {
code: err.code || (statusCode === 401 ? 'UNAUTHORIZED' : 'INTERNAL_ERROR'),
message: errorMessage,
data: err.data || undefined,
},
id: req.body.id,
});

// Report error to monitoring service
errorReportingService.report(err);
},
});

Middleware

Adding Middleware

You can add custom middleware functions:

// Rate limiting middleware
import rateLimit from 'express-rate-limit';

const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
});

// Logging middleware
const loggingMiddleware = (req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);
next();
};

// Add middleware to server
const server = new MCPServer({
port: 3000,
middleware: [
apiLimiter,
loggingMiddleware,
],
});

CORS Configuration

Configure CORS for cross-origin requests:

const server = new MCPServer({
port: 3000,
cors: {
origin: ['https://your-app.com', 'https://admin.your-app.com'],
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
},
});

Streaming Support

Enabling Streaming

Enable streaming for real-time AI responses:

const server = new MCPServer({
port: 3000,
streaming: {
enabled: true, // Enable streaming support
chunkSize: 10, // Characters per chunk (for testing)
},
});

Metrics and Monitoring

Enabling Metrics

Configure metrics collection for monitoring:

const server = new MCPServer({
port: 3000,
metrics: {
enabled: true,
provider: 'prometheus', // Metrics provider
endpoint: '/metrics', // Metrics endpoint
},
});

Health Check Endpoint

Add a health check endpoint:

const server = new MCPServer({
port: 3000,
healthCheck: {
enabled: true,
endpoint: '/health',
checks: [
// Custom health checks
async () => {
// Check database connection
const dbStatus = await checkDatabaseConnection();
return {
name: 'database',
status: dbStatus ? 'up' : 'down',
};
},
],
},
});

TypeScript Support

The SDK provides full TypeScript support:

import { MCPServer, Tool, Resource, ContextStore } from '@trmx/server';

// Define tool with TypeScript
interface CalculatorParams {
operation: 'add' | 'subtract' | 'multiply' | 'divide';
a: number;
b: number;
}

interface CalculatorResult {
result: number;
}

const calculatorTool: Tool<CalculatorParams, CalculatorResult> = {
name: 'calculator',
description: 'Performs basic arithmetic operations',
parameters: {
type: 'object',
properties: {
operation: {
type: 'string',
enum: ['add', 'subtract', 'multiply', 'divide'],
description: 'The operation to perform',
},
a: {
type: 'number',
description: 'First operand',
},
b: {
type: 'number',
description: 'Second operand',
},
},
required: ['operation', 'a', 'b'],
},
execute: async ({ operation, a, b }) => {
switch (operation) {
case 'add': return { result: a + b };
case 'subtract': return { result: a - b };
case 'multiply': return { result: a * b };
case 'divide':
if (b === 0) throw new Error('Division by zero');
return { result: a / b };
default:
throw new Error(`Unknown operation: ${operation as string}`);
}
},
};

// Create server with TypeScript
const server = new MCPServer({
port: 3000,
tools: [calculatorTool],
});

Deployment

Production Best Practices

When deploying to production, follow these best practices:

  1. Use a persistent context store (MongoDB, Redis, etc.)
  2. Enable authentication
  3. Configure HTTPS
  4. Set up proper error handling and logging
  5. Implement rate limiting
  6. Monitor server health and performance

Example production configuration:

import { MCPServer } from '@trmx/server';
import { MongoContextStore } from '@trmx/context-mongodb';
import fs from 'fs';

// Create context store
const contextStore = new MongoContextStore({
uri: process.env.MONGODB_URI,
database: 'mcp',
collection: 'contexts',
});

// Create server with production settings
const server = new MCPServer({
port: process.env.PORT || 3000,

// Use context store
contextStore,

// Enable authentication
auth: {
enabled: true,
apiKey: process.env.API_KEY,
},

// Configure HTTPS
httpsOptions: {
key: fs.readFileSync('path/to/key.pem'),
cert: fs.readFileSync('path/to/cert.pem'),
},

// CORS configuration
cors: {
origin: process.env.ALLOWED_ORIGINS?.split(',') || '*',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
},

// Rate limiting
middleware: [
rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
}),
],

// Metrics and monitoring
metrics: {
enabled: true,
provider: 'prometheus',
},

// Health check
healthCheck: {
enabled: true,
},
});

// Start server
server.start().catch(error => {
console.error('Failed to start server:', error);
process.exit(1);
});

Next Steps