Skip to main content
Glama

sipap-mcp

Framework de servidores MCP listo para producción en AWS Lambda y ECS Fargate

Python Version Type Checked Code Style Test Coverage Tests


Descripción general

sipap-mcp proporciona clases base e infraestructura para construir servidores Model Context Protocol (MCP) que implementan JSON-RPC 2.0 y pueden ejecutarse en:

  • AWS Lambda: Funciones serverless para cargas de trabajo ligeras y esporádicas

  • ECS Fargate: Servicios contenedorizados para cargas de trabajo de larga duración y con estado

Este framework impulsa los 5 servidores de datos de la arquitectura de Valo (Plataforma de Inteligencia Deportiva), que gestionan datos deportivos, inteligencia de cuotas, contexto de noticias, datos meteorológicos y estadísticas históricas.

Related MCP server: mcp-server-toolkit

Características

Funcionalidad principal

  • Clase base MCPServer: Base abstracta con registro de herramientas y autodetección

  • Decorador @mcp_tool: Marca funciones como herramientas MCP con validación de JSON Schema

  • Protocolo JSON-RPC 2.0: Implementación completa con manejo de errores adecuado

  • Transporte dual: Handler de Lambda y servidor HTTP FastAPI

Seguridad y estado

  • Autenticación: Estrategias conectables (NoAuth, API key, AWS SigV4)

  • Gestión de sesiones: Preservación de estado entre llamadas respaldada por Redis

  • Validación de entradas: Validación JSON Schema en todas las entradas de las herramientas

Calidad

  • Seguridad de tipos: Cumplimiento total del modo estricto de mypy (cero errores)

  • Cobertura de pruebas: 96 % de cobertura con 112 pruebas superadas

  • Listo para producción: Cero errores de linting, manejo de errores exhaustivo

Instalación

pip install sipap-mcp

Para desarrollo:

pip install sipap-mcp[dev]

Inicio rápido

1. Define un servidor MCP

from sipap_mcp import MCPServer, mcp_tool

class WeatherMCP(MCPServer):
    """Weather data MCP server."""

    def __init__(self):
        super().__init__(name="weather-mcp", version="1.0.0")

    @mcp_tool(
        description="Get current weather for a location",
        input_schema={
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "City name"},
                "units": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "default": "celsius"
                }
            },
            "required": ["location"]
        }
    )
    def get_weather(self, location: str, units: str = "celsius") -> dict:
        """Get current weather conditions."""
        # Your implementation here
        return {
            "location": location,
            "temperature": 22 if units == "celsius" else 72,
            "units": units,
            "condition": "partly cloudy"
        }

2. Despliega en AWS Lambda

from sipap_mcp.transport import create_lambda_handler
from sipap_mcp.auth import APIKeyAuth

# Create server instance
server = WeatherMCP()

# Configure authentication
auth = APIKeyAuth(api_keys=["your-api-key"])

# Create Lambda handler (entry point for AWS)
handler = create_lambda_handler(server, auth=auth)

Despliega con AWS CDK o Terraform:

  • Handler: your_module.handler

  • Runtime: python3.12

  • Timeout: 30 segundos

3. Despliega en ECS Fargate (HTTP)

from sipap_mcp.transport import create_http_app
import uvicorn

# Create server instance
server = WeatherMCP()

# Create FastAPI app
app = create_http_app(server, auth=auth)

# Run with uvicorn
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Despliega con Docker:

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install sipap-mcp
CMD ["uvicorn", "your_module:app", "--host", "0.0.0.0", "--port", "8000"]

Conceptos fundamentales

Herramientas

Las herramientas son funciones decoradas con @mcp_tool que se pueden invocar a través del protocolo MCP:

@mcp_tool(
    description="Description of what this tool does",
    input_schema={
        "type": "object",
        "properties": {
            "param": {"type": "string"}
        },
        "required": ["param"]
    }
)
def my_tool(self, param: str) -> dict:
    """Docstring for the tool."""
    return {"result": param}

