- Inicio
- Documentation
- MCP
- Autoría de servidores y herramientas MCP
Autoría de servidores y herramientas MCP
Este documento explica cómo las definiciones de servidores MCP se convierten en herramientas mcp_* invocables en coding-agent, y qué deben esperar los operadores cuando las configuraciones son inválidas, duplicadas, deshabilitadas o protegidas por autenticación.
Arquitectura general
Sección titulada «Arquitectura general»Config sources (.xcsh/.claude/.cursor/.vscode/mcp.json, mcp.json, etc.) -> discovery providers normalize to canonical MCPServer -> capability loader dedupes by server name (higher provider priority wins) -> loadAllMCPConfigs converts to MCPServerConfig + skips enabled:false -> MCPManager connects/listTools (with auth/header/env resolution) -> MCPTool/DeferredMCPTool bridge exposes tools as mcp_<server>_<tool> -> AgentSession.refreshMCPTools replaces live MCP tools immediately1) Modelo de configuración del servidor y validación
Sección titulada «1) Modelo de configuración del servidor y validación»src/mcp/types.ts define la forma de autoría utilizada por los escritores de configuración MCP y el entorno de ejecución:
stdio(valor por defecto cuandotypeestá ausente): requierecommand, opcionalesargs,env,cwdhttp: requiereurl, opcionalesheaderssse: requiereurl, opcionalesheaders(mantenido por compatibilidad)- campos compartidos:
enabled,timeout,auth
validateServerConfig() (src/mcp/config.ts) aplica las reglas básicas de transporte:
- rechaza configuraciones que definen tanto
commandcomourl - requiere
commandpara stdio - requiere
urlpara http/sse - rechaza
typedesconocido
config-writer.ts aplica esta validación para operaciones de agregar/actualizar y también valida los nombres de servidor:
- no vacío
- máximo 100 caracteres
- solo
[a-zA-Z0-9_.-]
Problemas comunes con el transporte
Sección titulada «Problemas comunes con el transporte»typeomitido significa stdio. Si su intención era HTTP/SSE pero omitiótype,commandse vuelve obligatorio.ssetodavía se acepta pero se trata internamente como transporte HTTP (createHttpTransport).- La validación es estructural, no de accesibilidad: una URL sintácticamente válida puede fallar al momento de la conexión.
2) Descubrimiento, normalización y precedencia
Sección titulada «2) Descubrimiento, normalización y precedencia»Descubrimiento basado en capacidades
Sección titulada «Descubrimiento basado en capacidades»loadAllMCPConfigs() (src/mcp/config.ts) carga elementos canónicos MCPServer mediante loadCapability(mcpCapability.id).
La capa de capacidades (src/capability/index.ts) entonces:
- carga proveedores en orden de prioridad
- elimina duplicados por
server.name(el primero gana = mayor prioridad) - valida los elementos sin duplicados
Resultado: los nombres de servidor duplicados entre distintas fuentes no se fusionan. Una definición gana; los duplicados de menor prioridad quedan ocultos.
.mcp.json y archivos relacionados
Sección titulada «.mcp.json y archivos relacionados»El proveedor de respaldo dedicado en src/discovery/mcp-json.ts lee mcp.json y .mcp.json de la raíz del proyecto (baja prioridad).
En la práctica, los servidores MCP también provienen de proveedores de mayor prioridad (por ejemplo, directorios nativos .xcsh/... y directorios de configuración específicos de herramientas). Guía de autoría:
- Prefiera
.xcsh/mcp.json(proyecto) o~/.xcsh/mcp.json(usuario) para control explícito. - Use
mcp.json/.mcp.jsonen la raíz cuando necesite compatibilidad de respaldo. - Reutilizar el mismo nombre de servidor en múltiples fuentes causa ocultamiento por precedencia, no fusión.
Comportamiento de normalización
Sección titulada «Comportamiento de normalización»convertToLegacyConfig() (src/mcp/config.ts) mapea el MCPServer canónico a MCPServerConfig de tiempo de ejecución.
Comportamiento clave:
- transporte inferido como
server.transport ?? (command ? "stdio" : url ? "http" : "stdio") - los servidores deshabilitados (
enabled === false) se eliminan antes de la conexión - los campos opcionales se preservan cuando están presentes
Expansión de variables de entorno durante el descubrimiento
Sección titulada «Expansión de variables de entorno durante el descubrimiento»mcp-json.ts expande marcadores de posición de variables de entorno en campos de texto con expandEnvVarsDeep():
- soporta
${VAR}y${VAR:-default} - los valores no resueltos permanecen como cadenas literales
${VAR}
mcp-json.ts también realiza verificaciones de tipo en tiempo de ejecución para JSON de usuario y registra advertencias para valores inválidos de enabled/timeout en lugar de hacer fallar todo el archivo.
3) Autenticación y resolución de valores en tiempo de ejecución
Sección titulada «3) Autenticación y resolución de valores en tiempo de ejecución»MCPManager.prepareConfig()/#resolveAuthConfig() (src/mcp/manager.ts) es el paso final antes de la conexión.
Inyección de credenciales OAuth
Sección titulada «Inyección de credenciales OAuth»Si la configuración tiene:
auth: { type: "oauth", credentialId: "..." }y la credencial existe en el almacenamiento de autenticación:
http/sse: inyecta el encabezadoAuthorization: Bearer <access_token>stdio: inyecta la variable de entornoOAUTH_ACCESS_TOKEN
Si la búsqueda de credenciales falla, el manager registra una advertencia y continúa con la autenticación sin resolver.
Resolución de valores de encabezados/variables de entorno
Sección titulada «Resolución de valores de encabezados/variables de entorno»Antes de conectar, el manager resuelve cada valor de encabezado/variable de entorno mediante resolveConfigValue() (src/config/resolve-config-value.ts):
- valor que comienza con
!=> ejecuta comando de shell, usa stdout recortado (en caché) - de lo contrario, trata el valor como nombre de variable de entorno primero (
process.env[name]), con respaldo al valor literal - los valores de comando/variable de entorno no resueltos se omiten del mapa final de encabezados/variables de entorno
Advertencia operativa: esto significa que un comando secreto o clave de variable de entorno mal escrita puede eliminar silenciosamente esa entrada de encabezado/variable de entorno, produciendo errores 401/403 o fallos de inicio del servidor aguas abajo.
4) Puente de herramientas: MCP -> herramientas invocables por el agente
Sección titulada «4) Puente de herramientas: MCP -> herramientas invocables por el agente»src/mcp/tool-bridge.ts convierte las definiciones de herramientas MCP en CustomTools.
Nombrado y dominio de colisiones
Sección titulada «Nombrado y dominio de colisiones»Los nombres de herramientas se generan como:
mcp_<sanitized_server_name>_<sanitized_tool_name>Reglas:
- se convierte a minúsculas
- caracteres que no son
[a-z_]se convierten en_ - guiones bajos repetidos se colapsan
- el prefijo redundante
<server>_en el nombre de la herramienta se elimina una vez
Esto evita muchas colisiones, pero no todas. Diferentes nombres originales pueden sanitizarse al mismo identificador (por ejemplo my-server y my.server se sanitizan de forma similar), y la inserción en el registro es último-en-escribir-gana.
Mapeo de esquema
Sección titulada «Mapeo de esquema»convertSchema() mantiene el JSON Schema de MCP mayormente tal cual, pero corrige esquemas de objetos que carecen de properties con {} para compatibilidad con proveedores.
Mapeo de ejecución
Sección titulada «Mapeo de ejecución»MCPTool.execute() / DeferredMCPTool.execute():
- llama a
tools/callde MCP - aplana el contenido MCP en texto visualizable
- devuelve detalles estructurados (
serverName,mcpToolName, metadatos del proveedor) - mapea
isErrorreportado por el servidor a resultado de textoError: ... - mapea fallos de transporte/tiempo de ejecución lanzados a
MCP error: ... - preserva la semántica de cancelación traduciendo AbortError en
ToolAbortError
5) Ciclo de vida del operador: agregar/editar/eliminar y actualizaciones en vivo
Sección titulada «5) Ciclo de vida del operador: agregar/editar/eliminar y actualizaciones en vivo»El modo interactivo expone /mcp en src/modes/controllers/mcp-command-controller.ts.
Operaciones soportadas:
add(asistente o adición rápida)remove/rmenable/disabletestreauth/unauthreload
Las escrituras de configuración son atómicas (writeMCPConfigFile: archivo temporal + renombrado).
Después de los cambios, el controlador llama a #reloadMCP():
mcpManager.disconnectAll()mcpManager.discoverAndConnect()session.refreshMCPTools(mcpManager.getTools())
refreshMCPTools() reemplaza todas las entradas mcp_ del registro y reactiva inmediatamente el conjunto más reciente de herramientas MCP, de modo que los cambios toman efecto sin reiniciar la sesión.
Diferencias según el modo
Sección titulada «Diferencias según el modo»- Modo interactivo/TUI:
/mcpproporciona UX dentro de la aplicación (asistente, flujo OAuth, texto de estado de conexión, reasociación inmediata en tiempo de ejecución). - Integración SDK/headless:
discoverAndLoadMCPTools()(src/mcp/loader.ts) devuelve herramientas cargadas + errores por servidor; sin UX del comando/mcp.
6) Superficies de error visibles para el usuario
Sección titulada «6) Superficies de error visibles para el usuario»Cadenas de error comunes que ven los usuarios/operadores:
- fallos de validación al agregar/actualizar:
Invalid server config: ...Server "<name>" already exists in <path>
- problemas con argumentos de adición rápida:
Use either --url or -- <command...>, not both.--token requires --url (HTTP/SSE transport).
- fallos de conexión/prueba:
Failed to connect to "<name>": <message>- texto de ayuda sobre timeout sugiere aumentar el tiempo de espera
- texto de ayuda de autenticación para
401/403
- flujos de autenticación/OAuth:
Authentication required ... OAuth endpoints could not be discoveredOAuth flow timed out. Please try again.OAuth authentication failed: ...
- uso de servidor deshabilitado:
Server "<name>" is disabled. Run /mcp enable <name> first.
El JSON de fuente incorrecto en el descubrimiento generalmente se maneja como advertencias/registros; las rutas de config-writer lanzan errores explícitos.
7) Guía práctica de autoría
Sección titulada «7) Guía práctica de autoría»Para una autoría MCP robusta en esta base de código:
- Mantenga los nombres de servidor globalmente únicos entre todas las fuentes de configuración compatibles con MCP.
- Prefiera nombres alfanuméricos/con guión bajo para evitar colisiones de nombres sanitizados en los nombres de herramientas
mcp_*generados. - Use
typeexplícito para evitar valores por defecto accidentales de stdio. - Trate
enabled: falsecomo apagado total: el servidor se omite del conjunto de conexión en tiempo de ejecución. - Para configuraciones OAuth, almacene un
credentialIdválido; de lo contrario la inyección de autenticación se omite. - Si usa resolución de secretos basada en comandos (
!cmd), verifique que la salida del comando sea estable y no vacía.