mcp-low-level-server-streamable-http

amartiinezg/mcp-low-level-server-streamable-http

3.2

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

This project demonstrates the implementation of a Model Context Protocol (MCP) server using a low-level API with HTTP transport, OAuth 2.0 authentication, and integration with SAP CAP.

Tools
4
Resources
0
Prompts
0

MCP Low-Level Server - Streamable HTTP 🔗

Implementación de un servidor MCP (Model Context Protocol) usando la Low-Level API del SDK oficial, con HTTP transport, autenticación OAuth 2.0, e integración con SAP CAP (Cloud Application Programming Model).

🌟 Características Principales

  • MCP Server - Low-Level API con Streamable HTTP transport
  • OAuth 2.0 Authentication - Autenticación JWT con SAP Identity Authentication Service (IAS)
  • OAuth Discovery - Soporte completo para RFC 8414 y RFC 9728
  • CAP Integration - Servicio OData para gestión de catálogo e-commerce
  • Session Management - Gestión de sesiones HTTP con headers
  • 3 MCP Tools - Herramientas para interactuar con CAP OData
  • Kubernetes Ready - Deployable en KYMA BTP
  • Health Checks - Endpoints para liveness y readiness probes

📁 Estructura del Proyecto

mcp-low-level-server-streamable-http/
├── mcp-service/              # Servidor MCP (Node.js + TypeScript)
│   ├── src/
│   │   ├── index.ts          # Servidor MCP principal
│   │   ├── cap-integration.ts # Cliente HTTP para CAP
│   │   └── auth/
│   │       └── ias-auth.ts   # Módulo OAuth 2.0
│   ├── Dockerfile
│   └── package.json
│
├── cap-service/              # Servicio CAP OData
│   ├── db/                   # Modelos de datos CDS
│   ├── srv/                  # Servicios y lógica de negocio
│   │   ├── catalog-service.cds
│   │   ├── catalog-service.js
│   │   ├── auth-middleware.js
│   │   └── server.js
│   ├── Dockerfile
│   └── package.json
│
├── k8s/                      # Manifiestos de Kubernetes
│   ├── namespace.yaml
│   ├── mcp-service/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── apirule.yaml
│   └── cap-service/
│       ├── deployment.yaml
│       └── service.yaml
│
├── docs/
│   └── IAS_SETUP.md          # Guía completa OAuth 2.0
│
├── CLAUDE.md                 # Guía para Claude Code
├── OAUTH_IMPLEMENTATION_SUMMARY.md
└── README.md                 # Este archivo

🚀 Quick Start

👉 para instrucciones paso a paso en 5 minutos.

Prerrequisitos

  • Node.js 20+
  • Docker Desktop (opcional)
  • kubectl (para deployment en KYMA)
  • (Opcional) SAP BTP account con IAS para OAuth 2.0

Desarrollo Local Rápido

# 1. Instalar dependencias
cd mcp-service && npm install
cd ../cap-service && npm install

# 2. Desplegar base de datos CAP
cd cap-service
npm run deploy

# 3. Iniciar servicios
# Terminal 1 - CAP Service
cd cap-service
npm start

# Terminal 2 - MCP Service
cd mcp-service
npm run build
npm start

Con Docker Compose (recomendado)

docker-compose up

Los servicios estarán disponibles en:

🔐 Autenticación OAuth 2.0

Este proyecto soporta autenticación OAuth 2.0 usando SAP Identity Authentication Service (IAS). La autenticación es opcional y se controla mediante variables de entorno.

OAuth Discovery y Compatibilidad con SAP IAS

El servidor implementa OAuth Discovery con compatibilidad especial para SAP IAS:

✅ RFC 8414 - Authorization Server Metadata

  • Endpoint: GET /.well-known/oauth-authorization-server
  • Permite a clientes MCP descubrir automáticamente la configuración OAuth
  • Retorna endpoints de autorización, token y JWKS

⚠️ RFC 9728 - Protected Resource Metadata (DESHABILITADO)

  • El endpoint /.well-known/oauth-protected-resource está intencionalmente deshabilitado
  • Razón: SAP IAS no soporta el parámetro resource de RFC 8707
  • Cuando los clientes MCP detectan RFC 9728, automáticamente agregan el parámetro resource causando error invalid_target

🔄 OAuth Proxy Endpoints

  • GET /oauth/authorize - Filtra el parámetro resource antes de redirigir a SAP IAS
  • POST /oauth/token - Filtra el parámetro resource antes de reenviar a SAP IAS
  • Estos endpoints actúan como proxy para garantizar compatibilidad con SAP IAS

Clientes MCP compatibles (Gemini CLI, etc.) pueden conectarse con dynamic discovery:

