Creación de su primer servidor MCP
Use el SDK de MCP para Python para crear un servidor que exponga recursos, herramientas y mensajes, y conéctelo a Claude Desktop para comprobar su funcionamiento de principio a fin.
Creación de su primer servidor MCP es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.
Configuración del proyecto para un servidor MCP
Para crear un servidor MCP en Python se necesitan el SDK mcp y un entorno de Python. Creará un servidor al que Claude Desktop o cualquier cliente MCP podrá conectarse mediante stdio. Empiece instalando el paquete y creando el archivo del servidor.
# Create a project directory
# mkdir my_mcp_server && cd my_mcp_server
# Create a virtual environment
# python -m venv venv && source venv/bin/activate
# Install the MCP SDK
# pip install mcp httpx
# Project structure:
# my_mcp_server/
# server.py <- Your MCP server
# requirements.txt
# README.mdCreación del objeto de servidor
Importe elementos del paquete mcp y cree una instancia de Server con el nombre de su servidor. El nombre se muestra a los clientes en su lista de servidores MCP; elija uno descriptivo. El objeto de servidor es el punto de entrada para registrar todas sus herramientas, recursos y prompts.
# server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
import asyncio
import httpx
# Create the server — name is shown in Claude Desktop
app = Server('weather-server')
# --- Tool registrations go here ---
# Entry point
if __name__ == '__main__':
asyncio.run(stdio_server(app))Registro de herramientas con @app.list_tools()
El decorador @app.list_tools() registra un controlador que devuelve la lista de herramientas disponibles cuando el cliente la solicita. Cada herramienta se define con un nombre, una descripción y un inputSchema: el esquema JSON que describe sus parámetros. El cliente envía esta lista al LLM para que sepa qué herramientas puede invocar.
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name='get_weather',
description='Get current weather for a city. Use when the user asks about weather in a specific location.',
inputSchema={
'type': 'object',
'properties': {
'city': {
'type': 'string',
'description': 'City name, e.g. London or New York'
},
'units': {
'type': 'string',
'enum': ['metric', 'imperial'],
'description': 'Temperature units. Default is metric.'
}
},
'required': ['city']
}
),
types.Tool(
name='list_cities',
description='Return a list of major cities the user can query weather for.',
inputSchema={'type': 'object', 'properties': {}, 'required': []}
)
]Implementación de la ejecución de herramientas
El decorador @app.call_tool() gestiona la ejecución de herramientas. Cuando el cliente llama a una herramienta, este controlador recibe el nombre y los argumentos de la herramienta. Ejecute la lógica adecuada y devuelva una lista de objetos TextContent que contengan la cadena con el resultado.
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == 'list_cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney']
return [types.TextContent(type='text', text=', '.join(cities))]
if name == 'get_weather':
city = arguments['city']
units = arguments.get('units', 'metric')
unit_symbol = 'C' if units == 'metric' else 'F'
# Call real weather API (stub here)
async with httpx.AsyncClient() as client:
# Replace with actual API call
result = f'{city}: 18{chr(176)}{unit_symbol}, partly cloudy, humidity 65%'
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')Exponer recursos
Los recursos son datos estáticos o dinámicos que el modelo puede leer; considérelos como archivos. Defina los URI de los recursos e implemente un lector de recursos. Los recursos aparecen en el cliente como elementos a los que la IA puede hacer referencia, lo que resulta útil para la configuración, la documentación o las instantáneas de datos a las que se accede con frecuencia.
@app.list_resources()
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri='weather://supported-cities',
name='Supported Cities List',
description='Complete list of cities available in this weather server.',
mimeType='text/plain'
)
]
@app.read_resource()
async def read_resource(uri: str) -> str:
if uri == 'weather://supported-cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney', 'Dubai', 'Singapore']
return '\n'.join(cities)
raise ValueError(f'Unknown resource URI: {uri}')Registrar plantillas de prompts
Los prompts son plantillas de mensajes reutilizables que los clientes muestran a los usuarios como comandos de barra o acciones rápidas. Aceptan parámetros y devuelven una lista de mensajes que se convierten en el contexto inicial de una conversación. Los prompts son ideales para encapsular instrucciones complejas que los usuarios activan con un solo comando.
@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
return [
types.Prompt(
name='weather-report',
description='Generate a formatted weather report for a city.',
arguments=[
types.PromptArgument(name='city', description='City name', required=True)
]
)
]
@app.get_prompt()
async def get_prompt(name: str, arguments: dict) -> types.GetPromptResult:
if name == 'weather-report':
city = arguments.get('city', 'London')
return types.GetPromptResult(
description=f'Weather report for {city}',
messages=[
types.PromptMessage(
role='user',
content=types.TextContent(
type='text',
text=f'Use the get_weather tool to look up {city} and give me a detailed weather report including what clothing I should wear.'
)
)
]
)
raise ValueError(f'Unknown prompt: {name}')Conectarse a Claude Desktop
Para usar su servidor MCP con Claude Desktop, añádalo al archivo de configuración de Claude Desktop. En macOS, se encuentra en ~/Library/Application Support/Claude/claude_desktop_config.json. Especifique el comando para iniciar el servidor y las variables de entorno que necesita.
# ~/Library/Application Support/Claude/claude_desktop_config.json
# Add this JSON configuration:
# {
# "mcpServers": {
# "weather-server": {
# "command": "/path/to/venv/bin/python",
# "args": ["/path/to/my_mcp_server/server.py"],
# "env": {
# "WEATHER_API_KEY": "your_api_key_here"
# }
# }
# }
# }
# After saving, restart Claude Desktop.
# Your server's tools will appear in Claude's tool list.Probar su servidor con MCP CLI
Antes de conectarse a Claude Desktop, pruebe su servidor con el inspector de MCP o las herramientas de CLI. El comando mcp dev inicia el servidor y abre un inspector en el navegador desde el que puede llamar a las herramientas manualmente y ver los mensajes sin procesar del protocolo, lo que facilita la depuración de problemas.
# Install the MCP development tools
# pip install 'mcp[cli]'
# Start the inspector with your server
# mcp dev server.py
# The inspector opens at http://localhost:5173
# You can:
# - See all registered tools and their schemas
# - Call tools with custom arguments
# - Browse available resources
# - Test prompt templates
# - View the full JSON-RPC message exchangeGestión de errores en servidores MCP
Los servidores MCP nunca deben bloquearse debido a entradas incorrectas. Incluya toda la ejecución de herramientas en un bloque try/except y devuelva mensajes de error como TextContent en lugar de generar excepciones. Para errores críticos (problemas de configuración, claves de API ausentes), regístrelos durante el inicio y genere una excepción antes de que el servidor entre en su bucle principal.
@app.call_tool()
async def call_tool_safe(name: str, arguments: dict) -> list[types.TextContent]:
try:
if name == 'get_weather':
city = arguments.get('city')
if not city:
return [types.TextContent(type='text', text='Error: city argument is required.')]
result = await fetch_weather(city, arguments.get('units', 'metric'))
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')
except httpx.TimeoutException:
return [types.TextContent(type='text', text='Error: Weather API timed out. Try again.')]
except Exception as e:
return [types.TextContent(type='text', text=f'Error: {str(e)}')]Registro de eventos para servidores MCP
Dado que los servidores MCP se comunican con el cliente mediante stdio, las instrucciones de impresión interrumpirán el protocolo. Use siempre stderr para el registro: se envía a un flujo independiente que no interfiere con el intercambio de mensajes MCP. Configure el módulo de registro de Python para que escriba en stderr.
import logging
import sys
# Configure logging to stderr (NOT stdout — that's the MCP channel)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
stream=sys.stderr
)
logger = logging.getLogger('weather-server')
# In your tool handler:
# logger.info(f'Getting weather for {city}')
# logger.error(f'API call failed: {e}')
# Claude Desktop captures stderr to a log file:
# ~/Library/Logs/Claude/mcp-server-weather-server.logEmpaquetar su servidor MCP
Comparta su servidor MCP empaquetándolo con un pyproject.toml y publicándolo en PyPI, o distribúyalo como un contenedor de Docker para los equipos. Use variables de entorno para todos los secretos —claves de API y URL de bases de datos—, de modo que la configuración del servidor se mantenga separada del código. Documente las variables de entorno necesarias y un ejemplo de configuración en un README claro.
Comprobación rápida
Compruebe su comprensión de la creación de un servidor MCP en Python.
Resumen de la lección
En esta lección aprendió que: los servidores MCP exponen herramientas mediante los decoradores @app.list_tools() y @app.call_tool(), los recursos y los prompts amplían el servidor con datos legibles y plantillas reutilizables, y el registro debe usar stderr para evitar corromper el canal del protocolo MCP mediante stdio. A continuación, conectaremos un servidor MCP a una base de datos y expondremos recursos dinámicos con paginación.
Aprende Python con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 30
- Lecciones
- 120
Preguntas frecuentes
¿La lección «Creación de su primer servidor MCP» es gratis?
Sí — el texto completo de «Creación de su primer servidor MCP» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Creación de su primer servidor MCP»?
Use el SDK de MCP para Python para crear un servidor que exponga recursos, herramientas y mensajes, y conéctelo a Claude Desktop para comprobar su funcionamiento de principio a fin. Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Engineering Academy?
No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Creación de su primer servidor MCP»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?
Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Qué es MCP y por qué es importante
- Creación de su primer servidor MCP
- Exposición de recursos de bases de datos mediante MCP
- Seguridad y autenticación en MCP