- El SDK oficial de MCP existe en Python (
mcp) y TypeScript (@modelcontextprotocol/sdk). Ambos producen servidores 100% compatibles con la spec 2025-11-25. - FastMCP en Python permite definir herramientas con un simple decorador
@mcp.tool()sobre cualquier función Python normal. - Un servidor MCP stdio se conecta a Claude Desktop editando un único fichero JSON de configuración. No hay puertos ni servidores web necesarios en local.
- El mismo servidor funciona con Claude Desktop, Claude Code, Cursor, VS Code + Copilot y cualquier otro cliente que implemente la spec.
- Para producción remota, la spec exige Streamable HTTP como transporte y autenticación OAuth 2.1 con PKCE.
Arquitectura MCP: host, client y server
Antes de escribir código conviene tener clara la separación de responsabilidades que define la spec.
La arquitectura MCP separa tres roles bien definidos. El host es la aplicación que el usuario ve: Claude Desktop, VS Code, Cursor. El client es el objeto protocolario que el host crea por cada servidor al que se conecta; gestiona el ciclo de vida de la conexión y la negociación de capacidades. El server es el proceso que expones tú: declara herramientas, recursos y prompts, y responde a las peticiones del cliente.
Lo que tú construyes en este tutorial es el servidor. El host (Claude Desktop u otro cliente) se encarga de descubrir tus herramientas, presentarlas al modelo y enrutar las llamadas. Tu servidor solo necesita responder a las peticiones que llegan por el transporte que elijas: stdio para local, Streamable HTTP para remoto.
buscar_productos, crear_ticket.archivo://config.json.Instalar el SDK de MCP
El SDK oficial de Python se instala con pip o con uv. El tutorial usa Python 3.10+ y el paquete mcp[cli].
Instalación con pip (recomendado para empezar)
# Crear entorno virtual
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .venv\Scripts\activate # Windows
# Instalar el SDK con extras de CLI y FastMCP
pip install "mcp[cli]"
# Verificar la instalación
python -c "import mcp; print(mcp.__version__)"
Instalación con uv (alternativa rápida)
La documentación oficial de MCP recomienda uv como gestor de paquetes por su velocidad. Si ya lo tienes instalado:
# Crear proyecto con uv
uv init mi-servidor-mcp
cd mi-servidor-mcp
# Añadir dependencia MCP
uv add "mcp[cli]"
# Ejecutar con uv run (gestiona el entorno automáticamente)
uv run python server.py
[cli] instala FastMCP, las utilidades de línea de comandos mcp dev y mcp install, y todas las dependencias de transporte (stdio y Streamable HTTP). Es el punto de partida recomendado para nuevos servidores.El servidor más simple posible
Un servidor MCP mínimo funcional en cinco líneas de Python usando FastMCP.
FastMCP es la clase de alto nivel del SDK de Python. Gestiona el protocolo, el ciclo de vida y el transporte. Tú solo necesitas definir las herramientas como funciones normales con tipos Python y un docstring.
Guarda esto como server.py:
from mcp.server.fastmcp import FastMCP
# Nombre del servidor (visible en los clientes)
mcp = FastMCP("mi-primer-servidor")
@mcp.tool()
def sumar(a: int, b: int) -> int:
"""Suma dos numeros enteros y devuelve el resultado."""
return a + b
@mcp.tool()
def saludar(nombre: str) -> str:
"""Genera un saludo personalizado para la persona indicada."""
return f"Hola, {nombre}! Soy tu servidor MCP."
if __name__ == "__main__":
mcp.run(transport="stdio")
Para probar que el servidor arranca correctamente:
# Deberia arrancar sin errores (Ctrl+C para salir)
python server.py
# O con uv
uv run python server.py
El servidor espera conexiones por stdin/stdout. En este modo no verás nada en la terminal hasta que un cliente se conecte. Eso es correcto: el transporte stdio espera JSON-RPC por stdin. El servidor está listo para conectarse a Claude Desktop o a cualquier otro cliente.
Definir tools: la primitiva principal
Las tools son las acciones que el LLM puede invocar. FastMCP infiere el esquema JSON automáticamente desde los tipos Python.
Anatomía de una tool MCP
Cada tool tiene cuatro elementos: nombre (el nombre de la función), descripción (el docstring), esquema de entrada (inferido de los tipos de argumentos) y la lógica de ejecución (el cuerpo de la función). FastMCP genera el JSON Schema automáticamente desde los type hints de Python.
from mcp.server.fastmcp import FastMCP
from typing import Optional
mcp = FastMCP("catalogo-tools")
@mcp.tool()
def buscar_productos(
termino: str,
categoria: Optional[str] = None,
precio_max: Optional[float] = None,
) -> list[dict]:
"""
Busca productos en el catalogo por termino y filtros opcionales.
Args:
termino: Texto a buscar en el nombre y descripcion del producto.
categoria: Categoria opcional para filtrar (electronica, ropa, hogar...).
precio_max: Precio maximo en euros. Si no se indica, sin limite.
Returns:
Lista de productos encontrados con id, nombre y precio.
"""
# Logica real aqui: consulta a base de datos, API, etc.
# Ejemplo simulado:
productos = [
{"id": 1, "nombre": "Teclado mecanico", "precio": 89.99, "categoria": "electronica"},
{"id": 2, "nombre": "Raton ergonomico", "precio": 49.99, "categoria": "electronica"},
]
resultados = [p for p in productos if termino.lower() in p["nombre"].lower()]
if categoria:
resultados = [p for p in resultados if p["categoria"] == categoria]
if precio_max is not None:
resultados = [p for p in resultados if p["precio"] <= precio_max]
return resultados
@mcp.tool()
async def obtener_precio_actual(simbolo: str) -> dict:
"""
Consulta el precio actual de un ticker de bolsa.
Usa un simbolo como AAPL, MSFT o GOOGL.
"""
import httpx
# Ejemplo con llamada HTTP real (simulada aqui)
# async with httpx.AsyncClient() as client:
# resp = await client.get(f"https://api.ejemplo.com/price/{simbolo}")
# return resp.json()
return {"simbolo": simbolo, "precio": 150.25, "moneda": "USD"}
if __name__ == "__main__":
mcp.run(transport="stdio")
Reglas para buenas tools MCP
Docstrings claros y completos
El docstring es la descripción que el LLM usa para decidir si invocar la tool. Cuanto más precisa sea la descripción de qué hace, cuándo usarla y qué devuelve, mejor elegirá el modelo cuándo usarla.
Tipos Python estrictos
FastMCP convierte los type hints en JSON Schema. Usa tipos precisos: str, int, float, bool, list[str], Optional[str]. Evita Any o tipos sin anotar.
Funciones sync y async
FastMCP soporta tanto funciones síncronas como async def. Usa async cuando hagas llamadas HTTP, operaciones de IO o consultas a bases de datos para no bloquear el event loop.
Errores con excepciones Python normales
Si la tool falla, lanza una excepción Python normal. FastMCP la convierte en un error MCP correcto que el cliente puede manejar. No devuelvas mensajes de error como si fueran resultados exitosos.
Definir resources: datos para el contexto
Los resources exponen fuentes de datos que el host puede leer y añadir al contexto del modelo. A diferencia de las tools, no se invocan por el LLM sino por el host.
Un resource en MCP tiene una URI (como config://app o archivo://README.md) y devuelve texto o datos binarios cuando el cliente lo lee. FastMCP usa el decorador @mcp.resource() con la URI como patrón.
from mcp.server.fastmcp import FastMCP
from pathlib import Path
mcp = FastMCP("servidor-con-resources")
# Resource estatico: siempre devuelve el mismo contenido
@mcp.resource("config://aplicacion")
def config_aplicacion() -> str:
"""Configuracion actual de la aplicacion en formato texto."""
return """
version: 1.2.0
entorno: produccion
base_de_datos: postgresql://localhost:5432/miapp
max_conexiones: 100
"""
# Resource dinamico: lee un archivo del sistema
@mcp.resource("archivo://{nombre_archivo}")
def leer_archivo(nombre_archivo: str) -> str:
"""
Lee el contenido de un archivo del directorio de datos.
Usa rutas relativas como datos/config.json o logs/app.log.
"""
ruta = Path("datos") / nombre_archivo
if not ruta.exists():
raise FileNotFoundError(f"Archivo no encontrado: {nombre_archivo}")
if not ruta.is_relative_to(Path("datos")):
raise PermissionError("Solo se pueden leer archivos del directorio datos/")
return ruta.read_text(encoding="utf-8")
# Resource que lista elementos disponibles
@mcp.resource("lista://usuarios")
async def lista_usuarios() -> str:
"""Lista de usuarios activos en el sistema en formato JSON."""
import json
# Aqui iria la consulta real a la base de datos
usuarios = [
{"id": 1, "nombre": "Ana Garcia", "rol": "admin"},
{"id": 2, "nombre": "Carlos Lopez", "rol": "usuario"},
]
return json.dumps(usuarios, ensure_ascii=False, indent=2)
if __name__ == "__main__":
mcp.run(transport="stdio")
Los resources aparecen en el panel de contexto de Claude Desktop (el icono de clip). El usuario puede seleccionarlos para incluirlos en la conversación. El host decide qué resources añadir al contexto; el LLM no puede invocarlos directamente como hace con las tools.
Conectar el servidor a Claude Desktop
Una vez que el servidor funciona localmente, conectarlo a Claude Desktop requiere editar un único fichero de configuración JSON.
Localizar el fichero de configuración
Claude Desktop lee la configuración de servidores MCP desde:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Si el fichero no existe, créalo. Si ya existe, añade tu servidor dentro de mcpServers.
Configuración para un servidor Python local
{
"mcpServers": {
"mi-servidor": {
"command": "/ruta/absoluta/a/tu/.venv/bin/python",
"args": ["/ruta/absoluta/a/tu/server.py"]
}
}
}
El campo command debe apuntar al Python del entorno virtual donde instalaste el SDK, no al Python del sistema. Si usas Windows:
{
"mcpServers": {
"mi-servidor": {
"command": "C:\\ruta\\a\\tu\\.venv\\Scripts\\python.exe",
"args": ["C:\\ruta\\a\\tu\\server.py"]
}
}
}
Configuración con variables de entorno
Si tu servidor necesita credenciales o configuración por entorno, pásalas en el campo env:
{
"mcpServers": {
"mi-servidor": {
"command": "/ruta/.venv/bin/python",
"args": ["/ruta/server.py"],
"env": {
"DATABASE_URL": "postgresql://localhost:5432/miapp",
"API_KEY": "tu-clave-api-aqui"
}
}
}
}
Instalar usando el CLI de MCP (alternativa)
Si instalaste el SDK con el extra [cli], puedes usar el comando mcp install para registrar el servidor automáticamente en Claude Desktop:
# Instalar el servidor en Claude Desktop
mcp install server.py --name "mi-servidor"
# Verificar que aparece en la configuracion
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
Verificar la conexión en Claude Desktop
Después de editar el fichero de configuración, reinicia Claude Desktop. Si el servidor se conecta correctamente:
- Veras el icono del martillo (herramientas) en el panel de composición.
- Al hacer clic mostrara las tools que tu servidor declara.
- Puedes hacer una pregunta que requiera una tool para probar que el flujo funciona de extremo a extremo.
Servidor MCP que consulta una base de datos SQLite
Un ejemplo funcional y completo: un servidor MCP que expone herramientas para leer y escribir en una base de datos SQLite local. Puedes probarlo sin dependencias externas.
Guarda el siguiente código como servidor_bd.py. Incluye inicialización de la base de datos, tres tools (listar tablas, ejecutar consultas SELECT y insertar registros) y un resource que expone el esquema completo.
"""
Servidor MCP que expone una base de datos SQLite a traves del protocolo MCP.
Herramientas:
- listar_tablas: devuelve las tablas de la base de datos
- consultar: ejecuta una query SELECT y devuelve los resultados como JSON
- insertar_tarea: anade una tarea a la tabla 'tareas'
Resources:
- schema://base-de-datos: esquema SQL de la base de datos
"""
import json
import sqlite3
from pathlib import Path
from mcp.server.fastmcp import FastMCP
# Inicializar FastMCP
mcp = FastMCP("servidor-sqlite")
# Ruta de la base de datos (relativa al script)
DB_PATH = Path(__file__).parent / "datos.db"
def get_conn() -> sqlite3.Connection:
"""Abre una conexion a SQLite con row_factory para devolver dicts."""
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
return conn
def inicializar_db() -> None:
"""Crea las tablas si no existen y anade datos de ejemplo."""
conn = get_conn()
conn.executescript("""
CREATE TABLE IF NOT EXISTS tareas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
titulo TEXT NOT NULL,
hecho INTEGER DEFAULT 0,
creado TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS notas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
contenido TEXT NOT NULL,
creado TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT OR IGNORE INTO tareas (id, titulo, hecho)
VALUES (1, 'Revisar documentacion MCP', 0);
INSERT OR IGNORE INTO tareas (id, titulo, hecho)
VALUES (2, 'Construir primer servidor MCP', 0);
INSERT OR IGNORE INTO notas (id, contenido)
VALUES (1, 'MCP usa JSON-RPC 2.0 sobre stdio o HTTP.');
""")
conn.commit()
conn.close()
# ─── TOOLS ────────────────────────────────────────────────────────────────────
@mcp.tool()
def listar_tablas() -> list[str]:
"""
Devuelve los nombres de todas las tablas de la base de datos.
Util para explorar la estructura antes de hacer consultas.
"""
conn = get_conn()
rows = conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
).fetchall()
conn.close()
return [row["name"] for row in rows]
@mcp.tool()
def consultar(sql: str, limite: int = 50) -> str:
"""
Ejecuta una consulta SQL SELECT en la base de datos y devuelve los resultados.
Solo se permiten sentencias SELECT. Usa LIMIT para no cargar demasiados datos.
Devuelve los resultados como JSON.
Args:
sql: Sentencia SELECT. Ejemplo: SELECT * FROM tareas WHERE hecho = 0
limite: Numero maximo de filas a devolver (por defecto 50, maximo 200).
"""
# Validacion de seguridad: solo SELECT
sql_limpio = sql.strip().upper()
if not sql_limpio.startswith("SELECT"):
raise ValueError("Solo se permiten sentencias SELECT.")
limite = min(limite, 200)
# Inyectar LIMIT si no lo tiene la query
if "LIMIT" not in sql_limpio:
sql = f"{sql.rstrip(';')} LIMIT {limite}"
conn = get_conn()
try:
rows = conn.execute(sql).fetchall()
resultados = [dict(row) for row in rows]
return json.dumps(resultados, ensure_ascii=False, indent=2, default=str)
except sqlite3.Error as e:
raise ValueError(f"Error en la query SQL: {e}") from e
finally:
conn.close()
@mcp.tool()
def insertar_tarea(titulo: str) -> dict:
"""
Anade una nueva tarea a la base de datos.
Args:
titulo: Titulo de la tarea. Debe ser descriptivo y no estar vacio.
Returns:
Diccionario con el id asignado y el titulo de la tarea creada.
"""
if not titulo.strip():
raise ValueError("El titulo de la tarea no puede estar vacio.")
conn = get_conn()
cursor = conn.execute(
"INSERT INTO tareas (titulo) VALUES (?)",
(titulo.strip(),),
)
conn.commit()
nuevo_id = cursor.lastrowid
conn.close()
return {"id": nuevo_id, "titulo": titulo.strip(), "hecho": False}
@mcp.tool()
def marcar_tarea_hecha(id_tarea: int) -> str:
"""
Marca una tarea como completada dado su ID.
Args:
id_tarea: ID numerico de la tarea a marcar como hecha.
"""
conn = get_conn()
conn.execute("UPDATE tareas SET hecho = 1 WHERE id = ?", (id_tarea,))
conn.commit()
conn.close()
return f"Tarea {id_tarea} marcada como completada."
# ─── RESOURCES ────────────────────────────────────────────────────────────────
@mcp.resource("schema://base-de-datos")
def esquema_bd() -> str:
"""
Devuelve el esquema SQL completo de la base de datos.
Util para que el LLM conozca la estructura antes de hacer consultas.
"""
conn = get_conn()
rows = conn.execute(
"SELECT sql FROM sqlite_master WHERE type='table' AND sql IS NOT NULL ORDER BY name"
).fetchall()
conn.close()
schemas = [row["sql"] for row in rows]
return "\n\n".join(schemas)
# ─── ARRANQUE ─────────────────────────────────────────────────────────────────
if __name__ == "__main__":
inicializar_db()
mcp.run(transport="stdio")
Configuración en Claude Desktop para este ejemplo
{
"mcpServers": {
"base-de-datos-local": {
"command": "/ruta/a/.venv/bin/python",
"args": ["/ruta/a/servidor_bd.py"]
}
}
}
Una vez conectado, puedes preguntarle a Claude cosas como: "Lístame las tareas pendientes", "Crea una tarea llamada Revisar logs de producción" o "Muestra todas las notas". Claude invocará las tools del servidor automáticamente.
Versión TypeScript del mismo servidor
El SDK oficial de TypeScript (@modelcontextprotocol/sdk) produce servidores 100% compatibles. El patrón es equivalente al de Python.
Instalación del SDK TypeScript
# Inicializar proyecto Node.js
mkdir mi-servidor-mcp-ts && cd mi-servidor-mcp-ts
npm init -y
# Instalar dependencias
npm install @modelcontextprotocol/sdk zod
# TypeScript (opcional pero recomendado)
npm install -D typescript @types/node tsx
Servidor MCP mínimo en TypeScript
Guarda como server.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import * as z from "zod";
// Instanciar el servidor MCP
const server = new McpServer({
name: "mi-servidor-ts",
version: "1.0.0",
});
// Registrar una tool: sumar
server.registerTool(
"sumar",
{
description: "Suma dos numeros enteros y devuelve el resultado.",
inputSchema: z.object({
a: z.number().int().describe("Primer numero"),
b: z.number().int().describe("Segundo numero"),
}),
},
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
}),
);
// Registrar otra tool: buscar en la base de conocimiento
server.registerTool(
"buscar_kb",
{
description:
"Busca un termino en la base de conocimiento y devuelve articulos relacionados.",
inputSchema: z.object({
termino: z.string().describe("Texto a buscar"),
limite: z.number().int().min(1).max(20).default(5),
}),
},
async ({ termino, limite }) => {
// Logica real de busqueda aqui
const articulos = [
{ id: 1, titulo: "Introduccion a MCP", relevancia: 0.95 },
{ id: 2, titulo: "Servidores MCP en produccion", relevancia: 0.82 },
]
.filter((a) => a.titulo.toLowerCase().includes(termino.toLowerCase()))
.slice(0, limite);
return {
content: [
{
type: "text",
text: JSON.stringify(articulos, null, 2),
},
],
};
},
);
// Nota CRITICA para stdio: usa console.error(), NUNCA console.log()
// console.log() escribe en stdout y corrompe el canal JSON-RPC
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Servidor MCP arrancado y esperando conexiones...");
}
main().catch((err) => {
console.error("Error fatal:", err);
process.exit(1);
});
Ejecutar el servidor TypeScript
# Con tsx (sin compilar, recomendado para desarrollo)
npx tsx server.ts
# Compilar y ejecutar con node
npx tsc
node dist/server.js
console.log() en un servidor MCP con transporte stdio. El stdout es el canal JSON-RPC exclusivo del protocolo. Cualquier texto que escribas en stdout corrompe el flujo y el cliente no podrá parsear los mensajes. Usa siempre console.error() para logs y depuración: escribe en stderr, que el host gestiona por separado.Probar y depurar el servidor MCP
El SDK incluye herramientas para probar el servidor sin necesitar Claude Desktop. También hay un inspector visual oficial.
MCP Inspector: interfaz visual para probar tools
El MCP Inspector es una herramienta web oficial que se conecta a tu servidor y permite invocar tools y leer resources desde una interfaz gráfica. Es el método más rápido para depurar sin necesitar Claude Desktop.
# Ejecutar el inspector con tu servidor (Python)
npx @modelcontextprotocol/inspector python server.py
# Con TypeScript
npx @modelcontextprotocol/inspector npx tsx server.ts
# El inspector abre en http://localhost:5173 por defecto
Prueba desde línea de comandos con mcp dev
# El modo dev del SDK arranca el servidor con hot-reload
mcp dev server.py
# O con uv
uv run mcp dev server.py
Errores comunes y cómo resolverlos
| Error | Causa probable | Solución |
|---|---|---|
| El servidor no aparece en Claude Desktop | Ruta incorrecta en claude_desktop_config.json |
Verifica que la ruta al Python del virtualenv es absoluta y correcta. Reinicia Claude Desktop después de cada cambio en el JSON. |
| Las tools no se muestran | El servidor arranca pero falla silenciosamente | Ejecuta el servidor manualmente desde la terminal. Revisa los logs de Claude Desktop en ~/Library/Logs/Claude/ (macOS) o %APPDATA%\Claude\logs\ (Windows). |
| Error de parseo JSON en el cliente | print() o console.log() en el servidor |
En Python, no uses print() para logs; usa sys.stderr.write(). En TypeScript, usa console.error() en lugar de console.log(). |
| ModuleNotFoundError al arrancar | SDK instalado en el Python del sistema, no en el virtualenv | Activa el entorno virtual antes de instalar: source .venv/bin/activate. Usa la ruta absoluta al Python del venv en la configuración de Claude Desktop. |
| Tool no se invoca aunque el prompt la requiere | Descripción de la tool poco clara o ambigua | Mejora el docstring: específica exactamente qué hace la tool, cuándo usarla y qué datos devuelve. El LLM usa la descripción para decidir si invocarla. |
Preguntas frecuentes sobre el tutorial MCP
Con FastMCP en Python, un servidor MCP con dos o tres herramientas tarda menos de 30 minutos desde cero: instalar el SDK, escribir las funciones con decoradores @mcp.tool() y conectarlo a Claude Desktop. El tiempo aumenta si el servidor necesita acceso a bases de datos, APIs externas o autenticación OAuth.
Las tools son acciones que el LLM puede invocar para obtener un resultado o producir un efecto (consultar una API, ejecutar una query SQL, enviar un mensaje). Los resources son fuentes de datos que el host puede leer y añadir al contexto del modelo (archivos, registros de base de datos, documentos). La diferencia principal es que las tools tienen efectos secundarios y los resources son típicamente de solo lectura.
Sí. Anthropic mantiene un SDK oficial de TypeScript en github.com/modelcontextprotocol/typescript-sdk. El patrón es equivalente al de Python: creas una instancia de McpServer, registras herramientas con server.registerTool() usando esquemas Zod, y conectas un StdioServerTransport. Ambos SDKs son oficialmente mantenidos y producen servidores 100% compatibles con la spec MCP 2025-11-25.
El primer paso es ejecutar el servidor manualmente desde la terminal para verificar que arranca sin errores. Después, revisa los logs de Claude Desktop en ~/Library/Logs/Claude/ (macOS) o %APPDATA%\Claude\logs\ (Windows). El error más común es una ruta incorrecta en claude_desktop_config.json: la clave "command" debe apuntar al ejecutable Python del entorno virtual donde instalaste el SDK, no al Python del sistema.
Para servidores locales (en la misma máquina que el cliente), stdio es el transporte recomendado: simple, sin puertos abiertos y seguro por defecto. Para servidores remotos accesibles por red, la spec 2025-11-25 define Streamable HTTP como el transporte estándar, con soporte opcional para SSE legacy para compatibilidad con clientes antiguos. En producción remota es obligatorio implementar autenticación OAuth 2.1.
Sí. Cualquier servidor MCP correcto es compatible con todos los clientes que implementen la spec: Claude Code, VS Code con GitHub Copilot, Cursor, Continue, Zed y otros. La configuración cambia según el cliente (en Cursor editas ~/.cursor/mcp.json, en VS Code editas settings.json) pero el servidor en sí no necesita ningún cambio. Consulta la página de clientes MCP para ver la configuración específica de cada uno.
Descubre todos los clientes MCP disponibles
Tu servidor MCP funciona con Claude Desktop, Claude Code, Cursor, VS Code y muchos más. Consulta la guía de clientes para ver cómo configurar cada uno y comparar su nivel de soporte de la spec.
Ver clientes MCP