mcp-server-nuclio-template

Advisori-FTC/mcp-server-nuclio-template

3.1

If you are the rightful owner of mcp-server-nuclio-template and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

This document provides a comprehensive guide to setting up and using a Model Context Protocol (MCP) server using the Nuclio framework.

MCP Server Nuclio Template 🚀

A production-ready template for building Nuclio-based MCP (Model Context Protocol) servers. This template provides a complete foundation with configurable tools, error handling, caching, and streaming support.

Features ✨

  • 🛠️ Configurable Tool System - Define tools via configuration files
  • 🔄 Streaming Support - Server-Sent Events and chunked responses
  • Performance Optimized - Built-in caching and circuit breaker patterns
  • 🔒 Security First - Input validation and output sanitization
  • 📊 Monitoring Ready - Comprehensive logging and metrics
  • 🎯 Production Ready - Error handling, retries, and graceful shutdown
  • 🔧 Developer Friendly - Local development server with hot reload

Quick Start 🏃‍♂️

1. Clone and Setup

# Clone the template
git clone <your-repo-url>
cd mcp-server-nuclio-template

# Install dependencies
npm install

# Copy environment configuration
cp .env.example .env

# Edit .env with your settings
nano .env

2. Configure Your Tools

Edit config/tools.config.js to define your MCP tools:

tools: [
    {
        name: 'your_tool_name',
        description: 'What your tool does',
        inputSchema: {
            type: 'object',
            properties: {
                // Define input parameters
            }
        },
        outputSchema: {
            type: 'object',
            properties: {
                // Define output structure
            }
        },
        handler: 'lib/tools/your-tool.handler.js'
    }
]

3. Create Tool Handlers

Create handler files in lib/tools/:

// lib/tools/your-tool.handler.js
async function execute(args, context) {
    const { logger, config } = context;

    // Your tool logic here

    return {
        // Your response data
    };
}

module.exports = { execute };

4. Run Locally

# Start local development server (recommended)
npm run server

# With auto-reload on file changes
npm run server:dev

# Or run the Nuclio function directly
npm start

# Development mode with auto-reload (function only)
npm run dev

The local development server (npm run server) provides:

  • Full Nuclio function wrapper
  • Hot reload capability
  • Request/response logging
  • Development endpoints for testing
  • CORS support for browser testing

Project Structure 📁

mcp-server-nuclio-template/
├── config/                    # Global configuration
│   └── server.config.js      # Server configuration
├── tools/                     # Tool modules (NEW STRUCTURE)
│   ├── echo/                 # Echo tool
│   │   ├── config/
│   │   │   ├── main.config.js
│   │   │   └── description.md
│   │   ├── properties/
│   │   │   ├── properties.config.js
│   │   │   └── description.md
│   │   └── handler.js
│   ├── search/               # Search tool
│   │   └── ...
│   └── [your-tool]/          # Your custom tools
├── lib/                       # Core library code
│   ├── mcp-handler.js        # MCP protocol handler
│   ├── tool-loader.js        # Dynamic tool loader
│   └── streamable-transport.js # Streaming support
├── utils/                     # Utility modules
│   ├── logger.js             # Logging utility
│   ├── circuit-breaker.js   # Circuit breaker pattern
│   ├── cache.js              # Caching utility
│   └── validation.js        # Schema validation
├── test/                      # Test files
│   ├── local-server.js       # Local development server
│   └── test-mcp.js           # Test suite
├── docs/                      # Documentation
│   └── TOOL_STRUCTURE.md     # Tool structure guide
├── index.js                  # Main entry point
├── function.yaml             # Nuclio configuration
├── package.json
├── .env.example              # Environment template
└── README.md

Configuration 🔧

Server Configuration (config/server.config.js)

{
    server: {
        name: 'your-server-name',
        version: '1.0.0',
        description: 'Your server description'
    },
    performance: {
        maxConcurrentRequests: 10,
        requestTimeout: 30000,
        cacheEnabled: true,
        cacheTTL: 3600
    },
    errorHandling: {
        circuitBreaker: {
            enabled: true,
            failureThreshold: 5,
            resetTimeout: 60000
        }
    }
}

Environment Variables

Key environment variables (see .env.example):

  • MCP_SERVER_NAME - Server identifier
  • LOG_LEVEL - Logging level (error, warn, info, debug)
  • CACHE_ENABLED - Enable/disable caching
  • CIRCUIT_BREAKER_ENABLED - Enable/disable circuit breaker
  • PORT - Development server port

