JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 35
  • Score
    100M100P100Q91142F
  • License MIT

Official TypeScript/JavaScript SDK for the MCPaaS platform - A wrapper around the official MCP Server using @modelcontextprotocol/sdk

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.

npm version TypeScript License: MIT

🚀 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

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 begins
  • tool_call_completed - Successful tool completion
  • tool_call_failed - Tool execution failed
  • tool_call_timeout - Tool execution timed out

Resource Events

  • resource_read_started - Resource access begins
  • resource_read_completed - Successful resource read
  • resource_read_failed - Resource access failed

Session Events

  • session_initialized - New MCP session created
  • session_closed - Session ended normally
  • session_timeout - Session timed out

Server Events

  • server_started - Server initialization complete
  • server_stopped - Server shutdown
  • server_error - Server-level error occurred

Performance Events

  • performance_metric - General performance data
  • memory_usage - Memory consumption snapshot
  • cpu_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 analytics
  • registerResource(name, uri, config, handler) - Register MCP resource
  • registerPrompt(name, config, handler) - Register MCP prompt
  • registerAPI(name, config, apiSpec) - Transform HTTP API into MCP tool
  • registerOpenAPI(openApiSchema) - Bulk register APIs from OpenAPI schema
  • connect(transport) - Connect to MCP transport
  • close() - Close connection and cleanup

HTTP Server Methods

  • start(options) - Start HTTP server with CORS and middleware
  • stop() - Stop HTTP server

Information Methods

  • getStats() - Get server statistics
  • listTools() - Get registered tools summary
  • listResources() - Get registered resources summary
  • listPrompts() - Get registered prompts summary
  • getServer() - Get underlying server instance
  • getTools() - Get tools Map with handlers
  • getResources() - Get resources Map with handlers
  • getPrompts() - 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 route
  • post(path, handler) - Register POST route
  • put(path, handler) - Register PUT route
  • delete(path, handler) - Register DELETE route
  • use(path?, middleware) - Add middleware

Server Control

  • start() - Start HTTP server with MCP integration
  • stop() - Stop HTTP server
  • health() - Get server health status with detailed metrics
  • rootHandler(req, res) - Built-in root endpoint handler
  • getApp() - Get underlying Express app instance
  • isServerRunning() - Check if server is running

Built-in Endpoints

  • POST /mcp - MCP client-to-server communication
  • GET /mcp - Server-to-client notifications (SSE)
  • DELETE /mcp - Session termination
  • GET /health - Health check endpoint with metrics
  • GET / - Server information and capabilities
  • GET /chat - Redirect to chat interface

AnalyticsClient Class

Constructor

new AnalyticsClient(
  config: AnalyticsClientConfig,
  apiConfig: APIConfig
)

Methods

  • trackTool(eventType, data) - Track tool events with flat schema
  • trackResource(eventType, data) - Track resource events
  • trackPrompt(eventType, data) - Track prompt events
  • trackEvent(data) - Track custom events
  • trackPerformance(data) - Track performance metrics
  • flush() - Force send pending analytics
  • configure(options) - Update analytics configuration
  • enable() - Enable analytics collection
  • disable() - 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 with MCPWeb
  • ✅ Add appId and apiKey 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 metrics
  • mcpweb-express-minimal.ts - Minimal MCPWebExpress server setup
  • mcpweb-express.ts - Full-featured Express server with MCP integration
  • openapi-registration-demo.ts - Bulk API registration from OpenAPI specs
  • stdio.ts - Stdio transport integration for CLI tools
  • streamable-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

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

  1. ✅ Check this README
  2. ✅ Look at the examples
  3. ✅ Search existing issues
  4. ✅ 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**

[![npm](https://img.shields.io/npm/v/@mcpweb-org/sdk)](https://www.npmjs.com/package/@mcpweb-org/sdk)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/mcpaas/sdk)](https://github.com/mcpaas/sdk)
[![Discord](https://img.shields.io/discord/123456789)](https://discord.gg/mcpaas)