{
  "mcpServers": {
    "mcp-cap-service": {
      "url": "https://mcp-service.a7dda9c.kyma.ondemand.com/mcp",
      "oauth": {
        "enabled": true,
        "clientId": "YOUR_CLIENT_ID_HERE",
        "clientSecret": "YOUR_CLIENT_SECRET_HERE",
        "scopes": ["openid", "email", "profile"],
        "authProviderType": "dynamic_discovery"
      }
    }
  }
}

Importante: Este servidor NO soporta dynamic client registration. Debes:

  1. Obtener un client_id y client_secret pre-configurado en SAP IAS
  2. Configurar el redirect_uri en IAS según tu cliente MCP:
    • Gemini CLI: http://localhost:7777/oauth/callback
    • Navegador web: https://mcp-service.a7dda9c.kyma.ondemand.com/mcp/callback
  3. Agregar client_id y client_secret a la configuración del cliente MCP

El cliente automáticamente:

  1. Detecta que requiere OAuth al recibir 401 con WWW-Authenticate header
  2. Realiza GET /.well-known/oauth-authorization-server para descubrir configuración
  3. Inicia el flujo OAuth 2.0 Authorization Code con PKCE
  4. Obtiene access token y lo incluye en futuras peticiones

Sin Autenticación (Development)

# MCP Service
export IAS_ENABLED=false
npm start

# CAP Service
export IAS_ENABLED=false
npm start

Con Autenticación (Production)

# MCP Service
export IAS_ENABLED=true
export IAS_ISSUER=https://your-tenant.accounts.ondemand.com
export IAS_JWKS_URI=https://your-tenant.accounts.ondemand.com/oauth2/certs
export IAS_AUDIENCE=your-client-id
npm start

# CAP Service
export IAS_ENABLED=true
export IAS_ISSUER=https://your-tenant.accounts.ondemand.com
export IAS_JWKS_URI=https://your-tenant.accounts.ondemand.com/oauth2/certs
export IAS_AUDIENCE=your-client-id
npm start

📚 Guía Completa: Ver para configuración paso a paso.

🛠️ MCP Tools

El servidor MCP expone 4 herramientas:

1. create_note

Crea notas de texto (demo original de MCP)

Parámetros:

  • title (string) - Título de la nota
  • content (string) - Contenido de la nota

2. cap_list_products

Lista productos del catálogo OData

Parámetros:

  • filterByLowStock (boolean, opcional) - Filtrar por bajo stock
  • threshold (number, opcional) - Umbral de stock (default: 10)

3. cap_create_order

Crea una orden de compra

Parámetros:

  • customerName (string) - Nombre del cliente
  • items (array) - Lista de productos
    • productId (string) - UUID del producto
    • quantity (number) - Cantidad

4. cap_update_order_status

Actualiza el estado de una orden

Parámetros:

  • orderId (string) - UUID de la orden
  • newStatus (string) - PENDING | PROCESSING | SHIPPED | DELIVERED | CANCELLED

📡 Endpoints HTTP

MCP Service (Port 3001)

EndpointMétodoAutenticaciónDescripción
/mcpPOSTRequerida*Endpoint principal MCP
/mcpGETRequerida*SSE streaming
/mcpDELETERequerida*Terminar sesión
/healthGETPúblicaHealth check
/readyGETPúblicaReadiness probe
/.well-known/oauth-authorization-serverGETPúblicaOAuth Server Metadata (RFC 8414)
/oauth/authorizeGETPúblicaOAuth proxy - filtra parámetro resource
/oauth/tokenPOSTPúblicaOAuth token proxy - filtra parámetro resource
/mcp/loginGETPúblicaIniciar flujo OAuth 2.0
/mcp/callbackGETPúblicaCallback OAuth 2.0
/mcp/logoutGETPúblicaCerrar sesión OAuth

* Solo si IAS_ENABLED=true

CAP Service (Port 4004)

EndpointMétodoAutenticaciónDescripción
/odata/v4/catalog/ProductsGETRequerida*Listar productos
/odata/v4/catalog/OrdersGETRequerida*Listar órdenes
/odata/v4/catalog/createCompleteOrderPOSTRequerida*Crear orden
/odata/v4/catalog/updateOrderStatusPOSTRequerida*Actualizar estado

* Solo si IAS_ENABLED=true

🐳 Docker

Build de Imágenes

# MCP Service
cd mcp-service
docker build -t mcp-service:latest .

# CAP Service
cd cap-service
docker build -t cap-service:latest .

Run con Docker

# Network para comunicación entre servicios
docker network create mcp-network

# CAP Service
docker run -d --name cap-service \
  --network mcp-network \
  -p 4004:4004 \
  -e IAS_ENABLED=false \
  cap-service:latest