Creating Custom Tools 🛠️

1. Define Tool Schema

Add your tool definition to config/tools.config.js:

{
    name: 'analyze_data',
    description: 'Analyze data and return insights',
    inputSchema: {
        type: 'object',
        properties: {
            data: { type: 'array' },
            metrics: {
                type: 'array',
                items: { type: 'string' }
            }
        },
        required: ['data', 'metrics']
    },
    outputSchema: {
        type: 'object',
        properties: {
            insights: { type: 'array' },
            summary: { type: 'string' }
        }
    },
    handler: 'lib/tools/analyze-data.handler.js',
    config: {
        timeout: 60000,
        cacheEnabled: true
    }
}

2. Implement Handler

Create lib/tools/analyze-data.handler.js:

async function execute(args, context) {
    const { logger, config } = context;
    const { data, metrics } = args;

    logger.info('Analyzing data', { metrics });

    // Your analysis logic
    const insights = await analyzeData(data, metrics);

    return {
        insights,
        summary: `Analyzed ${data.length} items`
    };
}

module.exports = { execute };

3. Test Your Tool

# Use the test endpoint
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "tools/call",
    "params": {
        "name": "analyze_data",
        "arguments": {
            "data": [1, 2, 3],
            "metrics": ["sum", "average"]
        }
    }
}'

Deployment to Nuclio 🚢

1. Create Nuclio Function

# function.yaml
apiVersion: nuclio.io/v1beta1
kind: Function
metadata:
  name: mcp-server
spec:
  handler: index:handler
  runtime: nodejs
  env:
    - name: MCP_SERVER_NAME
      value: "production-mcp-server"
    - name: LOG_LEVEL
      value: "info"
  resources:
    requests:
      memory: "128Mi"
      cpu: "100m"
    limits:
      memory: "512Mi"
      cpu: "500m"

2. Deploy

# Build and deploy to Nuclio
nuctl deploy \
    --path . \
    --registry your-registry \
    --project-name your-project \
    --platform local

API Reference 📚

MCP Protocol Methods

initialize

Initialize the MCP server and get capabilities.

tools/list

Get list of available tools with schemas.

tools/call

Execute a tool with given arguments.

{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "tools/call",
    "params": {
        "name": "tool_name",
        "arguments": {
            // Tool-specific arguments
        }
    }
}

HTTP Endpoints (Development Server)

  • GET /health - Health check
  • GET /status - Server status and metrics
  • GET /tools - List available tools
  • POST /mcp - Main MCP endpoint

Advanced Features 🔬

Circuit Breaker

Prevents cascading failures by stopping requests to failing services:

// Automatically managed per tool
// Configurable via environment variables:
CIRCUIT_BREAKER_ENABLED=true
CIRCUIT_BREAKER_THRESHOLD=5
CIRCUIT_BREAKER_RESET=60000

Caching

Built-in caching with TTL support:

// Configure in tool definition
config: {
    cacheEnabled: true,
    cacheTTL: 3600  // seconds
}

Streaming Support

Enable streaming for long-running operations:

// In your tool handler
async function execute(args, context) {
    const { stream } = context;

    // Stream chunks
    for (const chunk of data) {
        stream(chunk);
        await processChunk(chunk);
    }

    return { complete: true };
}

Best Practices 💡

  1. Tool Design

    • Keep tools focused on single responsibilities
    • Use clear, descriptive names
    • Provide comprehensive schemas
  2. Error Handling

    • Always return structured errors
    • Log errors with context
    • Use circuit breaker for external services
  3. Performance

    • Enable caching for expensive operations
    • Set appropriate timeouts
    • Use streaming for large responses
  4. Security

    • Validate all inputs
    • Sanitize outputs
    • Never expose sensitive data in logs
  5. Monitoring

    • Use structured logging
    • Track tool execution metrics
    • Monitor circuit breaker status

Examples 📝

See the examples/ directory for:

  • Complex tool implementations
  • Integration patterns
  • Testing strategies
  • Deployment configurations

Troubleshooting 🔍

Common Issues

  1. Tool not loading

    • Check handler file path in config
    • Verify export format: module.exports = { execute }
    • Check logs for loading errors
  2. Validation errors

    • Ensure input matches schema exactly
    • Check required fields
    • Validate data types
  3. Performance issues

    • Enable caching
    • Increase timeout values
    • Check circuit breaker status

Contributing 🤝

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Submit a pull request

License 📄

MIT License - see LICENSE file for details

Support 💬


Built with ❤️ for the MCP community