# MCP Server Development

### Server Requirements <a href="#server-requirements" id="server-requirements"></a>

To be listed in Tairon's directory, MCP servers must meet these requirements:

#### **Core Requirements** <a href="#core-requirements" id="core-requirements"></a>

**MCP v1.0+ Support**

* Implement all required MCP endpoints
* Follow protocol specifications
* Provide proper error handling

***

**Documented API**

* Complete API documentation
* Function descriptions and examples
* Parameter and return type definitions

***

**Security Audit Preferred**

* Optional but recommended security review
* Vulnerability assessments
* Best practices compliance

***

**Open Source or Verifiable Builds**

* Public source code repository, OR
* Verifiable build artifacts
* Reproducible deployments

***

### MCP Endpoint Reference <a href="#mcp-endpoint-reference" id="mcp-endpoint-reference"></a>

**`GET /health` – Health Check**

Basic status check used to confirm that a server is operational.

**Method:** `GET` **URL:** `https://your-server.com/health`

**Response Example:**

```bash
{
  "status": "ok",
  "uptime": 102934,
  "timestamp": "2025-06-30T12:34:56Z"
}
```

* `status`: Should return `ok` if the server is operational
* `uptime`: Time (in seconds) the server has been up
* `timestamp`: ISO 8601 timestamp of the check

***

**`GET /capabilities` – Function Discovery**

Returns a list of callable functions exposed by the MCP server.

**Method:** `GET` **URL:** `https://your-server.com/capabilities`

**Response Example:**

```json5
{
  "functions": [
    {
      "name": "extract_entities",
      "description": "Extracts named entities from a string",
      "inputs": ["text"],
      "outputs": ["entities"]
    },
    {
      "name": "get_exchange_rate",
      "description": "Returns current exchange rate between two currencies",
      "inputs": ["from", "to"],
      "outputs": ["rate"]
    }
  ]
}
```

* `name`: Function identifier to be used with `/execute`
* `description`: Human-readable explanation of function
* `inputs`: List of expected input keys
* `outputs`: List of output keys

***

**`POST /execute` – Function Execution**

Main execution endpoint for calling any available function listed in `/capabilities`.

**Method:** `POST` **URL:** `https://your-server.com/execute` **Headers:**

```
Content-Type: application/json
```

**Request Example:**

```json
{
  "function": "get_exchange_rate",
  "input": {
    "from": "USD",
    "to": "EUR"
  }
}
```

**Response Example:**

```json
{
  "output": {
    "rate": 0.9254
  }
}
```

* `function`: Must match a name returned by `/capabilities`
* `input`: Object with named parameters expected by the function
* `output`: Object with named result keys as defined by the server

***

### Development Templates <a href="#development-templates" id="development-templates"></a>

#### **Node.js Template** <a href="#node.js-template" id="node.js-template"></a>

```json
const express = require('express');
const app = express();

// Middleware
app.use(express.json());
app.use(require('cors')());

// Server configuration
const SERVER_CONFIG = {
  name: 'My MCP Server',
  version: '1.0.0',
  mcpVersion: '1.0.0',
  description: 'Description of your server'
};

// Function registry
const functions = new Map();

// Register a function
function registerFunction(name, handler, schema) {
  functions.set(name, { handler, schema });
}

// Health endpoint
app.get('/health', (req, res) => {
  res.json({
    status: 'healthy',
    timestamp: new Date().toISOString(),
    version: SERVER_CONFIG.version,
    mcpVersion: SERVER_CONFIG.mcpVersion
  });
});

// Capabilities endpoint
app.get('/capabilities', (req, res) => {
  const functionList = Array.from(functions.entries()).map(([name, func]) => ({
    name,
    description: func.schema.description,
    parameters: func.schema.parameters,
    returns: func.schema.returns
  }));

  res.json({
    mcpVersion: SERVER_CONFIG.mcpVersion,
    server: {
      name: SERVER_CONFIG.name,
      version: SERVER_CONFIG.version,
      description: SERVER_CONFIG.description
    },
    functions: functionList
  });
});

// Execute endpoint
app.post('/execute', async (req, res) => {
  const { function: functionName, parameters, requestId } = req.body;
  
  try {
    const func = functions.get(functionName);
    if (!func) {
      return res.status(400).json({
        error: {
          code: 'FUNCTION_NOT_FOUND',
          message: `Function '${functionName}' not found`
        },
        requestId
      });
    }

    const startTime = Date.now();
    const result = await func.handler(parameters);
    const executionTime = Date.now() - startTime;

    res.json({
      requestId,
      result,
      executionTime
    });
  } catch (error) {
    res.status(500).json({
      error: {
        code: 'EXECUTION_ERROR',
        message: error.message
      },
      requestId
    });
  }
});

// Example function registration
registerFunction('getPrice', async (params) => {
  // Your function logic here
  return {
    price: 2345.67,
    timestamp: new Date().toISOString(),
    symbol: params.symbol
  };
}, {
  description: 'Get current price for a trading pair',
  parameters: {
    type: 'object',
    properties: {
      symbol: { type: 'string', description: 'Trading pair symbol' }
    },
    required: ['symbol']
  },
  returns: {
    type: 'object',
    properties: {
      price: { type: 'number' },
      timestamp: { type: 'string' },
      symbol: { type: 'string' }
    }
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`MCP Server running on port ${PORT}`);
});
```