Tipos de JSON Schema compatibles:

  • string, number, integer, boolean, array, object

  • Validación: minLength, maxLength, minimum, maximum, pattern, enum

Autenticación

Elige la estrategia de autenticación que se adapte a tu despliegue:

NoAuth (solo desarrollo)

from sipap_mcp.auth import NoAuth

auth = NoAuth()  # No authentication - use for local dev only

Autenticación por API Key

from sipap_mcp.auth import APIKeyAuth

auth = APIKeyAuth(api_keys=[
    "client-a-key",
    "client-b-key",
    "client-c-key"
])

Los clientes envían la API key en la cabecera X-API-Key.

Autenticación AWS SigV4

from sipap_mcp.auth import SigV4Auth

auth = SigV4Auth(service="lambda", region="us-east-1")

Para URLs de Lambda Function con autenticación IAM.

Gestión de sesiones

Mantén el estado entre múltiples solicitudes usando Redis:

import redis
from sipap_mcp.session import SessionManager

# Connect to Redis
redis_client = redis.Redis(host="localhost", port=6379)

# Create session manager
session_manager = SessionManager(
    redis_client=redis_client,
    ttl=3600  # 1 hour default
)

# Create session
session_id = session_manager.create_session(
    data={"user_id": "123", "preferences": {...}},
    ttl=1800  # 30 minutes custom TTL
)

# Retrieve session
session_data = session_manager.get_session(session_id)

# Update session
session_manager.update_session(session_id, updated_data)

# Extend TTL
session_manager.extend_ttl(session_id, ttl=7200)

Hooks del ciclo de vida

Sobrescribe _setup() y _cleanup() para la gestión de recursos:

class MyServer(MCPServer):
    def __init__(self):
        super().__init__(name="my-server", version="1.0.0")
        self.db_connection = None

    def _setup(self) -> None:
        """Called when entering context manager."""
        self.db_connection = connect_to_database()

    def _cleanup(self) -> None:
        """Called when exiting context manager."""
        if self.db_connection:
            self.db_connection.close()

Úsalo con el gestor de contexto:

with server:
    # Server is set up, resources initialized
    response = server.handle_request(request)
    # Cleanup happens automatically on exit

Protocolo JSON-RPC 2.0

Formato de solicitud

Listar herramientas disponibles

{
  "jsonrpc": "2.0",
  "id": "req-1",
  "method": "tools/list",
  "params": {}
}

Respuesta:

{
  "jsonrpc": "2.0",
  "id": "req-1",
  "result": {
    "tools": [
      {
        "name": "get_weather",
        "description": "Get current weather for a location",
        "inputSchema": {
          "type": "object",
          "properties": {...},
          "required": [...]
        }
      }
    ]
  }
}

Invocar una herramienta

{
  "jsonrpc": "2.0",
  "id": "req-2",
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "location": "London",
      "units": "celsius"
    }
  }
}

Respuesta:

{
  "jsonrpc": "2.0",
  "id": "req-2",
  "result": {
    "content": [{
      "type": "text",
      "text": "{\"location\": \"London\", \"temperature\": 15, ...}"
    }]
  }
}

Manejo de errores

Códigos de error estándar de JSON-RPC 2.0:

Código

Significado

Cuándo

-32700

Error de análisis

JSON no válido

-32600

Solicitud no válida

Faltan campos obligatorios

-32601

Método no encontrado

Método desconocido

-32602

Parámetros no válidos

Falló la validación

-32603

Error interno

Error del servidor

Respuesta de error:

{
  "jsonrpc": "2.0",
  "id": "req-3",
  "error": {
    "code": -32602,
    "message": "Invalid params: 'location' is required"
  }
}

Ejemplos

Consulta el directorio examples/ para ver ejemplos completos:

Ejemplo

Descripción

01_basic_server.py

Servidor simple de calculadora

02_lambda_with_auth.py

