Package Exports
- @mcpweb-org/sdk
Readme
MCPaaS TypeScript SDK
The official TypeScript SDK for MCPaaS (Model Context Protocol as a Service) - build, deploy, and monitor MCP servers with automatic analytics and observability.
🚀 Ready in 2 minutes - Get your MCP server running with built-in analytics, HTTP routing, API integrations, and comprehensive observability
📚 Table of Contents
- Quick Start
- Installation
- Core Components
- Complete Feature Overview
- Step-by-Step Tutorials
- Examples
- API Reference
- Analytics & Observability
- Best Practices
- Troubleshooting
🚀 Quick Start
Get running in under 2 minutes:
# 1. Install the SDK
npm install @mcpweb-org/sdk
# 2. Create a new TypeScript project
mkdir my-mcpaas-server
cd my-mcpaas-server
npm init -y
npm install @mcpweb-org/sdk typescript @types/node zod
npx tsc --init
# 3. Create your server file
touch server.ts
Then add this code to server.ts
:
import { MCPWeb } from '@mcpweb-org/sdk';
import { z } from 'zod';
// ✨ Create server with automatic analytics
const server = new MCPWeb({
name: 'my-awesome-server',
version: '1.0.0',
}, 'your-app-id', 'your-api-key');
// 🛠️ Add a tool in 30 seconds
server.registerTool('greet', {
title: 'Greeting Tool',
description: 'Say hello to someone',
inputSchema: {
name: z.string().describe('Person to greet'),
style: z.enum(['formal', 'casual']).default('casual')
}
}, async ({ name, style }) => {
const greeting = style === 'formal'
? `Good day, ${name}.`
: `Hey ${name}! 👋`;
return {
content: [{
type: 'text',
text: greeting
}]
};
});
// 🚀 Start your server
await server.start();
console.log('🎉 Server running! Try calling the greet tool.');
Run it:
# 4. Set environment variables
echo "MCPAAS_API_BASE_URL=https://us-central1-mcpaas-dev.cloudfunctions.net/analytics" > .env
echo "MCPAAS_APP_ID=your-app-id" >> .env
echo "MCPAAS_API_KEY=your-api-key" >> .env
# 5. Start your server
npx tsx server.ts
# or compile and run: npx tsc && node server.js
That's it! Your MCP server is running with built-in analytics, error tracking, and performance monitoring.
📦 Installation
# npm
npm install @mcpweb-org/sdk
# yarn
yarn add @mcpweb-org/sdk
# pnpm
pnpm add @mcpweb-org/sdk
Requirements:
- Node.js 18+
- TypeScript 5.0+ (recommended)
🧩 Core Components
🎯 What Should I Use?
Component | Use Case | When to Choose |
---|---|---|
MCPWeb | Core MCP server with HTTPS/HTTP support | ✅ Always start here - complete MCP server |
MCPWebExpress | Drop-in Express replacement with MCP | ✅ Migrating from Express servers |
AnalyticsClient | Advanced analytics tracking | ✅ Custom metrics and observability |
MCPWebLog | Lightweight logging utility | ✅ Production debugging with toggle |
OpenAPI Parser | Auto-register APIs from schemas | ✅ Bulk API integration from specs |
API Helper | Manual API registration utilities | ✅ Custom API transformations |
✨ Complete Feature Overview
🚀 Core MCP Server (MCPWeb)
- Full MCP Protocol: Complete implementation of MCP specification
- HTTP/HTTPS Server: Built-in web server with REST endpoints
- Transport Support: Works with StreamableHTTP, Stdio, and custom transports
- Session Management: Automatic session lifecycle tracking and cleanup
- Built-in Endpoints:
/health
,/docs
,/tools
,/resources
,/prompts
📊 Advanced Analytics System
- Flat Schema Design: BigQuery-compatible event structure
- Comprehensive Tracking: Tools, resources, prompts, sessions, performance
- Real-time Metrics: Memory usage, CPU, response times, error rates
- Batch Processing: Efficient data transmission with configurable batching
- Custom Events: Track your own business metrics and KPIs
- Retry Logic: Robust error handling with exponential backoff
🌐 OpenAPI Integration Engine
- Bulk Registration: Register entire API suites from OpenAPI 3.0 specifications
- Automatic Schema Conversion: OpenAPI schemas → Zod validation schemas
- Parameter Extraction: Path, query, body, and header parameters automatically mapped
- Type Safety: Full TypeScript type generation from OpenAPI definitions
- Authentication Support: Bearer, Basic, API Key, OAuth2 from security schemes
- Template Variables: Dynamic parameter injection with
{{param}}
syntax - Error Handling: Comprehensive validation and error reporting with retry logic
- Selective Registration: Filter and register only specific endpoints
- Remote Loading: Load schemas from URLs, files, or inline definitions
🌐 API Integration Engine
- HTTP Method Support: GET, POST, PUT, DELETE, PATCH, and 20+ others
- Template System: Dynamic parameter injection with
{{param}}
syntax - Built-in Functions:
{{$now}}
,{{$uuid}}
,{{$timestamp}}
,{{$env.VAR}}
- Authentication: Bearer, Basic, API Key, OAuth2, Custom headers
- OpenAPI Parsing: Bulk registration from OpenAPI 3.0 specifications
- Error Handling: Comprehensive validation and error reporting
⚡ Express Integration (MCPWebExpress)
- Drop-in Replacement: Zero-code migration from Express servers
- MCP Protocol: Automatic
/mcp
endpoints for client communication - Middleware Support: Full Express.js middleware ecosystem compatibility
- CORS & Security: Built-in cross-origin and security features
- Session Cleanup: Automatic transport cleanup on disconnect
🔍 Developer Tools
- MCPWebLog: Lightweight logging with production toggle
- Type Safety: Full TypeScript support with Zod validation
- Error Classes: Structured error handling with custom error types
- Configuration Schemas: Validated configuration with helpful error messages
🎓 Step-by-Step Tutorials
Tutorial 1: Your First MCP Tool (2 minutes)
import { MCPWeb } from '@mcpweb-org/sdk';
import { z } from 'zod';
// Step 1: Create server
const server = new MCPWeb({
name: 'tutorial-server',
version: '1.0.0'
}, process.env.MCPAAS_APP_ID!, process.env.MCPAAS_API_KEY!);
// Step 2: Add a simple tool
server.registerTool('flip-coin', {
title: 'Coin Flipper',
description: 'Flip a virtual coin',
inputSchema: {
// No inputs needed!
}
}, async () => {
const result = Math.random() > 0.5 ? 'heads' : 'tails';
return {
content: [{
type: 'text',
text: `🪙 Coin flip result: ${result.toUpperCase()}!`
}]
};
});
// Step 3: Start server
await server.start();
Tutorial 2: Mounting MCP on Express Server (3 minutes)
import { MCPWeb, MCPWebExpress } from '@mcpweb-org/sdk';
// Step 1: Setup MCP server (from Tutorial 1)
const mcpServer = new MCPWeb({
name: 'web-server',
version: '1.0.0'
}, process.env.MCPAAS_APP_ID!, process.env.MCPAAS_API_KEY!);
// Add your MCP tools here...
// Step 2: Mount MCP on Express server
const server = new MCPWebExpress({
mcpWeb: mcpServer,
options: {
port: 3000,
cors: true,
json: true
}
});
// Step 3:(Optional) Add additional custom REST APIs
server.get('/api/flip', async (req, res) => {
// Call your MCP tool from HTTP!
const result = Math.random() > 0.5 ? 'heads' : 'tails';
res.json({ result, timestamp: new Date().toISOString() });
});
server.post('/api/greet', async (req, res) => {
const { name } = req.body;
res.json({ message: `Hello ${name}!` });
});
// Step 4: Start server
await server.start();
console.log('🌐 Server running on http://localhost:3000');
console.log('🧪 Try: curl http://localhost:3000/api/flip');
Tutorial 3: External API Integration (5 minutes)
// Step 1: Transform GitHub API into MCP tool
server.registerAPI('github-user', {
title: 'GitHub User Info',
description: 'Get GitHub user information',
inputSchema: {
username: z.string().describe('GitHub username')
}
}, {
method: 'GET',
url: 'https://api.github.com/users/{{username}}',
headers: {
'User-Agent': 'MCPaaS-SDK',
'Accept': 'application/vnd.github.v3+json'
}
});
// Step 2: Use weather API with API key
server.registerAPI('weather', {
title: 'Current Weather',
description: 'Get current weather for a city',
inputSchema: {
city: z.string(),
units: z.enum(['metric', 'imperial']).default('metric')
}
}, {
method: 'GET',
url: 'https://api.openweathermap.org/data/2.5/weather',
headers: {
'Authorization': `Bearer ${process.env.OPENWEATHER_API_KEY}`
},
queryParams: {
q: '{{city}}',
units: '{{units}}'
}
});
// Done! Your external APIs are now MCP tools 🎉
Tutorial 4: Advanced Analytics Tracking (3 minutes)
import { MCPWeb, AnalyticsClient } from '@mcpweb-org/sdk';
// Step 1: Setup server with analytics
const server = new MCPWeb({
name: 'analytics-demo',
version: '1.0.0'
}, process.env.MCPAAS_APP_ID!, process.env.MCPAAS_API_KEY!);
// Step 2: Get analytics collector
const analytics = server.analyticsCollector;
// Step 3: Add tool with custom analytics
server.registerTool('process-data', {
title: 'Data Processor',
description: 'Process and analyze data',
inputSchema: {
data: z.array(z.number()),
algorithm: z.enum(['mean', 'median', 'mode'])
}
}, async ({ data, algorithm }) => {
const startTime = Date.now();
// Track custom business metrics
analytics.trackEvent({
eventType: 'performance_metric',
performanceCustomMetricsJson: JSON.stringify({
inputDataSize: data.length,
algorithmType: algorithm,
memoryBefore: process.memoryUsage().heapUsed
})
});
// Process data
let result: number;
switch (algorithm) {
case 'mean':
result = data.reduce((a, b) => a + b, 0) / data.length;
break;
case 'median':
const sorted = [...data].sort((a, b) => a - b);
result = sorted[Math.floor(sorted.length / 2)];
break;
case 'mode':
const counts = data.reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {} as Record<number, number>);
result = Number(Object.keys(counts).reduce((a, b) => counts[Number(a)] > counts[Number(b)] ? a : b));
break;
}
// Track completion with performance data
const duration = Date.now() - startTime;
analytics.trackEvent({
eventType: 'performance_metric',
performanceCustomMetricsJson: JSON.stringify({
processingTime: duration,
memoryAfter: process.memoryUsage().heapUsed,
efficiency: data.length / duration, // items per ms
accuracy: 1.0 // assuming 100% accuracy for demo
})
});
return {
content: [{
type: 'text',
text: `${algorithm.toUpperCase()} of ${data.length} items: ${result}`
}]
};
});
// Step 4: Configure analytics behavior
analytics.configure({
batchSize: 50, // Events per batch
flushInterval: 30000, // Flush every 30 seconds
maxEventsInMemory: 1000, // Memory limit
enabled: true
});
await server.start();
Tutorial 5: Bulk API Registration with OpenAPI (2 minutes)
Register entire API suites instantly using OpenAPI specifications:
import { MCPWeb, OpenAPISchema } from '@mcpweb-org/sdk';
// Step 1: Define or load your OpenAPI schema
const githubAPISchema: OpenAPISchema = {
openapi: "3.0.0",
info: {
title: "GitHub API",
version: "1.0.0",
description: "GitHub REST API endpoints for user and repository management"
},
servers: [{
url: "https://api.github.com",
description: "GitHub API v3"
}],
paths: {
"/users/{username}": {
get: {
operationId: "getUser",
summary: "Get user information",
description: "Fetch detailed information about a GitHub user",
parameters: [{
name: "username",
in: "path",
required: true,
description: "The GitHub username to fetch",
schema: { type: "string" }
}],
responses: {
"200": {
description: "User data retrieved successfully",
content: {
"application/json": {
schema: {
type: "object",
properties: {
login: { type: "string" },
id: { type: "number" },
name: { type: "string" },
company: { type: "string" },
public_repos: { type: "number" }
}
}
}
}
},
"404": { description: "User not found" }
}
}
},
"/users/{username}/repos": {
get: {
operationId: "getUserRepos",
summary: "List user repositories",
description: "List public repositories for the specified user",
parameters: [
{
name: "username",
in: "path",
required: true,
description: "GitHub username",
schema: { type: "string" }
},
{
name: "type",
in: "query",
required: false,
description: "Repository type filter",
schema: {
type: "string",
enum: ["all", "owner", "member"],
default: "all"
}
},
{
name: "sort",
in: "query",
required: false,
description: "Sort repositories by",
schema: {
type: "string",
enum: ["created", "updated", "pushed", "full_name"],
default: "updated"
}
},
{
name: "per_page",
in: "query",
required: false,
description: "Number of results per page (max 100)",
schema: {
type: "integer",
minimum: 1,
maximum: 100,
default: 30
}
}
],
responses: {
"200": {
description: "Repository list retrieved successfully",
content: {
"application/json": {
schema: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
full_name: { type: "string" },
description: { type: "string" },
private: { type: "boolean" }
}
}
}
}
}
}
}
}
},
"/repos/{owner}/{repo}/issues": {
get: {
operationId: "listRepoIssues",
summary: "List repository issues",
description: "List issues in a repository",
parameters: [
{
name: "owner",
in: "path",
required: true,
description: "Repository owner",
schema: { type: "string" }
},
{
name: "repo",
in: "path",
required: true,
description: "Repository name",
schema: { type: "string" }
},
{
name: "state",
in: "query",
required: false,
description: "Issue state filter",
schema: {
type: "string",
enum: ["open", "closed", "all"],
default: "open"
}
}
],
responses: {
"200": { description: "Issues retrieved successfully" }
}
},
post: {
operationId: "createRepoIssue",
summary: "Create repository issue",
description: "Create a new issue in a repository",
parameters: [
{
name: "owner",
in: "path",
required: true,
schema: { type: "string" }
},
{
name: "repo",
in: "path",
required: true,
schema: { type: "string" }
}
],
requestBody: {
required: true,
description: "Issue details",
content: {
"application/json": {
schema: {
type: "object",
required: ["title"],
properties: {
title: {
type: "string",
description: "Issue title",
minLength: 1,
maxLength: 256
},
body: {
type: "string",
description: "Issue description"
},
assignees: {
type: "array",
items: { type: "string" },
description: "GitHub usernames to assign"
},
labels: {
type: "array",
items: { type: "string" },
description: "Labels to apply"
}
}
}
}
}
},
responses: {
"201": { description: "Issue created successfully" }
}
}
}
},
components: {
securitySchemes: {
githubAuth: {
type: "http",
scheme: "bearer",
description: "GitHub personal access token"
}
}
}
};
// Step 2: Register entire API with one call
console.log('📋 Registering GitHub API endpoints...');
server.registerOpenAPI(githubAPISchema);
// Result: All endpoints automatically become MCP tools!
// ✅ getUser - Get user information with username validation
// ✅ getUserRepos - List repositories with filtering and pagination
// ✅ listRepoIssues - List issues with state filtering
// ✅ createRepoIssue - Create new issues with full validation
// ✅ Full type safety with Zod validation schemas
// ✅ Automatic parameter extraction and templating
// ✅ Built-in retry logic and error handling
console.log('✅ Registered tools:', server.listTools().map(t => t.name));
Advanced OpenAPI Features
// Load OpenAPI schema from URL
const loadOpenAPIFromURL = async (url: string): Promise<OpenAPISchema> => {
const response = await fetch(url);
return await response.json();
};
// Load from Swagger/OpenAPI spec URL
const petStoreSchema = await loadOpenAPIFromURL('https://petstore3.swagger.io/api/v3/openapi.json');
server.registerOpenAPI(petStoreSchema);
// Load from local file
import fs from 'fs';
const localSchema: OpenAPISchema = JSON.parse(fs.readFileSync('./api-spec.json', 'utf-8'));
server.registerOpenAPI(localSchema);
// Selective registration with filtering
const parseAndFilterAPIs = (schema: OpenAPISchema, filter: (path: string, method: string) => boolean) => {
const parsedAPIs = parseOpenAPISchema(schema);
return parsedAPIs.filter(api => {
// Extract path and method from the API config
const path = api.apiConfig.uri.replace(/https?:\/\/[^\/]+/, '');
const method = api.apiConfig.method.toLowerCase();
return filter(path, method);
});
};
// Only register GET endpoints
const getAPIs = parseAndFilterAPIs(githubAPISchema, (path, method) => method === 'get');
getAPIs.forEach(api => {
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
});
📋 OpenAPI Integration Guide
The MCPaaS SDK provides comprehensive OpenAPI 3.0 integration, enabling you to register entire API suites as MCP tools with a single function call. This powerful feature transforms any OpenAPI specification into fully-functional, type-safe MCP tools with automatic validation and error handling.
🚀 OpenAPI Quick Start
import { MCPWeb, OpenAPISchema } from '@mcpweb-org/sdk';
// Initialize your MCP server
const server = new MCPWeb(config, appId, apiKey);
// Define your OpenAPI schema
const apiSchema: OpenAPISchema = {
openapi: "3.0.0",
info: { title: "User Management API", version: "1.0.0" },
servers: [{ url: "https://api.myservice.com" }],
paths: {
"/users/{id}": {
get: {
operationId: "getUser",
parameters: [{
name: "id",
in: "path",
required: true,
schema: { type: "string" }
}],
responses: { "200": { description: "User found" } }
}
}
}
};
// Register entire API with one line
server.registerOpenAPI(apiSchema);
// ✅ Result: getUser tool is now available with full type safety!
🛠️ Supported OpenAPI Features
✅ Complete HTTP Method Support
- GET, POST, PUT, DELETE, PATCH: All standard HTTP methods
- HEAD, OPTIONS, TRACE: Extended method support
- Request/Response Bodies: JSON, form data, multipart uploads
- Custom Headers: Authorization, content types, API keys
✅ Advanced Parameter Handling
- Path Parameters:
{id}
automatically becomes{{id}}
template variables - Query Parameters: Full URL query string support with validation
- Request Bodies: Complex JSON schemas with nested validation
- Header Parameters: Custom headers and authentication schemes
✅ Schema Validation System
- Primitive Types: string, number, integer, boolean with constraints
- Complex Objects: Nested objects, arrays, references (
$ref
) - Enumerations: String and numeric enum validation
- Format Validation: email, url, date, uuid, and custom formats
- Constraints: min/max length, value ranges, patterns, required fields
✅ Authentication & Security
- Bearer Token:
Authorization: Bearer {token}
- API Key: Header, query parameter, or cookie-based authentication
- Basic Auth: Username/password authentication
- OAuth2: Full OAuth2 flow support with scopes
- Custom Security: Flexible header-based authentication schemes
🎯 Production-Ready Examples
E-commerce API Integration
const ecommerceSchema: OpenAPISchema = {
openapi: "3.0.0",
info: {
title: "E-commerce API",
version: "2.1.0",
description: "Complete e-commerce backend with products, orders, and customers"
},
servers: [
{ url: "https://api.shop.com/v2", description: "Production API" },
{ url: "https://staging-api.shop.com/v2", description: "Staging Environment" }
],
paths: {
"/products": {
get: {
operationId: "listProducts",
summary: "List products with advanced filtering",
parameters: [
{
name: "category",
in: "query",
description: "Filter by product category",
schema: {
type: "string",
enum: ["electronics", "clothing", "books", "home"]
}
},
{
name: "price_min",
in: "query",
description: "Minimum price filter",
schema: { type: "number", minimum: 0, maximum: 100000 }
},
{
name: "price_max",
in: "query",
description: "Maximum price filter",
schema: { type: "number", minimum: 0, maximum: 100000 }
},
{
name: "in_stock",
in: "query",
description: "Filter by stock availability",
schema: { type: "boolean", default: true }
},
{
name: "sort",
in: "query",
description: "Sort products by field",
schema: {
type: "string",
enum: ["name", "price", "created_at", "popularity"],
default: "popularity"
}
},
{
name: "limit",
in: "query",
description: "Number of products to return",
schema: {
type: "integer",
minimum: 1,
maximum: 100,
default: 20
}
}
],
responses: {
"200": {
description: "Products retrieved successfully",
content: {
"application/json": {
schema: {
type: "object",
properties: {
products: {
type: "array",
items: { $ref: "#/components/schemas/Product" }
},
total: { type: "integer" },
page: { type: "integer" },
total_pages: { type: "integer" }
}
}
}
}
}
}
},
post: {
operationId: "createProduct",
summary: "Create new product",
requestBody: {
required: true,
content: {
"application/json": {
schema: { $ref: "#/components/schemas/CreateProductRequest" }
}
}
},
responses: {
"201": {
description: "Product created successfully",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/Product" }
}
}
},
"400": { description: "Validation error" },
"401": { description: "Authentication required" }
}
}
},
"/products/{id}": {
get: {
operationId: "getProduct",
summary: "Get product by ID",
parameters: [{
name: "id",
in: "path",
required: true,
description: "Product unique identifier",
schema: {
type: "string",
pattern: "^[0-9a-f]{24}$",
example: "507f1f77bcf86cd799439011"
}
}],
responses: {
"200": {
description: "Product retrieved successfully",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/Product" }
}
}
},
"404": { description: "Product not found" }
}
},
put: {
operationId: "updateProduct",
summary: "Update product",
parameters: [{
name: "id",
in: "path",
required: true,
schema: { type: "string", pattern: "^[0-9a-f]{24}$" }
}],
requestBody: {
required: true,
content: {
"application/json": {
schema: { $ref: "#/components/schemas/UpdateProductRequest" }
}
}
},
responses: {
"200": { description: "Product updated successfully" },
"404": { description: "Product not found" }
}
},
delete: {
operationId: "deleteProduct",
summary: "Delete product",
parameters: [{
name: "id",
in: "path",
required: true,
schema: { type: "string", pattern: "^[0-9a-f]{24}$" }
}],
responses: {
"204": { description: "Product deleted successfully" },
"404": { description: "Product not found" }
}
}
},
"/orders": {
post: {
operationId: "createOrder",
summary: "Create new order",
requestBody: {
required: true,
content: {
"application/json": {
schema: {
type: "object",
required: ["customer_id", "items"],
properties: {
customer_id: {
type: "string",
description: "Customer identifier"
},
items: {
type: "array",
minItems: 1,
maxItems: 50,
items: {
type: "object",
required: ["product_id", "quantity"],
properties: {
product_id: { type: "string" },
quantity: {
type: "integer",
minimum: 1,
maximum: 100
},
price_override: {
type: "number",
minimum: 0,
description: "Override product price for this order"
}
}
}
},
shipping_address: {
type: "object",
required: ["street", "city", "country"],
properties: {
street: { type: "string", minLength: 1, maxLength: 255 },
city: { type: "string", minLength: 1, maxLength: 100 },
state: { type: "string", maxLength: 100 },
postal_code: { type: "string", maxLength: 20 },
country: {
type: "string",
minLength: 2,
maxLength: 2,
description: "ISO 3166-1 alpha-2 country code"
}
}
},
coupon_code: {
type: "string",
pattern: "^[A-Z0-9]{4,12}$",
description: "Promotional coupon code"
}
}
}
}
}
},
responses: {
"201": { description: "Order created successfully" },
"400": { description: "Invalid order data" }
}
}
}
},
components: {
schemas: {
Product: {
type: "object",
required: ["id", "name", "price", "category"],
properties: {
id: {
type: "string",
description: "Unique product identifier"
},
name: {
type: "string",
minLength: 1,
maxLength: 255,
description: "Product name"
},
description: {
type: "string",
maxLength: 2000,
description: "Product description"
},
price: {
type: "number",
minimum: 0,
maximum: 999999.99,
description: "Product price in USD"
},
category: {
type: "string",
enum: ["electronics", "clothing", "books", "home"],
description: "Product category"
},
in_stock: {
type: "boolean",
default: true,
description: "Whether product is in stock"
},
stock_quantity: {
type: "integer",
minimum: 0,
description: "Available stock quantity"
},
tags: {
type: "array",
items: {
type: "string",
minLength: 1,
maxLength: 50
},
maxItems: 10,
uniqueItems: true,
description: "Product tags for search and categorization"
},
images: {
type: "array",
items: {
type: "string",
format: "uri",
description: "Image URL"
},
maxItems: 10,
description: "Product image URLs"
},
created_at: {
type: "string",
format: "date-time",
description: "Product creation timestamp"
},
updated_at: {
type: "string",
format: "date-time",
description: "Last update timestamp"
}
}
},
CreateProductRequest: {
type: "object",
required: ["name", "price", "category"],
properties: {
name: {
type: "string",
minLength: 1,
maxLength: 255
},
description: {
type: "string",
maxLength: 2000
},
price: {
type: "number",
minimum: 0,
maximum: 999999.99
},
category: {
type: "string",
enum: ["electronics", "clothing", "books", "home"]
},
stock_quantity: {
type: "integer",
minimum: 0,
default: 0
},
tags: {
type: "array",
items: {
type: "string",
minLength: 1,
maxLength: 50
},
maxItems: 10,
uniqueItems: true
}
}
},
UpdateProductRequest: {
type: "object",
properties: {
name: { type: "string", minLength: 1, maxLength: 255 },
description: { type: "string", maxLength: 2000 },
price: { type: "number", minimum: 0, maximum: 999999.99 },
category: {
type: "string",
enum: ["electronics", "clothing", "books", "home"]
},
in_stock: { type: "boolean" },
stock_quantity: { type: "integer", minimum: 0 },
tags: {
type: "array",
items: { type: "string", minLength: 1, maxLength: 50 },
maxItems: 10,
uniqueItems: true
}
}
}
},
securitySchemes: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
description: "JWT access token from /auth/login endpoint"
},
apiKeyAuth: {
type: "apiKey",
in: "header",
name: "X-API-Key",
description: "API key for service authentication"
}
}
},
security: [
{ bearerAuth: [] },
{ apiKeyAuth: [] }
]
};
// Register the complete e-commerce API
console.log('🛍️ Registering E-commerce API...');
server.registerOpenAPI(ecommerceSchema);
console.log('✅ Registered Tools:');
server.listTools().forEach(tool => {
console.log(` 🔧 ${tool.name}: ${tool.description}`);
});
// Result: Complete e-commerce API suite available as MCP tools!
// ✅ listProducts - Advanced product filtering and pagination
// ✅ createProduct - Product creation with validation
// ✅ getProduct - Product retrieval by ID
// ✅ updateProduct - Product updates with partial data
// ✅ deleteProduct - Product deletion
// ✅ createOrder - Complex order creation with items and shipping
// ✅ Full type safety with comprehensive validation
// ✅ Automatic authentication handling
📚 Loading Schemas from Different Sources
From Remote APIs
// Load from public API specifications
const loadRemoteOpenAPI = async (url: string): Promise<OpenAPISchema> => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch OpenAPI spec: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error(`Error loading OpenAPI from ${url}:`, error);
throw error;
}
};
// Popular API examples
const APIs = {
petStore: 'https://petstore3.swagger.io/api/v3/openapi.json',
github: 'https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json',
stripe: 'https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json',
slack: 'https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json'
};
// Load and register Stripe API
try {
const stripeSchema = await loadRemoteOpenAPI(APIs.stripe);
server.registerOpenAPI(stripeSchema);
console.log('✅ Stripe API registered successfully');
} catch (error) {
console.error('❌ Failed to load Stripe API:', error.message);
}
// Load multiple APIs in parallel
const loadMultipleAPIs = async () => {
const results = await Promise.allSettled([
loadRemoteOpenAPI(APIs.petStore),
loadRemoteOpenAPI(APIs.github)
]);
results.forEach((result, index) => {
const apiName = Object.keys(APIs)[index];
if (result.status === 'fulfilled') {
server.registerOpenAPI(result.value);
console.log(`✅ ${apiName} API registered`);
} else {
console.error(`❌ Failed to load ${apiName} API:`, result.reason);
}
});
};
await loadMultipleAPIs();
From Local Files
import fs from 'fs/promises';
import path from 'path';
// Load from JSON file
const loadLocalOpenAPI = async (filePath: string): Promise<OpenAPISchema> => {
try {
const content = await fs.readFile(filePath, 'utf-8');
return JSON.parse(content);
} catch (error) {
console.error(`Error loading local OpenAPI file ${filePath}:`, error);
throw error;
}
};
// Load from YAML file (requires js-yaml package)
import yaml from 'js-yaml';
const loadOpenAPIYAML = async (filePath: string): Promise<OpenAPISchema> => {
try {
const content = await fs.readFile(filePath, 'utf-8');
return yaml.load(content) as OpenAPISchema;
} catch (error) {
console.error(`Error loading YAML OpenAPI file ${filePath}:`, error);
throw error;
}
};
// Load from different file formats
const apiPaths = {
json: './specs/my-api.json',
yaml: './specs/my-api.yaml',
remote: 'https://api.example.com/openapi.json'
};
// Batch load with error handling
const loadAllAPIs = async () => {
for (const [format, apiPath] of Object.entries(apiPaths)) {
try {
let schema: OpenAPISchema;
if (format === 'json') {
schema = await loadLocalOpenAPI(apiPath);
} else if (format === 'yaml') {
schema = await loadOpenAPIYAML(apiPath);
} else {
schema = await loadRemoteOpenAPI(apiPath);
}
server.registerOpenAPI(schema);
console.log(`✅ ${format.toUpperCase()} API loaded from ${apiPath}`);
} catch (error) {
console.error(`❌ Failed to load ${format} API from ${apiPath}:`, error.message);
// Continue loading other APIs even if one fails
}
}
};
await loadAllAPIs();
🔍 Advanced Filtering and Customization
Selective API Registration
import { parseOpenAPISchema } from '@mcpweb-org/sdk';
// Parse schema without registering
const parsedAPIs = parseOpenAPISchema(ecommerceSchema);
// Filter by HTTP method
const readOnlyAPIs = parsedAPIs.filter(api =>
api.apiConfig.method.toUpperCase() === 'GET'
);
// Filter by path pattern
const productAPIs = parsedAPIs.filter(api =>
api.apiConfig.uri.includes('/products')
);
// Filter by operation ID pattern
const userManagementAPIs = parsedAPIs.filter(api =>
api.name.toLowerCase().includes('user') ||
api.name.toLowerCase().includes('customer')
);
// Advanced filtering with custom logic
const criticalAPIs = parsedAPIs.filter(api => {
const isMutating = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(
api.apiConfig.method.toUpperCase()
);
const isUserFacing = api.apiConfig.uri.includes('/users') ||
api.apiConfig.uri.includes('/orders');
const requiresAuth = api.toolConfig.inputSchema.properties?.authorization;
return isMutating && isUserFacing && requiresAuth;
});
// Register filtered APIs
console.log('📋 Registering filtered API subsets...');
readOnlyAPIs.forEach(api => {
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
console.log(`✅ Read-only: ${api.name}`);
});
productAPIs.forEach(api => {
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
console.log(`✅ Product API: ${api.name}`);
});
API Customization and Enhancement
// Enhanced API registration with custom modifications
const enhanceAPIs = (schemas: OpenAPISchema[], customizations: any[]) => {
schemas.forEach((schema, index) => {
const parsedAPIs = parseOpenAPISchema(schema);
const customization = customizations[index] || {};
parsedAPIs.forEach(api => {
// Add custom headers
api.apiConfig.headers = {
...api.apiConfig.headers,
'User-Agent': 'MCPaaS-SDK/2.1.0',
'X-Client-Version': '1.0.0',
'X-Request-ID': '{{requestId}}',
...customization.headers
};
// Add authentication
if (process.env.API_TOKEN) {
api.apiConfig.headers['Authorization'] = `Bearer ${process.env.API_TOKEN}`;
}
// Add API key from environment
if (process.env.API_KEY && customization.apiKeyHeader) {
api.apiConfig.headers[customization.apiKeyHeader] = process.env.API_KEY;
}
// Customize timeout based on endpoint
if (api.apiConfig.uri.includes('/reports') ||
api.apiConfig.uri.includes('/analytics')) {
api.apiConfig.timeout = 60000; // 60 seconds for slow endpoints
} else if (api.apiConfig.method.toUpperCase() === 'GET') {
api.apiConfig.timeout = 15000; // 15 seconds for read operations
} else {
api.apiConfig.timeout = 30000; // 30 seconds for write operations
}
// Add retry configuration
api.apiConfig.retryConfig = {
maxRetries: customization.maxRetries || 3,
retryDelay: customization.retryDelay || 1000,
retryOn: [408, 429, 500, 502, 503, 504]
};
// Add custom validation
if (customization.additionalValidation) {
// Extend Zod schema with custom validation
const originalSchema = api.toolConfig.inputSchema;
api.toolConfig.inputSchema = originalSchema.refine(
customization.additionalValidation,
{ message: customization.validationMessage || 'Custom validation failed' }
);
}
// Add custom error handling
if (customization.errorTransform) {
const originalErrorTransform = api.apiConfig.errorTransform;
api.apiConfig.errorTransform = (error) => {
const transformed = customization.errorTransform(error);
return originalErrorTransform ? originalErrorTransform(transformed) : transformed;
};
}
// Register the enhanced API
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
console.log(`🔧 Enhanced: ${api.name} with custom settings`);
});
});
};
// Apply customizations
const customizations = [
{
headers: { 'X-Service': 'ecommerce' },
apiKeyHeader: 'X-Ecommerce-Key',
maxRetries: 5,
retryDelay: 2000,
additionalValidation: (data: any) => {
return data.price === undefined || data.price >= 0;
},
validationMessage: 'Price must be non-negative',
errorTransform: (error: any) => ({
...error,
context: 'E-commerce API',
timestamp: new Date().toISOString()
})
}
];
enhanceAPIs([ecommerceSchema], customizations);
🐛 Error Handling & Debugging
Comprehensive Error Management
// Enable detailed logging
process.env.DEBUG = 'mcpaas:openapi,mcpaas:validation,mcpaas:http';
const registerWithErrorHandling = async (schema: OpenAPISchema, schemaName: string) => {
console.log(`🔄 Registering ${schemaName} API...`);
try {
// Validate schema first
if (!schema.openapi || !schema.info || !schema.paths) {
throw new Error('Invalid OpenAPI schema: missing required fields');
}
// Check for supported OpenAPI version
if (!schema.openapi.startsWith('3.0') && !schema.openapi.startsWith('3.1')) {
console.warn(`⚠️ OpenAPI version ${schema.openapi} may not be fully supported`);
}
// Register the API
server.registerOpenAPI(schema);
const registeredTools = server.listTools();
console.log(`✅ ${schemaName} registered successfully!`);
console.log(`📊 Total tools: ${registeredTools.length}`);
// Log registered endpoints
registeredTools
.filter(tool => tool.name.includes(schemaName.toLowerCase()) ||
tool.description?.includes(schemaName))
.forEach(tool => {
console.log(` 🔧 ${tool.name}: ${tool.description}`);
});
} catch (error) {
console.error(`❌ Failed to register ${schemaName}:`, error.message);
console.error('📋 Error details:', error);
// Attempt individual API registration for debugging
try {
console.log(`🔍 Attempting individual API registration for ${schemaName}...`);
const parsedAPIs = parseOpenAPISchema(schema);
let successCount = 0;
let failureCount = 0;
for (const api of parsedAPIs) {
try {
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
console.log(` ✅ ${api.name}`);
successCount++;
} catch (apiError) {
console.error(` ❌ ${api.name}: ${apiError.message}`);
failureCount++;
}
}
console.log(`📈 Registration Summary for ${schemaName}:`);
console.log(` ✅ Successful: ${successCount}`);
console.log(` ❌ Failed: ${failureCount}`);
} catch (parseError) {
console.error(`❌ Could not parse ${schemaName} schema:`, parseError.message);
}
}
};
// Register multiple APIs with comprehensive error handling
const apiRegistrations = [
{ schema: ecommerceSchema, name: 'E-commerce' },
{ schema: await loadRemoteOpenAPI(APIs.petStore).catch(() => null), name: 'PetStore' },
{ schema: await loadLocalOpenAPI('./my-api.json').catch(() => null), name: 'Custom' }
];
for (const registration of apiRegistrations) {
if (registration.schema) {
await registerWithErrorHandling(registration.schema, registration.name);
} else {
console.warn(`⚠️ Skipping ${registration.name} - schema not available`);
}
}
Validation and Testing
// Validate APIs before registration
const validateOpenAPISchema = (schema: OpenAPISchema): string[] => {
const issues: string[] = [];
// Check required fields
if (!schema.openapi) issues.push('Missing openapi version');
if (!schema.info?.title) issues.push('Missing API title');
if (!schema.info?.version) issues.push('Missing API version');
if (!schema.paths || Object.keys(schema.paths).length === 0) {
issues.push('No API paths defined');
}
// Check paths
Object.entries(schema.paths || {}).forEach(([path, pathItem]) => {
Object.entries(pathItem || {}).forEach(([method, operation]) => {
if (typeof operation === 'object' && operation !== null) {
if (!operation.operationId) {
issues.push(`Missing operationId for ${method.toUpperCase()} ${path}`);
}
if (!operation.responses) {
issues.push(`Missing responses for ${method.toUpperCase()} ${path}`);
}
}
});
});
return issues;
};
// Test API registration
const testAPIRegistration = async (schema: OpenAPISchema, schemaName: string) => {
console.log(`🧪 Testing ${schemaName} API registration...`);
// Validate schema
const issues = validateOpenAPISchema(schema);
if (issues.length > 0) {
console.warn(`⚠️ Schema validation issues for ${schemaName}:`);
issues.forEach(issue => console.warn(` - ${issue}`));
}
// Test parsing
try {
const parsedAPIs = parseOpenAPISchema(schema);
console.log(`✅ Successfully parsed ${parsedAPIs.length} APIs`);
// Test each API configuration
parsedAPIs.forEach((api, index) => {
console.log(` 🔧 API ${index + 1}: ${api.name}`);
console.log(` Method: ${api.apiConfig.method}`);
console.log(` URL: ${api.apiConfig.uri}`);
console.log(` Parameters: ${Object.keys(api.toolConfig.inputSchema.properties || {}).length}`);
});
return true;
} catch (error) {
console.error(`❌ Failed to parse ${schemaName} schema:`, error.message);
return false;
}
};
// Test before registering
const testResult = await testAPIRegistration(ecommerceSchema, 'E-commerce');
if (testResult) {
await registerWithErrorHandling(ecommerceSchema, 'E-commerce');
}
🎯 Best Practices
1. Schema Design Guidelines
// ✅ DO: Use clear, descriptive operationIds
{
"operationId": "getUserProfile", // Clear and specific
"summary": "Get user profile information", // Descriptive summary
"description": "Retrieve detailed profile information for a specific user including preferences and settings"
}
// ❌ DON'T: Use generic or missing operationIds
{
"operationId": "get1", // Too generic
// Missing summary and description
}
// ✅ DO: Provide comprehensive parameter documentation
"parameters": [{
"name": "userId",
"in": "path",
"required": true,
"description": "Unique identifier for the user account. Must be a valid ObjectId.",
"schema": {
"type": "string",
"pattern": "^[0-9a-f]{24}$",
"example": "507f1f77bcf86cd799439011"
}
}]
// ✅ DO: Define detailed response schemas
"responses": {
"200": {
"description": "User profile retrieved successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["id", "email", "name"],
"properties": {
"id": { "type": "string" },
"email": { "type": "string", "format": "email" },
"name": { "type": "string", "minLength": 1 },
"preferences": { "$ref": "#/components/schemas/UserPreferences" }
}
}
}
}
},
"404": {
"description": "User not found",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Error" }
}
}
}
}
2. Performance Optimization
// ✅ DO: Implement efficient batch operations
const registerMultipleAPIsEfficiently = async (schemas: OpenAPISchema[]) => {
// Parse all schemas first
const allParsedAPIs = schemas.flatMap(schema => {
try {
return parseOpenAPISchema(schema);
} catch (error) {
console.error(`Failed to parse schema:`, error.message);
return [];
}
});
// Group by base URL for connection pooling
const apisByBaseUrl = allParsedAPIs.reduce((groups, api) => {
const baseUrl = api.apiConfig.uri.split('/').slice(0, 3).join('/');
if (!groups[baseUrl]) groups[baseUrl] = [];
groups[baseUrl].push(api);
return groups;
}, {} as Record<string, typeof allParsedAPIs>);
// Register APIs grouped by base URL
for (const [baseUrl, apis] of Object.entries(apisByBaseUrl)) {
console.log(`🔗 Registering ${apis.length} APIs for ${baseUrl}...`);
// Set shared connection settings for APIs from same base URL
const sharedConfig = {
timeout: 30000,
retryConfig: { maxRetries: 3, retryDelay: 1000 },
headers: { 'User-Agent': 'MCPaaS-SDK/2.1.0' }
};
apis.forEach(api => {
api.apiConfig = { ...api.apiConfig, ...sharedConfig };
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
});
console.log(`✅ Registered ${apis.length} APIs for ${baseUrl}`);
}
};
3. Security Best Practices
// ✅ DO: Implement comprehensive security
const secureAPIRegistration = (schema: OpenAPISchema, credentials: any) => {
const parsedAPIs = parseOpenAPISchema(schema);
parsedAPIs.forEach(api => {
// Add authentication headers
api.apiConfig.headers = {
...api.apiConfig.headers,
'Authorization': `Bearer ${credentials.token}`,
'X-API-Key': credentials.apiKey,
'X-Client-ID': credentials.clientId
};
// Add request/response interceptors for security
api.apiConfig.requestInterceptor = (config) => {
// Add timestamp and nonce for request signing
config.headers['X-Timestamp'] = Date.now().toString();
config.headers['X-Nonce'] = Math.random().toString(36);
// Log sensitive operations
if (['POST', 'PUT', 'DELETE'].includes(config.method.toUpperCase())) {
console.log(`🔒 Secure operation: ${config.method} ${config.url}`);
}
return config;
};
api.apiConfig.responseInterceptor = (response, error) => {
// Sanitize sensitive data from error messages
if (error && error.response?.data?.message) {
error.response.data.message = error.response.data.message.replace(
/api[_-]?key|token|secret|password/gi,
'[REDACTED]'
);
}
return error ? Promise.reject(error) : response;
};
// Rate limiting configuration
api.apiConfig.rateLimitConfig = {
maxRequests: 100,
windowMs: 60000, // 1 minute
skipSuccessfulRequests: false
};
server.registerAPI(api.name, api.toolConfig, api.apiConfig);
});
};
This comprehensive OpenAPI integration system makes the MCPaaS SDK incredibly powerful for API management and integration. You can now register entire API suites with full type safety, validation, and professional-grade error handling!
## Installation
```bash
npm install @mcpaas/sdk
# or
yarn add @mcpaas/sdk
Core Concepts
MCPWeb
The main server class that replaces the official MCP SDK:
import { MCPWeb } from '@mcpaas/sdk';
const server = new MCPWeb(
{
name: 'my-server',
version: '1.0.0'
},
'app-id', // Your MCPaaS app ID
'api-key' // Your MCPaaS API key
);
MCPWebExpress
Drop-in replacement for Express servers with full MCP support. MCPWebExpress mounts MCP over Express, giving you all the Express functionality you know with automatic MCP protocol integration:
import { MCPWebExpress } from '@mcpaas/sdk';
const server = new MCPWebExpress({
mcpWeb: mcpServer, // Your MCPWeb instance
options: {
port: 3000,
host: 'localhost',
cors: true,
json: true
}
});
// Express.js-style routing
server.get('/api/users', (req, res) => {
res.json([{ id: 1, name: 'John' }]);
});
server.post('/api/users', (req, res) => {
res.json({ message: 'User created', data: req.body });
});
// Start the server
await server.start();
MCPWebExpress Features:
- 🚀 Drop-in Express Replacement: Seamlessly replace your existing Express servers
- 🛣️ Full Express Compatibility: All Express.js routing and middleware works as expected
- 🔌 MCP Integration: Automatic MCP protocol endpoints mounted on your Express server
- 🌐 CORS Support: Built-in cross-origin resource sharing
- 📝 JSON Parsing: Automatic request body parsing
- 🏥 Health Checks: Built-in
/health
and/status
endpoints - ⚡ Middleware Support: Complete Express.js middleware ecosystem compatibility
MCPWebLog
Lightweight logging utility with toggle capability:
import { MCPWebLog } from '@mcpaas/sdk';
const logger = new MCPWebLog({ disable: false });
logger.log('Server started');
logger.log('Processing request:', requestData);
MCPWebLog Features:
- 🔇 Toggle Logging: Enable/disable logging globally
- 🎯 Simple API: Familiar console.log-style interface
- 📊 Performance: Minimal overhead when disabled
- 🔧 Debug Mode: Perfect for development vs production
RegisterAPI Method
Transform any HTTP API into an MCP tool with automatic integration:
// Register external APIs as MCP tools
server.registerAPI('weather-api', {
title: 'Weather API',
description: 'Get current weather data',
inputSchema: {
city: z.string().describe('City name'),
units: z.enum(['metric', 'imperial']).optional()
}
}, {
method: 'GET',
url: 'https://api.openweathermap.org/data/2.5/weather',
headers: {
'Authorization': `Bearer ${API_KEY}`
},
queryParams: {
q: '{{city}}', // Template from input
units: '{{units}}'
}
});
// Register internal APIs
server.registerAPI('user-service', {
title: 'User Management',
description: 'Create new user account',
inputSchema: {
name: z.string(),
email: z.string().email()
}
}, {
method: 'POST',
url: 'http://localhost:8080/api/users',
headers: {
'Content-Type': 'application/json'
},
body: {
name: '{{name}}',
email: '{{email}}',
created_at: '{{$now}}' // Built-in template functions
}
});
RegisterAPI Features:
- 🌐 Any HTTP API: Support for GET, POST, PUT, DELETE, PATCH
- 📝 Template System: Dynamic parameter injection with
{{param}}
- 🔧 Built-in Functions:
{{$now}}
,{{$uuid}}
,{{$timestamp}}
- 🛡️ Type Safety: Full TypeScript validation for inputs and outputs
- 📊 Auto Analytics: Automatic performance tracking and error monitoring
- 🔁 Retry Logic: Built-in retry mechanisms for failed requests
- 🏷️ Header Support: Custom headers, authentication, content types
SDK Usage (Legacy API Client)
For platform management operations:
import { MCPaaSClient } from '@mcpaas/sdk/client';
const client = new MCPaaSClient({
apiKey: 'your-api-key',
baseUrl: 'https://api.mcpaas.dev', // Optional, defaults to production
timeout: 30000 // Optional, defaults to 10 seconds
});
Tool Registration
Register tools with automatic analytics tracking:
server.registerTool('tool-name', toolConfig, async (args) => {
// Your tool implementation
// Analytics automatically tracked:
// - Execution time
// - Input/output sizes
// - Success/failure
// - Memory usage
return { content: [{ type: 'text', text: 'response' }] };
});
Resource Registration
Register resources with access pattern tracking:
server.registerResource('resource-name', 'resource://uri', resourceConfig, async () => {
// Analytics tracked:
// - Access frequency
// - Response sizes
// - Cache effectiveness
return { content: 'resource data' };
});
Prompt Registration
Register prompts with generation analytics:
server.registerPrompt('prompt-name', promptConfig, async (args) => {
// Analytics tracked:
// - Generation time
// - Template complexity
// - Usage patterns
return { messages: [...] };
});
Analytics Overview
Analytics are automatically collected for every operation:
// Get analytics collector for custom tracking
const analytics = server.analyticsCollector;
// Track custom metrics
analytics.trackPerformance({
customMetrics: {
databaseQueries: 5,
cacheHitRate: 0.85
}
});
// Track tool execution manually
const eventId = analytics.trackToolStart('custom-tool');
// ... perform work ...
analytics.trackToolComplete(eventId, 'custom-tool', {
customMetrics: { accuracy: 0.95 }
});
Examples
Complete MCPWebExpress Server
import { MCPWeb, MCPWebExpress } from '@mcpaas/sdk';
import { z } from 'zod';
// Setup MCPaaS server with tools and resources
const setupMCPServer = () => {
const mcpWeb = new MCPWeb({
name: "mcpaas-express-server",
description: "High-performance server with MCPWebExpress",
version: "1.0.0",
capabilities: {
tools: true,
resources: true,
prompts: true,
},
}, 'your-app-id', 'your-api-key');
// Register calculation tool
mcpWeb.registerTool('calculate', {
title: 'Calculator',
description: 'Perform arithmetic calculations',
inputSchema: {
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
a: z.number(),
b: z.number(),
},
}, async ({ operation, a, b }) => {
let result: number;
switch (operation) {
case 'add': result = a + b; break;
case 'subtract': result = a - b; break;
case 'multiply': result = a * b; break;
case 'divide':
if (b === 0) throw new Error('Division by zero');
result = a / b;
break;
}
return {
content: [{
type: 'text',
text: `${a} ${operation} ${b} = ${result}`,
}],
};
});
// Register weather API as MCP tool
mcpWeb.registerAPI('weather', {
title: 'Weather API',
description: 'Get current weather',
inputSchema: {
city: z.string().describe('City name'),
units: z.enum(['metric', 'imperial']).default('metric')
}
}, {
method: 'GET',
url: 'https://api.openweathermap.org/data/2.5/weather',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
queryParams: {
q: '{{city}}',
units: '{{units}}'
}
});
return mcpWeb;
};
// Create MCPWebExpress server
const server = new MCPWebExpress({
mcpWeb: setupMCPServer(),
options: {
port: 3000,
host: 'localhost',
cors: true,
json: true
}
});
// Add REST API routes
server.get('/api/users', (req, res) => {
res.json([
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
]);
});
server.post('/api/users', (req, res) => {
const { name, email } = req.body;
const newUser = { id: Date.now(), name, email };
res.json({ message: 'User created', user: newUser });
});
// Add middleware for logging
server.use('/api', (req, res, next) => {
console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
next();
});
// Start server
await server.start();
console.log('🚀 MCPWebExpress server running on http://localhost:3000');
MCPWebLog Usage Example
import { MCPWebLog } from '@mcpaas/sdk';
// Create logger (disable in production)
const logger = new MCPWebLog({
disable: process.env.NODE_ENV === 'production'
});
// Use throughout your application
logger.log('Server starting...');
logger.log('Processing request:', { userId: 123, action: 'login' });
logger.log('Database connected successfully');
// Conditional logging
if (process.env.DEBUG) {
const debugLogger = new MCPWebLog({ disable: false });
debugLogger.log('Debug information:', complexObject);
}
RegisterAPI Advanced Examples
// GitHub API integration
server.registerAPI('github-repos', {
title: 'GitHub Repositories',
description: 'Get user repositories from GitHub',
inputSchema: {
username: z.string(),
type: z.enum(['all', 'public', 'private']).default('public'),
sort: z.enum(['created', 'updated', 'pushed', 'full_name']).default('updated')
}
}, {
method: 'GET',
url: 'https://api.github.com/users/{{username}}/repos',
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'MCPaaS-SDK'
},
queryParams: {
type: '{{type}}',
sort: '{{sort}}',
per_page: '50'
}
});
// Internal microservice with authentication
server.registerAPI('user-profile', {
title: 'User Profile Service',
description: 'Update user profile information',
inputSchema: {
userId: z.string(),
name: z.string().optional(),
email: z.string().email().optional(),
avatar: z.string().url().optional()
}
}, {
method: 'PATCH',
url: 'http://user-service:8080/api/users/{{userId}}',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{$env.USER_SERVICE_TOKEN}}',
'X-Request-ID': '{{$uuid}}'
},
body: {
name: '{{name}}',
email: '{{email}}',
avatar: '{{avatar}}',
updated_at: '{{$now}}',
updated_by: 'mcpaas-sdk'
}
});
// Database API with custom error handling
server.registerAPI('database-query', {
title: 'Database Query',
description: 'Execute SQL queries safely',
inputSchema: {
table: z.string(),
filters: z.record(z.any()).optional(),
limit: z.number().max(1000).default(100)
}
}, {
method: 'POST',
url: 'http://db-proxy:3000/query',
headers: {
'Content-Type': 'application/json',
'X-API-Key': '{{$env.DB_API_KEY}}'
},
body: {
query: 'SELECT * FROM {{table}} {{#if filters}}WHERE {{filters}} {{/if}}LIMIT {{limit}}',
timestamp: '{{$timestamp}}'
},
timeout: 30000,
retries: 3
});
Basic Calculator Tool
import { MCPWeb } from '@mcpaas/sdk';
const server = new MCPWeb({
name: 'calculator',
version: '1.0.0'
}, 'app-id', 'api-key');
server.registerTool('add', {
title: 'Add Numbers',
description: 'Add two numbers together',
inputSchema: {
a: z.number().describe('First number'),
b: z.number().describe('Second number')
}
}, async ({ a, b }) => {
const result = a + b;
return {
content: [{
type: 'text',
text: `${a} + ${b} = ${result}`
}]
};
});
await server.start();
Database Resource
import { MCPServer } from '@mcpaas/sdk';
const server = new MCPServer({
name: 'database-server',
version: '1.0.0'
}, 'app-id', 'api-key');
server.registerResource('users', 'db://users', {
name: 'users',
description: 'User database',
mimeType: 'application/json'
}, async () => {
const users = await fetchUsersFromDatabase();
return {
content: JSON.stringify(users),
mimeType: 'application/json'
};
});
server.start();
Custom Analytics
import { MCPServer } from '@mcpaas/sdk';
const server = new MCPServer({
name: 'ai-service',
version: '1.0.0'
}, 'app-id', 'api-key');
server.registerTool('generate', {
name: 'generate',
description: 'Generate AI content',
inputSchema: {
type: 'object',
properties: {
prompt: { type: 'string' }
}
}
}, async (args) => {
const analytics = server.analyticsCollector;
const startTime = Date.now();
const content = await generateAIContent(args.prompt);
const duration = Date.now() - startTime;
// Track custom business metrics
analytics.trackPerformance({
customMetrics: {
promptLength: args.prompt.length,
responseLength: content.length,
generationTime: duration,
modelConfidence: 0.87
}
});
return {
content: [{
type: 'text',
text: content
}]
};
});
server.start();
📊 Analytics & Observability
The MCPaaS SDK includes a comprehensive analytics system built with a flat schema design optimized for BigQuery and real-time dashboards.
📈 Analytics Features
Automatic Event Tracking
- Tool Execution: Performance, success rates, input/output sizes, memory usage
- Resource Access: Usage patterns, cache hit rates, content types, network latency
- Prompt Generation: Template complexity, generation times, variable counts
- Session Management: Duration, request counts, error rates, concurrent users
- Server Health: CPU usage, memory consumption, connection metrics, uptime
Custom Business Metrics
// Track custom metrics in tools
server.registerTool('business-logic', config, async (args) => {
const analytics = server.analyticsCollector;
// Track business KPIs
analytics.trackEvent({
eventType: 'performance_metric',
performanceCustomMetricsJson: JSON.stringify({
conversionRate: 0.85,
customerSatisfaction: 4.2,
processingAccuracy: 0.97,
businessValue: 1250.50
})
});
return result;
});
Real-time Performance Monitoring
// Monitor server performance
analytics.trackEvent({
eventType: 'performance_metric',
performanceCpuUsagePercent: 45.2,
performanceMemoryUsageMB: 256,
performanceActiveConnections: 12,
performanceRequestsPerSecond: 35.8,
performanceAverageResponseTime: 120
});
📊 Analytics Event Types
The SDK tracks these event types automatically:
Tool Events
tool_call_started
- Tool execution beginstool_call_completed
- Successful tool completiontool_call_failed
- Tool execution failedtool_call_timeout
- Tool execution timed out
Resource Events
resource_read_started
- Resource access beginsresource_read_completed
- Successful resource readresource_read_failed
- Resource access failed
Session Events
session_initialized
- New MCP session createdsession_closed
- Session ended normallysession_timeout
- Session timed out
Server Events
server_started
- Server initialization completeserver_stopped
- Server shutdownserver_error
- Server-level error occurred
Performance Events
performance_metric
- General performance datamemory_usage
- Memory consumption snapshotcpu_usage
- CPU utilization data
🔧 Analytics Configuration
const analytics = server.analyticsCollector;
// Configure batch behavior
analytics.configure({
batchSize: 100, // Events per batch (default: 5)
flushInterval: 60000, // Flush interval in ms (default: 30000)
maxEventsInMemory: 5000, // Memory limit (default: 10000)
maxRetries: 5, // Retry attempts (default: 3)
retryDelay: 2000, // Retry delay in ms (default: 1000)
enabled: true // Enable/disable analytics
});
// Manual flush
await analytics.flush();
// Disable analytics temporarily
await analytics.disable();
// Re-enable analytics
analytics.enable();
� Flat Schema Design
All analytics events use a flat schema optimized for analytical processing:
interface FlatAnalyticsEvent {
// Event Identity
eventId: string;
eventType: MCPEventType;
timestamp: string;
// Server Context
serverId: string;
serverName: string;
serverVersion: string;
appId: string;
// Tool Metrics (flattened)
toolName?: string;
toolDuration?: number;
toolSuccess?: boolean;
toolInputSize?: number;
toolOutputSize?: number;
toolMemoryUsed?: number;
toolCustomMetricsJson?: string;
// Resource Metrics (flattened)
resourceName?: string;
resourceUri?: string;
resourceDuration?: number;
resourceContentSize?: number;
resourceCacheHit?: boolean;
// Performance Metrics (flattened)
performanceCpuUsagePercent?: number;
performanceMemoryUsageMB?: number;
performanceActiveConnections?: number;
performanceRequestsPerSecond?: number;
performanceCustomMetricsJson?: string;
// And 50+ more specific fields...
}
📊 Usage Analytics
// Get server statistics
const stats = server.getStats();
console.log('📊 Server Stats:', {
toolsRegistered: stats.toolsCount,
resourcesRegistered: stats.resourcesCount,
isConnected: stats.isConnected,
platformIntegration: stats.platformIntegration
});
// List all registered components
console.log('🛠️ Tools:', server.listTools());
console.log('📚 Resources:', server.listResources());
console.log('💬 Prompts:', server.listPrompts());
See ANALYTICS.md for comprehensive analytics documentation.
API Reference
MCPWeb Class
Constructor
new MCPWeb(
serverConfig: MCPServerConfig,
serverId: string,
apiKey: string,
disableLogging?: boolean
)
Core Methods
registerTool(name, config, handler)
- Register MCP tool with analyticsregisterResource(name, uri, config, handler)
- Register MCP resourceregisterPrompt(name, config, handler)
- Register MCP promptregisterAPI(name, config, apiSpec)
- Transform HTTP API into MCP toolregisterOpenAPI(openApiSchema)
- Bulk register APIs from OpenAPI schemaconnect(transport)
- Connect to MCP transportclose()
- Close connection and cleanup
HTTP Server Methods
start(options)
- Start HTTP server with CORS and middlewarestop()
- Stop HTTP server
Information Methods
getStats()
- Get server statisticslistTools()
- Get registered tools summarylistResources()
- Get registered resources summarylistPrompts()
- Get registered prompts summarygetServer()
- Get underlying server instancegetTools()
- Get tools Map with handlersgetResources()
- Get resources Map with handlersgetPrompts()
- Get prompts Map with handlers
MCPWebExpress Class
Constructor
new MCPWebExpress({
mcpWeb: MCPWeb, // MCP server instance
options: {
port: number, // Server port (default: 3000)
host?: string, // Bind host (default: 'localhost')
cors?: boolean, // Enable CORS (default: true)
json?: boolean // Enable JSON parsing (default: true)
}
})
HTTP Methods
get(path, handler)
- Register GET routepost(path, handler)
- Register POST routeput(path, handler)
- Register PUT routedelete(path, handler)
- Register DELETE routeuse(path?, middleware)
- Add middleware
Server Control
start()
- Start HTTP server with MCP integrationstop()
- Stop HTTP serverhealth()
- Get server health status with detailed metricsrootHandler(req, res)
- Built-in root endpoint handlergetApp()
- Get underlying Express app instanceisServerRunning()
- Check if server is running
Built-in Endpoints
POST /mcp
- MCP client-to-server communicationGET /mcp
- Server-to-client notifications (SSE)DELETE /mcp
- Session terminationGET /health
- Health check endpoint with metricsGET /
- Server information and capabilitiesGET /chat
- Redirect to chat interface
AnalyticsClient Class
Constructor
new AnalyticsClient(
config: AnalyticsClientConfig,
apiConfig: APIConfig
)
Methods
trackTool(eventType, data)
- Track tool events with flat schematrackResource(eventType, data)
- Track resource eventstrackPrompt(eventType, data)
- Track prompt eventstrackEvent(data)
- Track custom eventstrackPerformance(data)
- Track performance metricsflush()
- Force send pending analyticsconfigure(options)
- Update analytics configurationenable()
- Enable analytics collectiondisable()
- Disable analytics collection
MCPWebLog Class
Constructor
new MCPWebLog({
disable: boolean // Set to true to disable logging
})
Methods
log(message, ...args)
- Log message (only if enabled)
OpenAPI Parser Functions
parseOpenAPISchema
parseOpenAPISchema(schema: OpenAPISchema): ParsedAPI[]
Features:
- Converts OpenAPI 3.0 specifications to MCPaaS API configurations
- Supports all HTTP methods (GET, POST, PUT, DELETE, PATCH, etc.)
- Generates Zod validation schemas automatically from OpenAPI schemas
- Handles nested objects, arrays, enums, and complex parameter types
- Extracts authentication schemes from security definitions
- Validates parameter constraints (min/max, patterns, required fields)
Example:
import { parseOpenAPISchema, OpenAPISchema } from '@mcpweb-org/sdk';
// Parse schema and inspect results
const parsedAPIs = parseOpenAPISchema(openApiSchema);
console.log(`Found ${parsedAPIs.length} API endpoints`);
parsedAPIs.forEach(api => {
console.log(`- ${api.name}: ${api.toolConfig.title}`);
console.log(` Method: ${api.apiConfig.method}`);
console.log(` URL: ${api.apiConfig.uri}`);
console.log(` Parameters:`, Object.keys(api.toolConfig.inputSchema));
});
registerOpenAPI
server.registerOpenAPI(openApiSchema: OpenAPISchema): void
Features:
- Bulk registration of all API endpoints in one call
- Automatic error handling - failed registrations don't stop others
- Progress tracking and detailed logging
- Analytics integration for registration events
- Support for complex OpenAPI features (allOf, oneOf, references)
Example:
// Register from local schema
server.registerOpenAPI(localSchema);
// Register from remote URL
const remoteSchema = await fetch('https://api.example.com/openapi.json').then(r => r.json());
server.registerOpenAPI(remoteSchema);
// Check what was registered
const tools = server.listTools();
console.log('Registered tools:', tools.map(t => t.name));
OpenAPI Parser Functions
parseOpenAPISchema
parseOpenAPISchema(schema: OpenAPISchema): ParsedAPI[]
- Converts OpenAPI 3.0 specs to MCPaaS API configurations
- Supports all HTTP methods and parameter types
- Generates Zod validation schemas automatically
- Handles nested objects and arrays
API Helper Functions
validateAPISpec
validateAPISpec(apiSpec: ApiConfig): void
- Validates API configuration before registration
- Checks URL format, HTTP methods, parameter types
- Validates authentication configurations
createAPIToolHandler
createAPIToolHandler(apiSpec: ApiConfig): ToolHandler
- Creates MCP tool handler from API specification
- Handles parameter templating and injection
- Implements retry logic and error handling
RegisterAPI Configuration
API Specification Object
{
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | /* 20+ more */,
uri: string, // API endpoint URL
headers?: Record<string, string>, // HTTP headers
queryParams?: string[], // Query parameter names
bodyParams?: string[], // Body parameter names
pathParams?: string[], // Path parameter names
auth?: ApiAuthConfig, // Authentication config
timeout?: number, // Request timeout in ms (default: 30000)
retries?: number // Number of retry attempts (default: 3)
}
Authentication Configuration
{
type: 'bearer' | 'basic' | 'apikey' | 'oauth2' | 'custom',
token?: string, // Bearer token
username?: string, // Basic auth username
password?: string, // Basic auth password
apiKey?: string, // API key value
apiKeyHeader?: string, // API key header name
customHeaders?: Record<string, string>, // Custom auth headers
oauth2Token?: string // OAuth2 token
}
Template Variables
{{paramName}}
- Inject input parameter{{$now}}
- Current ISO timestamp{{$uuid}}
- Generate UUID v4{{$timestamp}}
- Unix timestamp{{$env.VAR_NAME}}
- Environment variable
Configuration
Environment Variables
# Core Configuration
MCPAAS_APP_ID=your-app-id
MCPAAS_API_KEY=your-api-key
MCPAAS_API_BASE_URL=https://us-central1-mcpaas-dev.cloudfunctions.net/analytics
# Analytics Configuration
MCPAAS_ANALYTICS_BATCH_SIZE=50
MCPAAS_ANALYTICS_FLUSH_INTERVAL=30000
MCPAAS_ANALYTICS_MAX_EVENTS=10000
MCPAAS_ANALYTICS_MAX_RETRIES=3
MCPAAS_ANALYTICS_RETRY_DELAY=1000
# Server Configuration
SERVER_PORT=3000
SERVER_HOST=localhost
NODE_ENV=production
# Chat Interface (optional)
BUN_CHAT_URL=http://localhost:3000/chat
Analytics Configuration
// Configure analytics behavior
const analytics = server.analyticsCollector;
analytics.configure({
batchSize: 100, // Events per batch (default: 5)
flushInterval: 60000, // Flush every 60 seconds (default: 30000)
maxEventsInMemory: 5000, // Memory limit (default: 10000)
maxRetries: 5, // Retry attempts (default: 3)
retryDelay: 2000, // Retry delay in ms (default: 1000)
endpoint: 'custom-url', // Custom analytics endpoint
enabled: true // Enable/disable analytics
});
// Real-time configuration updates
analytics.enable(); // Enable analytics
analytics.disable(); // Disable analytics
await analytics.flush(); // Force flush pending events
Server Configuration
// MCPWeb Server Configuration
const serverConfig: MCPServerConfig = {
name: 'my-server',
description: 'My awesome MCP server',
version: '1.2.0',
capabilities: {
tools: true, // Enable tool registration
resources: true, // Enable resource registration
prompts: true // Enable prompt registration
}
};
// MCPWebExpress Configuration
const expressConfig = {
port: parseInt(process.env.SERVER_PORT || '3000'),
host: process.env.SERVER_HOST || 'localhost',
cors: true, // Enable CORS headers
json: true // Enable JSON body parsing
};
// HTTP Server Options (for MCPWeb.start())
const httpOptions = {
port: 3000,
host: 'localhost',
https: { // Optional HTTPS configuration
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
},
cors: { // Advanced CORS configuration
origin: ['http://localhost:3000', 'https://app.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
headers: ['Content-Type', 'Authorization', 'X-Requested-With']
}
};
TypeScript Types
All types are fully exported for use in your applications:
// Core Types
import {
MCPWeb,
MCPWebExpress,
AnalyticsClient,
MCPWebLog,
MCPServerConfig,
ToolConfig,
ResourceConfig,
MCPWebToolConfig,
ApiConfig,
OpenAPISchema,
ParsedAPI
} from '@mcpweb-org/sdk';
// Analytics Types
import {
FlatAnalyticsEvent,
AnalyticsEvent,
AnalyticsBatch,
MCPEventType,
ToolAnalyticsEvent,
ResourceAnalyticsEvent,
SessionAnalyticsEvent,
PerformanceAnalyticsEvent,
ToolUsageAggregate,
ServerHealthAggregate
} from '@mcpweb-org/sdk/client';
// Authentication & API Types
import {
HttpMethod,
AuthType,
ApiAuthConfig,
APIConfig,
AnalyticsClientConfig
} from '@mcpweb-org/sdk/types';
// Error Types
import {
MCPaaSError,
MCPaaSValidationError,
MCPaaSApiError
} from '@mcpweb-org/sdk/types';
// Platform Types (for SDK usage)
import {
Project,
CreateProject,
Deployment,
CreateDeployment,
ApiKey,
CreateApiKey,
MCPaaSResponse,
PaginatedResponse
} from '@mcpweb-org/sdk/types';
Type Examples
// Server configuration with full typing
const serverConfig: MCPServerConfig = {
name: 'typed-server',
description: 'Fully typed MCP server',
version: '1.0.0',
capabilities: {
tools: true,
resources: true,
prompts: true
}
};
// Tool configuration with Zod schema
const toolConfig: MCPWebToolConfig = {
title: 'Calculation Tool',
description: 'Perform mathematical operations',
inputSchema: {
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
operands: z.array(z.number()).min(2).max(10)
}
};
// API configuration with authentication
const apiConfig: ApiConfig = {
uri: 'https://api.example.com/data/{id}',
method: 'GET',
pathParams: ['id'],
queryParams: ['format', 'limit'],
headers: {
'Authorization': 'Bearer {{token}}',
'Content-Type': 'application/json'
},
auth: {
type: 'bearer',
token: process.env.API_TOKEN
},
timeout: 10000,
retries: 3
};
// Analytics event with full type safety
const analyticsEvent: FlatAnalyticsEvent = {
eventId: randomUUID(),
eventType: 'tool_call_completed',
timestamp: new Date().toISOString(),
serverId: 'server-123',
serverName: 'my-server',
serverVersion: '1.0.0',
appId: 'app-456',
toolName: 'calculator',
toolDuration: 150,
toolSuccess: true,
toolInputSize: 45,
toolOutputSize: 20,
performanceCpuUsagePercent: 25.5,
performanceMemoryUsageMB: 128
};
Migration from Official MCP SDK
Migrating is simple - just replace imports and enjoy enhanced functionality:
// Before (official SDK)
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server(
{ name: 'my-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// After (MCPaaS SDK)
import { MCPWeb, StdioServerTransport } from '@mcpweb-org/sdk';
const server = new MCPWeb(
{ name: 'my-server', version: '1.0.0' },
'your-app-id',
'your-api-key'
);
// Everything else works the same, with added:
// ✅ Automatic analytics tracking
// ✅ Built-in HTTP server support
// ✅ API integration capabilities
// ✅ Enhanced error handling
// ✅ Performance monitoring
Migration Checklist
- ✅ Replace
Server
withMCPWeb
- ✅ Add
appId
andapiKey
parameters - ✅ Set environment variables for analytics
- ✅ Optional: Upgrade to
registerTool
for enhanced features - ✅ Optional: Add HTTP endpoints with
start()
- ✅ Optional: Integrate APIs with
registerAPI()
Examples & Demos
Complete working examples are available in the examples/
directory:
📁 Available Examples
analytics-demo-simple.ts
- Basic analytics tracking and custom metricsmcpweb-express-minimal.ts
- Minimal MCPWebExpress server setupmcpweb-express.ts
- Full-featured Express server with MCP integrationopenapi-registration-demo.ts
- Bulk API registration from OpenAPI specsstdio.ts
- Stdio transport integration for CLI toolsstreamable-http-server.ts
- HTTP server with streaming support
🚀 Run Examples
# Navigate to SDK directory
cd sdk/ts
# Install dependencies
npm install
# Run analytics demo
npx tsx examples/analytics-demo-simple.ts
# Run Express server demo
npx tsx examples/mcpweb-express.ts
# Run OpenAPI registration demo
npx tsx examples/openapi-registration-demo.ts
📄 Additional Resources
Documentation
- Analytics Guide - Comprehensive analytics documentation
- Developer Guide - Development best practices
- Project Summary - Technical overview
- Changelog - Version history and updates
Testing
# Run all tests
npm test
# Run specific test suites
npm test -- --grep "MCPWeb"
npm test -- --grep "Analytics"
npm test -- --grep "OpenAPI"
# Run tests with coverage
npm run test:coverage
Development
# Build the SDK
npm run build
# Watch for changes
npm run build:watch
# Type checking
npm run type-check
# Linting
npm run lint
💡 Best Practices
🔧 Development Tips
// ✅ DO: Use environment variables for configuration
const server = new MCPWeb({
name: process.env.SERVER_NAME || 'my-server',
version: process.env.VERSION || '1.0.0'
}, process.env.MCPAAS_APP_ID!, process.env.MCPAAS_API_KEY!);
// ✅ DO: Add proper error handling
server.registerTool('safe-calculator', {
title: 'Safe Calculator',
inputSchema: {
expression: z.string().regex(/^[\d+\-*/\s()]+$/, 'Invalid expression')
}
}, async ({ expression }) => {
try {
// Use a safe eval library instead of eval()
const result = safeEval(expression);
return { content: [{ type: 'text', text: `Result: ${result}` }] };
} catch (error) {
throw new Error(`Calculation failed: ${error.message}`);
}
});
// ✅ DO: Use descriptive input schemas
const goodSchema = {
email: z.string().email().describe('User email address'),
age: z.number().min(0).max(150).describe('User age in years'),
role: z.enum(['admin', 'user']).describe('User role level')
};
// ❌ DON'T: Use vague schemas
const badSchema = {
data: z.string(),
value: z.number()
};
🚀 Performance Tips
// ✅ DO: Use MCPWebLog for conditional logging
const logger = new MCPWebLog({
disable: process.env.NODE_ENV === 'production'
});
// ✅ DO: Batch API calls when possible
server.registerAPI('batch-users', {
title: 'Get Multiple Users',
inputSchema: {
userIds: z.array(z.string()).max(50, 'Max 50 users per request')
}
}, {
method: 'POST',
url: 'https://api.example.com/users/batch',
body: { ids: '{{userIds}}' }
});
// ✅ DO: Set reasonable timeouts
server.registerAPI('external-service', config, {
method: 'GET',
url: 'https://slow-api.com/data',
timeout: 5000, // 5 seconds
retries: 3
});
🛡️ Security Best Practices
// ✅ DO: Validate all inputs
server.registerTool('file-reader', {
inputSchema: {
filename: z.string()
.regex(/^[a-zA-Z0-9._-]+$/, 'Invalid filename')
.max(100, 'Filename too long')
}
}, async ({ filename }) => {
// Prevent path traversal
if (filename.includes('..') || filename.includes('/')) {
throw new Error('Invalid filename');
}
// Continue with safe file operations...
});
// ✅ DO: Use environment variables for secrets
const apiConfig = {
method: 'GET',
url: 'https://api.service.com/data',
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
'X-API-Key': process.env.API_KEY
}
};
// ❌ DON'T: Hardcode secrets
const badConfig = {
headers: {
'Authorization': 'Bearer sk-1234567890abcdef' // Never do this!
}
};
🐛 Troubleshooting
Common Issues
1. "MCPAAS_API_BASE_URL is undefined"
# Solution: Set environment variables
echo "MCPAAS_API_BASE_URL=https://api.mcpaas.dev" >> .env
echo "MCPAAS_API_KEY=your-api-key" >> .env
# Or export them
export MCPAAS_API_BASE_URL="https://api.mcpaas.dev"
export MCPAAS_API_KEY="your-api-key"
2. "Cannot connect to transport"
// Check your server configuration
const server = new MCPWeb({
name: 'test-server',
version: '1.0.0',
capabilities: {
tools: true, // ← Make sure this is set
resources: true,
prompts: true
}
}, appId, apiKey);
// Wait for server to be ready
await server.start();
console.log('✅ Server ready');
3. "Tool execution failed"
// Add detailed error logging
server.registerTool('debug-tool', config, async (args) => {
try {
console.log('📥 Input:', args);
const result = await processData(args);
console.log('📤 Output:', result);
return result;
} catch (error) {
console.error('❌ Tool error:', error);
throw new Error(`Processing failed: ${error.message}`);
}
});
4. "External API calls timing out"
// Increase timeout and add retries
server.registerAPI('slow-api', config, {
method: 'GET',
url: 'https://slow-service.com/api',
timeout: 30000, // 30 seconds
retries: 5, // Retry 5 times
headers: {
'Connection': 'keep-alive'
}
});
Debug Mode
// Enable debug logging
process.env.DEBUG = 'mcpaas:*';
// Or use MCPWebLog for custom debugging
const debugLogger = new MCPWebLog({ disable: false });
debugLogger.log('🔍 Debug info:', { server: server.getStats() });
Health Checking
// Check server health
const stats = server.getStats();
console.log('📊 Server Status:', {
connected: stats.isConnected,
tools: stats.toolsCount,
resources: stats.resourcesCount,
uptime: process.uptime()
});
// For MCPWebExpress servers
const health = server.health();
console.log('🏥 Health Check:', health);
Performance Monitoring
// Monitor tool performance
server.registerTool('monitored-tool', config, async (args) => {
const startTime = Date.now();
try {
const result = await heavyOperation(args);
const duration = Date.now() - startTime;
if (duration > 5000) {
console.warn(`⚠️ Slow tool execution: ${duration}ms`);
}
return result;
} catch (error) {
console.error(`❌ Tool failed after ${Date.now() - startTime}ms`);
throw error;
}
});
📞 Getting Help
Quick Help
Issue Type | Where to Look |
---|---|
🐛 Bugs | GitHub Issues |
� Documentation | docs.mcpaas.com |
💬 Questions | Discord Community |
� Support | support@mcpaas.com |
Before Asking for Help
- ✅ Check this README
- ✅ Look at the examples
- ✅ Search existing issues
- ✅ Try the troubleshooting steps above
Creating a Good Issue Report
## � Bug Report
**Environment:**
- SDK Version: 0.1.2
- Node/MCPWeb Version: Node 18.17.0
- OS: macOS 14.0
**What happened:**
Clear description of the issue
**Expected behavior:**
What you expected to happen
**Code to reproduce:**
```typescript
// Minimal code that reproduces the issue
Error logs:
Paste any error messages here
## License
MIT License - see [LICENSE](./LICENSE) file for details.
---
**Made with ❤️ by the MCPaaS team**
🌟 **Star us on GitHub** | 💬 **Join our Discord** | 📚 **Read the Docs** | 🐛 **Report Issues**
[](https://www.npmjs.com/package/@mcpweb-org/sdk)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/mcpaas/sdk)
[](https://discord.gg/mcpaas)