#### **Python Template** <a href="#python-template" id="python-template"></a>

```python
from flask import Flask, request, jsonify
from datetime import datetime
import time

app = Flask(__name__)

# Server configuration
SERVER_CONFIG = {
    'name': 'My MCP Server',
    'version': '1.0.0',
    'mcpVersion': '1.0.0',
    'description': 'Description of your server'
}

# Function registry
functions = {}

def register_function(name, handler, schema):
    functions[name] = {'handler': handler, 'schema': schema}

@app.route('/health', methods=['GET'])
def health():
    return jsonify({
        'status': 'healthy',
        'timestamp': datetime.utcnow().isoformat() + 'Z',
        'version': SERVER_CONFIG['version'],
        'mcpVersion': SERVER_CONFIG['mcpVersion']
    })

@app.route('/capabilities', methods=['GET'])
def capabilities():
    function_list = []
    for name, func in functions.items():
        function_list.append({
            'name': name,
            'description': func['schema']['description'],
            'parameters': func['schema']['parameters'],
            'returns': func['schema']['returns']
        })
    
    return jsonify({
        'mcpVersion': SERVER_CONFIG['mcpVersion'],
        'server': {
            'name': SERVER_CONFIG['name'],
            'version': SERVER_CONFIG['version'],
            'description': SERVER_CONFIG['description']
        },
        'functions': function_list
    })

@app.route('/execute', methods=['POST'])
def execute():
    data = request.get_json()
    function_name = data.get('function')
    parameters = data.get('parameters', {})
    request_id = data.get('requestId')
    
    try:
        if function_name not in functions:
            return jsonify({
                'error': {
                    'code': 'FUNCTION_NOT_FOUND',
                    'message': f"Function '{function_name}' not found"
                },
                'requestId': request_id
            }), 400
        
        start_time = time.time()
        result = functions[function_name]['handler'](parameters)
        execution_time = int((time.time() - start_time) * 1000)
        
        return jsonify({
            'requestId': request_id,
            'result': result,
            'executionTime': execution_time
        })
    
    except Exception as e:
        return jsonify({
            'error': {
                'code': 'EXECUTION_ERROR',
                'message': str(e)
            },
            'requestId': request_id
        }), 500

# Example function
def get_price(params):
    return {
        'price': 2345.67,
        'timestamp': datetime.utcnow().isoformat() + 'Z',
        'symbol': params.get('symbol')
    }

# Register the function
register_function('getPrice', get_price, {
    'description': 'Get current price for a trading pair',
    'parameters': {
        'type': 'object',
        'properties': {
            'symbol': {'type': 'string', 'description': 'Trading pair symbol'}
        },
        'required': ['symbol']
    },
    'returns': {
        'type': 'object',
        'properties': {
            'price': {'type': 'number'},
            'timestamp': {'type': 'string'},
            'symbol': {'type': 'string'}
        }
    }
})

if __name__ == '__main__':
    app.run(debug=True, port=3000)
```

***

### Testing Your Server <a href="#testing-your-server" id="testing-your-server"></a>

Before submitting to Tairon, test your server locally:

```bash
# Install testing tools
npm install -g @tairon/test-suite

# Test your server
tairon-test http://localhost:3000 --comprehensive

# Example output:
# Health check endpoint
# Capabilities discovery
# Function execution
# Error handling
# Schema validation
# Rate limiting not implemented
# Security scan passed
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tairon.ai/tairon/mcp-server-development.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