Despliegue en Lambda con autenticación por API key

03_http_with_sessions.py

Servidor HTTP con sesiones Redis

04_advanced_server.py

Patrones avanzados y hooks del ciclo de vida

05_authentication.py

Todas las estrategias de autenticación

Ejecuta los ejemplos:

python examples/01_basic_server.py
python examples/02_lambda_with_auth.py
python examples/03_http_with_sessions.py  # Requires Redis

Arquitectura

Patrones de diseño (de Sentinel)

Este framework adapta patrones probados de la arquitectura Sentinel:

  1. Patrón ExitStack + Generator: Gestión de recursos con gestores de contexto

  2. Autodetección de herramientas: Registro de herramientas basado en introspección

  3. Aplicación de salida estructurada: Validación JSON Schema en todas las entradas/salidas

  4. Registro basado en ContextVar: Propagación de contexto segura para hilos

Estructura de módulos

sipap_mcp/
├── core/
│   ├── protocol.py       # JSON-RPC 2.0 implementation
│   └── server.py          # MCPServer base class
├── decorators/
│   └── tool.py            # @mcp_tool decorator & registry
├── transport/
│   ├── lambda_handler.py  # AWS Lambda adapter
│   └── http_handler.py    # FastAPI adapter
├── auth/
│   └── middleware.py      # Authentication strategies
├── session/
│   └── manager.py         # Redis session management
└── validation/
    └── schema.py          # JSON Schema validation

Desarrollo

Configuración

# Clone repository
git clone <repo-url>
cd sipap-mcp

# Create virtual environment
python3.12 -m venv .venv
source .venv/bin/activate

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

Ejecutar pruebas

# Run all tests
pytest

# Run with coverage
pytest --cov=src/sipap_mcp --cov-report=html

# Open coverage report
open htmlcov/index.html

Controles de calidad

Todos los controles de calidad deben superarse antes de hacer commit:

# Type checking (strict mode)
mypy src/sipap_mcp --strict

# Linting
ruff check src/sipap_mcp tests/

# Auto-fix linting errors
ruff check --fix src/sipap_mcp tests/

# All gates at once
pytest && mypy src/sipap_mcp --strict && ruff check src/sipap_mcp tests/

Construcción

# Build wheel and source distribution
python -m build

# Install built package
pip install dist/sipap_mcp-0.1.0-py3-none-any.whl

Requisitos

Runtime

  • Python 3.12, 3.13 o 3.14

  • pydantic >= 2.7.0

  • fastapi >= 0.111.0

  • uvicorn[standard] >= 0.30.0

  • jsonschema >= 4.22.0

  • sipap-common >= 0.1.0

  • typing-extensions >= 4.12.0

Desarrollo

  • pytest >= 8.0.0

  • pytest-cov >= 5.0.0

  • mypy >= 1.10.0

  • ruff >= 0.4.0

Referencia de la API

MCPServer

class MCPServer(name: str, version: str)

Métodos:

  • handle_request(request_data) -> dict: Procesa una solicitud JSON-RPC

  • list_tools() -> list[dict]: Obtiene las herramientas registradas

  • get_info() -> dict: Obtiene los metadatos del servidor

  • _setup() -> None: Sobrescribir para la inicialización (opcional)

  • _cleanup() -> None: Sobrescribir para la limpieza (opcional)

@mcp_tool

@mcp_tool(description: str, input_schema: dict)
def tool_function(self, **kwargs) -> dict:
    pass

Parámetros:

  • description: Descripción de la herramienta legible para humanos

  • input_schema: JSON Schema para la validación de entradas

SessionManager

class SessionManager(redis_client, ttl: int = 3600)

Métodos:

  • create_session(data, ttl=None) -> str: Crea una sesión y devuelve el ID

  • get_session(session_id) -> dict | None: Recupera los datos de la sesión

  • update_session(session_id, data, ttl=None) -> bool: Actualiza la sesión

  • delete_session(session_id) -> bool: Elimina la sesión

  • session_exists(session_id) -> bool: Comprueba si existe

  • extend_ttl(session_id, ttl) -> bool: Extiende la expiración

