Skip to main content
Glama

Construye tu propio servidor MCP (y despliégalo)

Un servidor MCP completo y funcional que convierte una API de LLM en herramientas MCP, diseñado para ser enseñado. Se ejecuta localmente sobre stdio para Claude Desktop / Claude Code, y de forma remota sobre HTTP una vez que lo despliegues.

Respaldado por Groq — inferencia rápida, API compatible con OpenAI, nivel gratuito que soporta a una sala llena de estudiantes usándolo intensamente durante un taller.

Todo está en un solo archivo: server.py. ~170 líneas incluyendo comentarios.


Parte 0 — ¿Qué es MCP, en un minuto

MCP (Model Context Protocol) es una forma estándar de darle nuevas capacidades a un cliente de IA. Escribes un servidor; cualquier cliente MCP puede usarlo.

Un servidor puede exponer tres cosas:

Primitiva

Qué es

Quién la controla

Tool

Una función que el modelo puede llamar

El modelo decide

Resource

Datos de solo lectura que el cliente puede obtener

El cliente/app decide

Prompt

Una plantilla de prompt reutilizable

El usuario la elige

Dos transportes:

  • stdio — el cliente lanza tu servidor como un subproceso y se comunica a través de stdin/stdout. Local únicamente. Sin redes. Así es como funciona el 90% de los servidores MCP.

  • streamable HTTP — tu servidor es un servicio web en una URL. Esto es lo que despliegas para que otras personas (o clientes alojados) puedan usarlo.

El mismo server.py hace ambas cosas. Ese es todo el truco.


Parte 1 — Qué estamos construyendo

llm-toolkit: un servidor MCP que le da a cualquier cliente MCP cuatro herramientas impulsadas por LLM.

Herramienta

Hace

ask_llm

Haz una pregunta, elige conciso / detallado / para niños

summarize

Texto → N viñetas

translate

Traduce, preservando markdown y bloques de código

extract_json

Texto no estructurado → JSON estructurado