# MCP Service
docker run -d --name mcp-service \
  --network mcp-network \
  -p 3001:3001 \
  -e CAP_SERVICE_URL=http://cap-service:4004 \
  -e IAS_ENABLED=false \
  mcp-service:latest

☸️ Kubernetes / KYMA Deployment

Paso 1: Crear Namespace

kubectl apply -f k8s/namespace.yaml

Paso 2: Deploy Servicios

# CAP Service
kubectl apply -f k8s/cap-service/

# MCP Service
kubectl apply -f k8s/mcp-service/

Paso 3: Verificar Deployment

kubectl get pods -n mcp-cap-integration
kubectl get svc -n mcp-cap-integration
kubectl get apirule -n mcp-cap-integration

Paso 4: Obtener URL Externa

kubectl get virtualservice -n mcp-cap-integration
# URL: https://mcp-service.c-<cluster-id>.kyma.ondemand.com

🧪 Testing

Test Manual

# Health check
curl http://localhost:3001/health

# Inicializar sesión MCP (sin auth)
curl -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {},
      "clientInfo": {"name": "test", "version": "1.0"}
    }
  }'

Test con OAuth 2.0

# Usar el script de testing
export IAS_TENANT=your-tenant.accounts.ondemand.com
export IAS_CLIENT_ID=your-client-id
export IAS_CLIENT_SECRET=your-client-secret
export MCP_URL=http://localhost:3001
export CAP_URL=http://localhost:4004

./test-oauth.sh

Test con MCP Inspector

cd mcp-service
npm run inspector

🔧 Configuración de Claude Desktop

Local (sin autenticación)

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "mcp-cap-integration": {
      "type": "http",
      "url": "http://localhost:3001/mcp"
    }
  }
}

KYMA (con autenticación)

{
  "mcpServers": {
    "mcp-cap-integration": {
      "type": "http",
      "url": "https://mcp-service.a7dda9c.kyma.ondemand.com/mcp",
      "headers": {
        "Authorization": "Bearer <your-access-token>"
      }
    }
  }
}

📚 Documentación

  • - Guía para Claude Code
  • - Documentación completa (OAuth 2.0, IAS Setup, Gemini CLI, etc.)
  • - Guía de deployment en KYMA

🏗️ Arquitectura

┌─────────────────┐
│  Claude Desktop │
│   (MCP Client)  │
└────────┬────────┘
         │
         │ MCP HTTP Protocol
         │ (con Bearer Token opcional)
         ▼
┌─────────────────────────┐
│     MCP Service         │
│  (Express + MCP SDK)    │
│                         │
│  • Session Management   │
│  • OAuth 2.0 (opcional) │
│  • MCP Tools            │
│  • CAP Client           │
└────────┬────────────────┘
         │
         │ HTTP REST
         │ (con Bearer Token opcional)
         ▼
┌─────────────────────────┐
│     CAP Service         │
│   (CAP + OData v4)      │
│                         │
│  • OAuth 2.0 (opcional) │
│  • Business Logic       │
│  • SQLite Database      │
└─────────────────────────┘

🔒 Seguridad

Autenticación JWT

  • ✅ Validación de firma con JWKS
  • ✅ Verificación de issuer, audience y expiración
  • ✅ Algoritmo RS256
  • ✅ Cache de claves públicas (10 min)

Best Practices

  • Usar HTTPS en producción
  • Almacenar secrets en Kubernetes Secrets
  • Implementar refresh token logic
  • Rate limiting (recomendado)
  • Audit logging

🐛 Troubleshooting

MCP Service no se conecta a CAP

Solución: Verifica la variable CAP_SERVICE_URL

kubectl logs -n mcp-cap-integration deployment/mcp-service | grep "Inicializando CAPClient"

Error de autenticación

Solución: Verifica que el token sea válido y no haya expirado

# Decodificar token
echo $TOKEN | cut -d'.' -f2 | base64 -d | jq .

CAP Service no responde

Solución: Verifica que la base de datos esté inicializada

kubectl exec -it deployment/cap-service -n mcp-cap-integration -- ls /app/data

Ver más en

🤝 Contribuir

  1. Fork el proyecto
  2. Crea una rama para tu feature (git checkout -b feature/amazing-feature)
  3. Commit tus cambios (git commit -m 'Add amazing feature')
  4. Push a la rama (git push origin feature/amazing-feature)
  5. Abre un Pull Request

📝 Licencia

Este proyecto es un demo educativo para mostrar integración de MCP con CAP y OAuth 2.0.

🙏 Reconocimientos


Versión: 1.0.0 Última Actualización: 2025-10-15