Funciones de transporte

create_lambda_handler(server, auth=None) -> Callable
create_http_app(server, auth=None) -> FastAPI

Pruebas de tu servidor

Pruebas unitarias

def test_my_server():
    server = MyServer()

    # Test tool listing
    tools = server.list_tools()
    assert len(tools) > 0

    # Test tool execution
    request = {
        "jsonrpc": "2.0",
        "id": "1",
        "method": "tools/call",
        "params": {
            "name": "my_tool",
            "arguments": {"param": "value"}
        }
    }

    with server:
        response = server.handle_request(request)
        assert "result" in response

Pruebas de integración

def test_lambda_handler():
    from sipap_mcp.transport import create_lambda_handler

    server = MyServer()
    handler = create_lambda_handler(server)

    event = {
        "headers": {},
        "body": json.dumps({
            "jsonrpc": "2.0",
            "id": "1",
            "method": "tools/list",
            "params": {}
        })
    }

    response = handler(event, {})
    assert response["statusCode"] == 200

Despliegue en producción

AWS Lambda

Configuración del handler:

# app.py
from sipap_mcp import MCPServer, mcp_tool
from sipap_mcp.transport import create_lambda_handler
from sipap_mcp.auth import APIKeyAuth
import os

class MyServer(MCPServer):
    # ... server definition ...

server = MyServer()
auth = APIKeyAuth(api_keys=os.getenv("API_KEYS", "").split(","))
handler = create_lambda_handler(server, auth=auth)

Despliegue:

  • Handler: app.handler

  • Runtime: python3.12

  • Memoria: 512 MB (ajústala según la carga de trabajo)

  • Timeout: 30 segundos (ajústalo según el tiempo de ejecución de las herramientas)

  • Variables de entorno: API_KEYS=key1,key2,key3

ECS Fargate

Dockerfile:

FROM python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

app.py:

from sipap_mcp.transport import create_http_app
# ... server definition ...

app = create_http_app(server, auth=auth)

Definición de tarea:

  • Puerto del contenedor: 8000

  • Comprobación de salud: /health (si está implementada)

  • CPU: 256 (.25 vCPU)

  • Memoria: 512 MB

Redis para sesiones

Desarrollo:

docker run -d -p 6379:6379 redis:7-alpine

Producción:

  • AWS ElastiCache para Redis

  • Versión: Redis 7.x

  • Tipo de nodo: cache.t4g.micro (o superior)

  • Cifrado: en tránsito y en reposo

  • Multi-AZ: habilitado para producción

Solución de problemas

Problemas comunes

Error de importación:

# Problem
from sipap_mcp import MCPServer  # ImportError

# Solution
pip install sipap-mcp

Fallo de autenticación:

# Check API key header name (must be X-API-Key)
headers = {"X-API-Key": "your-key"}  # Correct
headers = {"Api-Key": "your-key"}    # Wrong

Sesión no encontrada:

# Sessions expire after TTL
session_manager.session_exists(session_id)  # Check first
session_manager.extend_ttl(session_id, 3600)  # Extend if needed

Errores de tipo:

# Run mypy to catch type issues
mypy your_module.py --strict

Rendimiento

Benchmarks

Probado en AWS Lambda (512 MB, Python 3.12):

Operación

Arranque en frío

Arranque en caliente

tools/list

850ms

12ms

tools/call (simple)

900ms

15ms

tools/call (con BD)

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    A simple MCP server that provides a basic greeting tool and serves as a starter template for AWS Lambda deployment. Demonstrates how to build and deploy MCP servers with both local development and cloud deployment capabilities.
    1
    17
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Production-ready MCP server starter with authentication, observability, and a plugin system for building and deploying MCP servers quickly.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/odirasamuel/sipap-serverlesshandler-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server