Además de un recurso (config://server-info) y un prompt (code_review) para que los estudiantes vean las tres primitivas.


Parte 2 — Ejecútalo localmente

Configuración

python -m venv .venv

Windows: .\venv\Scripts\activate — macOS/Linux: source .venv/bin/activate

pip install -r requirements.txt

Obtén una clave gratuita en console.groq.com → API Keys. Luego copia .env.example a .env y pégala:

cp .env.example .env

.env está en gitignore. El servidor lo carga automáticamente desde su propio directorio, por lo que funciona sin importar desde dónde lo lance el cliente.

Inspecciónalo antes de conectarlo

El Inspector MCP es la mejor herramienta de enseñanza: muestra la lista de herramientas y te permite llamar a las herramientas manualmente, sin necesidad de un cliente de IA.

npx @modelcontextprotocol/inspector python server.py

Abre la URL impresa, presiona Connect, luego List Tools. Verás las cuatro.


Parte 3 — Conéctalo a un cliente

Claude Code

claude mcp add llm-toolkit -e GROQ_API_KEY=gsk_... -- python /absolute/path/to/server.py

O confirma un .mcp.json en la raíz de tu proyecto para que todo el equipo lo tenga — consulta .mcp.json.example.

Claude Desktop

Edita claude_desktop_config.json:

  • macOS — ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows — %APPDATA%\Claude\claude_desktop_config.json

Pega el bloque mcpServers de .mcp.json.example, luego cierra y vuelve a abrir completamente Claude Desktop. Las herramientas aparecen bajo el icono de herramientas.

Solo rutas absolutas. La razón #1 por la que un servidor MCP local "no aparece" es una ruta relativa — el directorio de trabajo del cliente no es el tuyo. Usa la ruta completa tanto para el binario de python (.venv/bin/python) como para server.py.


Parte 4 — Despliégalo

Cambia al modo HTTP con una bandera:

python server.py --http

El servidor ahora está en http://localhost:8000/mcp. Envía ese mismo comando en un contenedor.

Opción A — Render, sin Docker (recomendado)

Render tiene un entorno de ejecución nativo de Python. Sin Dockerfile, sin compilación de contenedor. Instala requirements.txt y ejecuta tu comando de inicio directamente. Este es el camino más rápido desde la laptop a una URL pública.

Paso 1 — sube el código a GitHub.

git init && git add -A && git commit -m "MCP server"

Crea un repositorio vacío en github.com/new, luego:

git remote add origin https://github.com/<you>/llm-toolkit-mcp.git && git push -u origin main

Paso 2 — crea el servicio.

Panel de Render → New → Web Service → conecta el repositorio. Render lee render.yaml y se configura solo:

Configuración

Valor

Runtime

Python (no Docker)

Build command

pip install -r requirements.txt

Start command

python server.py --http

Paso 3 — establece la clave. Panel → Environment → añade GROQ_API_KEY. Está marcada como sync: false en render.yaml, por lo que vive solo en el panel, nunca en git.

Paso 4 — despliega. Tu endpoint público es https://<tu-app>.onrender.com/mcp.

Sin health check a propósito. GET /mcp abre un flujo SSE que permanece abierto por diseño. Un health check apuntando a él se cuelga, y Render interpreta el tiempo de espera como un servicio muerto y lo reinicia en bucle. Con healthCheckPath omitido, Render solo verifica que el proceso enlace $PORT — la verificación correcta para este servidor.

Las instancias del nivel gratuito se duermen después de ~15 min de inactividad. La primera llamada después de un sueño toma ~30–50s mientras se despierta. Algunos clientes MCP agotan el tiempo de espera antes de eso e informan que el servidor está roto. Caliéntalo con un curl antes de que comience la clase.

Opción B — Otros hosts sin Docker

Host

Cómo

Railway

Conecta el repositorio. Nixpacks detecta automáticamente Python. Establece el comando de inicio en python server.py --http.

Hugging Face Spaces

Gratuito, sin sueño. Docker Space, o Gradio Space con un app.py personalizado.

Google Cloud Run

gcloud run deploy --source . — compila desde el código fuente, no se necesita Dockerfile.

Cualquier VPS

pip install -r requirements.txt, luego ejecuta bajo systemd o tmux.

Opción C — Fly.io

fly launch --no-deploy
fly secrets set GROQ_API_KEY=gsk_...
fly deploy

Endpoint: https://<tu-app>.fly.dev/mcp

Opción D — Cualquier host de contenedores

El Dockerfile se mantiene para los hosts que quieran un contenedor. Funciona en Railway, Cloud Run, ECS, un VPS:

docker build -t llm-toolkit-mcp .
docker run -p 8000:8000 -e GROQ_API_KEY=gsk_... llm-toolkit-mcp

Verifica el despliegue

Un curl prueba que el servidor está vivo y hablando MCP:

curl -X POST https://your-app.onrender.com/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

Deberías recibir un bloque serverInfo nombrando llm-toolkit.

Conecta un cliente al servidor desplegado

claude mcp add --transport http llm-toolkit https://your-app.onrender.com/mcp

Los estudiantes pegan esa línea y al instante tienen tus cuatro herramientas. Ese es el momento culminante de todo el taller — sin instalación, sin clave, sin Python en su máquina.

Compartirlo públicamente — lee esto primero

Un servidor MCP desplegado sin autenticación está abierto a todo internet. Cualquiera que aprenda la URL puede llamar a tus herramientas, y cada llamada gasta tu cuota de Groq.

Para un taller, eso suele estar bien, y el nivel gratuito de Groq es lo que lo hace estar bien: cuando la cuota se agota, recibes errores HTTP 429, no una factura. El modo de fallo es "las herramientas dejan de responder", no "factura sorpresa".

Deja de estar bien en el momento en que pones una clave de pago detrás. Luego añade autenticación antes de compartir la URL — el parámetro auth del SDK de MCP, o una puerta de enlace API al frente.

Dos hábitos que vale la pena mantener de cualquier manera:

  • Trata la URL como semisecreta. Compártela en clase, no la publiques públicamente.

  • Rota la clave después del taller. Es un clic en el panel.

Parte 5 — Cosas que vale la pena enseñar explícitamente

El docstring es la API. El modelo elige herramientas leyendo el docstring y las indicaciones de tipo. Un docstring vago significa una herramienta que nunca se llama. Esto es lo que tiene mayor impacto en todo el archivo.

Una función es dueña del proveedor. Cada herramienta llama a call_llm(). Cambiar Groq por OpenAI, Anthropic, o un Ollama local significa editar esa única función — las cuatro herramientas nunca cambian. Haz una demostración en vivo; causa una fuerte impresión.

Devuelve errores como cadenas, no los lances. call_llm captura GroqError y devuelve el mensaje como texto. El cliente le muestra al usuario un error real en lugar de una llamada a herramienta muerta.

stateless_http=True significa que no hay sesiones fijas, por lo que el servidor escala detrás de un balanceador de carga. Desactívalo solo si añades estado por sesión.

Nunca confirmes la clave. .env está en gitignore, render.yaml usa sync: false, Fly usa fly secrets.

Los servidores HTTP públicos están abiertos por defecto. Este no tiene autenticación — está bien para una demo, no para producción. Los despliegues reales añaden OAuth a través del parámetro auth del SDK, o se sientan detrás de una puerta de enlace API.

La deriva de versiones es real. MCP Python SDK 2.0 renombró FastMCP a MCPServer. La mayoría de los tutoriales en línea todavía muestran FastMCP y fallarán en una instalación nueva. Buen momento para enseñar a leer el paquete instalado en lugar de confiar en una publicación de blog.


Parte 6 — Ejercicios para la clase

  1. Añade una herramienta sentiment(text). (Copia summarize, cambia el prompt del sistema.)

  2. Haz que ask_llm acepte un argumento max_tokens y observa cómo el esquema se actualiza automáticamente en el Inspector.

  3. Apunta call_llm a un proveedor diferente sin tocar ninguna herramienta.

  4. Añade un recurso config://usage que informe cuántas llamadas a herramientas ha servido el proceso. (Pista: un contador a nivel de módulo.)

  5. Rompe un docstring a propósito, luego pídele al modelo que use esa herramienta. Observa cómo falla al seleccionar la herramienta. Esa es la lección.


Parte 7 — Conseguir que otras personas lo usen

Entregar las herramientas a otra persona son tres problemas separados: accesible, conectable, descubrible. Resuélvelos en ese orden.

1. Accesible. Un servidor en localhost es utilizable por exactamente una persona. Despliégalo (Parte 4) y tendrás una URL pública. Nada de lo siguiente funciona hasta que esto esté hecho.

2. Conectable. Dale a la gente USING-IT.md — una página independiente con configuración de copiar y pegar para Claude Code, Claude Desktop y Cursor, además de una tabla de solución de problemas. Para un taller, la ruta remota es la que se debe usar: los estudiantes pegan una línea y tienen herramientas funcionales sin Python, sin repositorio y sin clave API propia.

3. Descubrible. Solo si quieres que extraños lo encuentren, no solo tu clase:

Canal

Qué obtienes

Temas de GitHub mcp, mcp-server, model-context-protocol

Tráfico de búsqueda gratuito

El registro oficial de MCP

Listado en las interfaces "explorar servidores" del cliente

Listas de la comunidad awesome-mcp-servers

PR para añadir tu repositorio

Smithery / Glama y directorios similares

Botones de instalación alojados

Los requisitos del registro cambian rápidamente — consulta la documentación actual del registro MCP para conocer el formato del manifiesto antes de publicar.

Una nota sobre el límite honesto. La gente adopta un servidor MCP cuando hace algo que ya no pueden hacer. Este envuelve un LLM genérico, que la mayoría de los clientes ya tienen incorporado — perfecto para enseñar el protocolo, débil como producto. Un servidor que accede a tu base de datos, tu API interna, o tus datos propietarios es el que consigue usuarios reales. Vale la pena decirlo en voz alta a la clase.


Parte 8 — Qué lo hace listo para producción

La versión del taller y la versión de producción difieren en aspectos que no tienen nada que ver con MCP. Esta es la lista, y cada elemento existe debido a un fallo que realmente ocurrió mientras se construía este servidor.

Protegiendo la clave

Un endpoint MCP público es un endpoint de gasto público: cada llamada te cuesta a ti.

Guarda

Variable de entorno

Por defecto

Motivo

Autenticación Bearer

MCP_AUTH_TOKEN

vacío = abierto

Bloquear el acceso una vez que haya una clave de pago detrás

Límite de tasa

RATE_LIMIT_PER_MIN

30/IP

Un script no puede agotar tu cuota

Límite de entrada

MAX_INPUT_CHARS

20000

Una novela pegada se rechaza antes de que cueste tokens

Límite de cuerpo

MAX_BODY_BYTES

1 MB

Los payloads sobredimensionados mueren antes de analizarse

La autenticación está desactivada por defecto para que el servidor permanezca abierto para un taller con una clave gratuita. Actívala antes de apuntar una clave de pago a una URL pública:

MCP_AUTH_TOKEN=$(python -c "import secrets;print(secrets.token_urlsafe(32))") python server.py --http

Los clientes envían entonces Authorization: Bearer <token>.

Sobreviviendo al proveedor

Los modelos se retiran sin previo aviso. Groq eliminó llama-3.3-70b-versatile durante el desarrollo: funcionaba a las 07:15 y daba un 404 una hora después. Todas las herramientas se rompieron a la vez, y un 404 se lee como "tu servidor está roto", no como "el proveedor se movió".

MODEL_CHAIN soluciona esto: en un error de modelo no encontrado, la llamada pasa al siguiente modelo en lugar de fallar. Otros errores (una clave incorrecta, un límite de tasa) fallan rápidamente, porque reintentarlos en cinco modelos solo pierde tiempo.

Los tiempos de espera (LLM_TIMEOUT_SECONDS) y los reintentos (LLM_MAX_RETRIES) se entregan a los SDK del proveedor, que ya implementan la retirada correctamente.

Comprobaciones de salud

/health devuelve JSON simple. Nunca hagas una comprobación de salud a /mcp — es un flujo SSE que permanece abierto por diseño, por lo que el sondeo se cuelga, la plataforma declara muerto el servicio y obtienes un bucle de reinicio que parece un fallo. Esto costó un ciclo de depuración real aquí.

Registro

Todo va a stderr, nunca a stdout. En modo stdio, stdout transporta el flujo JSON-RPC, por lo que un solo print() extraviado corrompe el protocolo. Esta es la forma más común de romper un servidor MCP mientras se depura.

El middleware a nivel MCP registra cada método con su duración y funciona para ambos transportes.

Pruebas e IC

pytest tests/ se ejecuta sin conexión, sin clave API y no gasta nada. Cubre la caducidad de la ventana del limitador de tasa, los límites de entrada, la alternativa de modelo, la preservación del esquema de herramientas y la validación de configuración.

GitHub Actions ejecuta el conjunto en 3.11 y 3.12, inicia el servidor y escanea todo el historial de git en busca de claves API comprometidas — el fallo que es irrecuperable, porque una clave enviada es pública en el momento en que llega.

Limitaciones conocidas

Vale la pena ser honesto con una clase sobre lo que aún falta:

  • El límite de tasa es por proceso. Escala a N instancias y permites N veces el límite. Cambia a Redis antes de que importe.

  • Un token compartido, no claves por usuario. Está bien para una clase, no para clientes.

  • Sin medición de uso. No puedes saber quién gastó qué.

  • Los arranques en frío del nivel gratuito aún tardan 30–50s después de la inactividad.


Mapa de archivos

Archivo

Por qué existe

server.py

Todo el servidor — herramientas, recurso, prompt

requirements.txt

mcp[cli] + groq + python-dotenv

Dockerfile

Contenedor para cualquier host

render.yaml

Despliegue con un clic en Render

fly.toml

Despliegue en Fly.io

.env.example

Qué variables de entorno existen

.mcp.json.example

Configuración de cliente para copiar

USING-IT.md

Página independiente para entregar a los usuarios

guards.py

Autenticación, límite de tasa, límites de tamaño, registro

tests/

Conjunto de pruebas sin conexión, no necesita clave API

.github/workflows/

IC: pruebas, comprobación de inicio, escaneo de secretos

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • MCP server for AI dialogue using various LLM models via AceDataCloud

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.

View all MCP Connectors

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/aihunter9892/mcpserver'

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