Skip to main content
Skip to content

Uso de servidores MCP con el SDK de GitHub Copilot

El SDK de Copilot puede integrarse con servidores MCP (Protocolo de contexto de modelo) para ampliar las funcionalidades del asistente con herramientas externas. Los servidores MCP se ejecutan como procesos independientes y exponen herramientas (funciones) que Copilot pueden invocar durante las conversaciones.

Nota:

Esta es una característica en evolución. Consulte la issue n.º 36 para seguir la discusión en curso.

¿Qué es MCP?

El Protocolo de contexto de modelo (MCP) es un estándar abierto para conectar asistentes de IA a herramientas externas y orígenes de datos. Los servidores MCP pueden:

  • Ejecutar código o secuencias de comandos
  • Consulta de bases de datos
  • Acceso a sistemas de archivos
  • Llamar a las API externas
  • Y mucho más

Tipos de servidor

El SDK admite dos tipos de servidores MCP:

TipoDescriptionCaso de uso
Local/StdioSe ejecuta como un subproceso, se comunica a través de stdin/stdout.Herramientas locales, acceso a archivos, scripts personalizados
HTTP/SSEServidor remoto al que se accede a través de HTTPServicios compartidos, herramientas hospedadas en la nube

Configuración

Inspeccionar la configuración y el ciclo de vida

session.rpc.mcp.listConfigured() es una lectura pasiva de inventario sin parámetros. No inicia ni reinicia servidores, autenticar, aplicar directiva de espacio aislado o esperar a que se inicie el servidor. La detección de configuración y el filtrado de directivas determinan qué servidores aparecen y sus valores enabled.

Esta RPC experimental requiere una versión alineada del SDK y del entorno de ejecución. Su respuesta preliminar anterior permitía omitir live; los SDKs que usan el contrato de ciclo de vida necesario no admiten esa forma de respuesta anterior. Al proporcionar un entorno de ejecución externo, actualícelo junto con el SDK. La versión general del protocolo no cambia y no identifica esta revisión experimental del contrato.

Cada entrada incluye live.status. Un servidor configurado sin servidor en tiempo de ejecución materializado notifica el estado existente not_configured , incluso cuando enabled es true. Un servidor en tiempo de ejecución que se detuvo explícitamente informa de stopped. Los servidores materializados notifican su ciclo de vida real, incluidos pending, connected, needs-auth y failed; los fallos incluyen live.error cuando están disponibles.

La configuración y el ciclo de vida describen hechos diferentes. Si cambia la dirección URL, la autenticación o el origen de configuración de un servidor mientras una conexión antigua permanece activa, el inventario sigue informando del ciclo de vida real de esa conexión. El estado connected no significa que se haya aplicado la configuración más reciente. El tiempo de ejecución posee este registro; los clientes no deben sustituir el estado almacenado en caché solo en función del nombre del servidor.

Inventory reintenta el reemplazo simultáneo del grafo un número limitado de veces y devuelve un error si no puede obtener una instantánea coherente. Nunca omite live para ocultar una condición de carrera del grafo.

Una referencia solo con nombre startServer o restartServer resuelve e inicializa solo el servidor solicitado después de reanudar una sesión en frío sin llamar primero a list. Esto incluye configuraciones de usuario y de complementos y el servidor de GitHub integrado configurado a través de githubMcpToolConfig. No inicia otros servidores configurados ni anula el estado de deshabilitación, los requisitos de autenticación, la directiva de espacio aislado o la precedencia del origen de la configuración.

Node.js/TypeScript

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({
    model: "gpt-5",
    mcpServers: {
        // Local MCP server (stdio)
        "my-local-server": {
            type: "local",
            command: "node",
            args: ["./mcp-server.js"],
            env: { DEBUG: "true" },
            cwd: "./servers",
            tools: ["*"],  // "*" = all tools, [] = none, or list specific tools
            timeout: 30000,
        },
        // Remote MCP server (HTTP)
        "github": {
            type: "http",
            url: "https://api.githubcopilot.com/mcp/",
            headers: { "Authorization": "Bearer ${TOKEN}" },
            tools: ["*"],
        },
    },
});

Python

import asyncio
from copilot import CopilotClient
from copilot.session import PermissionHandler

async def main():
    client = CopilotClient()
    await client.start()

    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5", mcp_servers={
        # Local MCP server (stdio)
        "my-local-server": {
            "type": "local",
            "command": "python",
            "args": ["./mcp_server.py"],
            "env": {"DEBUG": "true"},
            "cwd": "./servers",
            "tools": ["*"],
            "timeout": 30000,
        },
        # Remote MCP server (HTTP)
        "github": {
            "type": "http",
            "url": "https://api.githubcopilot.com/mcp/",
            "headers": {"Authorization": "Bearer ${TOKEN}"},
            "tools": ["*"],
        },
    })

    response = await session.send_and_wait("List my recent GitHub notifications")
    print(response.data.content)

    await client.stop()

asyncio.run(main())

Go

package main

import (
    "context"
    "log"
    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)
    if err := client.Start(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Model: "gpt-5",
        MCPServers: map[string]copilot.MCPServerConfig{
            "my-local-server": copilot.MCPStdioServerConfig{
                Command: "node",
                Args:    []string{"./mcp-server.js"},
                Tools:   []string{"*"},
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    defer session.Disconnect()

    // Use the session...
}

.NET

using GitHub.Copilot;

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    Model = "gpt-5",
    McpServers = new Dictionary<string, McpServerConfig>
    {
        ["my-local-server"] = new McpStdioServerConfig
        {
            Command = "node",
            Args = new List<string> { "./mcp-server.js" },
            Tools = new List<string> { "*" },
        },
    },
});

Deshabilitación de servidores configurados por sesión

Establece disabledMcpServers con los nombres exactos de los servidores MCP que no deben ejecutarse en una sesión. El ámbito de la configuración es la solicitud individual de creación o reanudación; no modifica la configuración global de MCP ni la configuración del servidor.

const session = await client.createSession({
    mcpServers: {
        filesystem: { type: "local", command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "."] },
        github: { type: "http", url: "https://api.githubcopilot.com/mcp/" },
    },
    disabledMcpServers: ["github"],
});
SDKPropiedad de configuración
Node.jsdisabledMcpServers
Pythondisabled_mcp_servers
GoDisabledMCPServers
.NETDisabledMcpServers
JavasetDisabledMcpServers(...)
Óxidowith_disabled_mcp_servers(...)

Al crear una sesión y al reanudarla en estado frío, los servidores desactivados no se inician y el tiempo de ejecución no inicia su autenticación. Una reanudación residente no puede deshacer un servidor que el tiempo de ejecución ya haya generado. Los nombres coinciden exactamente.

Enumeración y recuperación de prompts

El espacio de nombres MCP generado experimentalmente expone los métodos JSON-RPC wire session.mcp.prompts.list y session.mcp.prompts.get. Utilice los métodos de acceso del SDK específicos del lenguaje siguientes para llamarlos. Estos métodos tienen como destino un servidor conectado en la sesión actual; no combinan resultados de varios servidores.

SDKLista de avisosConsigue una indicación
Node.jssession.rpc.mcp.prompts.list(...)session.rpc.mcp.prompts.get(...)
Pythonsession.rpc.mcp.prompts.list(...)session.rpc.mcp.prompts.get(...)
Gosession.RPC.MCP.Prompts().List(...)session.RPC.MCP.Prompts().Get(...)
.NETsession.Rpc.Mcp.Prompts.ListAsync(...)session.Rpc.Mcp.Prompts.GetAsync(...)
Javasession.getRpc().mcp.prompts.list(...)session.getRpc().mcp.prompts.get(...)
Óxidosession.rpc().mcp().prompts().list(...)session.rpc().mcp().prompts().get(...)

La enumeración requiere serverName y acepta una opaca cursoropcional. Cada llamada devuelve una página de definiciones de prompts tipadas y un nextCursor opcional. Pase ese cursor en otra llamada a la API de listado para solicitar la página siguiente. Las definiciones incluyen nombres, títulos opcionales y descripciones opcionales, y definiciones de argumentos. La marca required de un argumento omitido permanece distinta de false.

La obtención de un prompt requiere serverName y promptName, con un diccionario opcional arguments cuyos valores son cadenas. La omisión arguments deja ausentes los argumentos de la solicitud MCP; pasar {} envía un diccionario vacío explícitamente. El tiempo de ejecución conserva esta distinción para el servidor. El resultado contiene una descripción opcional y mensajes ordenados con roles tipados y JSON contentopaco. Inspeccione el type de cada bloque de contenido antes de interpretarlo; el contenido no se aplana en texto. Los recursos anidados, las anotaciones, los metadatos, los tipos de contenido desconocidos y los campos de contenido adicionales conservan su estructura JSON. Las extensiones de servidor en descriptores, mensajes y sobres de resultados con tipo están disponibles en additionalProperties. Una extensión de servidor denominada additionalProperties se conserva como una entrada dentro de ese mapa, no se fusiona con él. El tiempo de ejecución consume el discriminador de nivel superior resultType: "complete" del protocolo; no se devuelve como un campo del SDK ni una extensión de servidor. Las solicitudes fallan explícitamente si el tiempo de ejecución no puede conservar la respuesta sin procesar, incluidos los fotogramas de respuesta stdio que superan el límite de captura de 1 MiB.

Los mensajes de solicitud devueltos no se envían automáticamente al modelo ni se usan para ejecutar herramientas u obtener los recursos a los que se hace referencia. La aplicación decide cómo usar el resultado. Al generar ese resultado, un servidor MCP puede solicitar sampling u obtención de información a través de continuaciones con varias idas y vueltas. Estas solicitudes usan los mismos respondedores host configurados que otras operaciones de MCP; la recuperación de prompts no concede permiso adicional ni omite la decisión del host. La ausencia de un respondedor o un error del respondedor hace fallar la solicitud, y se devuelve al servidor sin cambios un rechazo de la elicitación. Las continuaciones de solo estado no invocan a ninguno de los respondedores.

Después de un evento de sesión existente mcp.prompts.list_changed, vuelva a mostrar las indicaciones del servidor especificado para actualizar la vista de la aplicación.

Aplicación de la directiva de espacio aislado antes del inicio de MCP

Pasa sandboxConfig a createSession o resumeSession para aplicar la directiva de espacio aislado durante la construcción, antes de que se inicien la configuración raíz detectada, el complemento, o los servidores MCP configurados explícitamente. Acepta la misma configuración que session.rpc.options.update({ sandboxConfig }).

const sandboxConfig = {
    enabled: true,
    sandboxMcpServers: true,
    userPolicy: { network: { allowOutbound: false } },
};
const session = await client.createSession({
    onPermissionRequest: approveAll,
    sandboxConfig,
});

Vuelva a aplicar la configuración en una reanudación en frío; la omisión conserva la directiva actual de una sesión residente. Una reanudación en segundo plano no puede deshacer los procesos que ya se iniciaron. La validación de directivas administradas usa la misma semántica de host directo que una actualización de opciones: una solicitud en conflicto produce un error al crear o reanudar en lugar de revertir a una sesión sin aislamiento, con data.code establecido a managed_sandbox_policy_conflict en el error de JSON-RPC. El tiempo de ejecución no asigna un valor derivado de la configuración sandboxConfigSource a esta configuración de host explícita.

Una versión posterior idéntica options.update({ sandboxConfig }) no reinicia los servidores MCP, incluido cuando la directiva administrada ha normalizado la configuración. Una directiva de espacio aislado de MCP eficaz diferente conserva el comportamiento de reinicio habitual.

Compruebe el tiempo de ejecución version devuelto por server.connect (ConnectResult) con la versión mínima del entorno de ejecución que requiere la aplicación para esta característica. La versión del protocolo SDK no es una señal de capacidad por característica. Los entornos de ejecución anteriores omiten los campos create/resume desconocidos, por lo que una aplicación que los admite puede enviar sandboxConfig al abrir y repetirlo en una actualización de opciones de seguimiento. Esa actualización es inofensiva en los entornos de ejecución compatibles, pero los entornos de ejecución más antiguos todavía pueden iniciar MCP antes de que llegue la actualización; se requiere una versión de entorno de ejecución compatible cuando el aislamiento desde el primer proceso es obligatorio.

Herramienta de configuración

Puede controlar qué herramientas están disponibles para un servidor MCP mediante el tools campo .

Permitir el acceso a todas las herramientas

Use "*" para habilitar todas las herramientas proporcionadas por el servidor MCP:

tools: ["*"]

Permitir herramientas específicas

Proporcione una lista de nombres de herramientas para restringir el acceso:

tools: ["bash", "edit"]

Solo las herramientas enumeradas estarán disponibles para el agente.

Deshabilitar todas las herramientas

Use una matriz vacía para deshabilitar todas las herramientas:

tools: []

Notes

  • El tools campo define qué herramientas se permiten.
  • No existe una configuración independiente de allow o disallow; el acceso de las herramientas se controla directamente mediante esta lista.

Inicio rápido: servidor MCP del sistema de archivos

Este es un ejemplo de trabajo completo mediante el servidor MCP oficial @modelcontextprotocol/server-filesystem :

import { CopilotClient } from "@github/copilot-sdk";

async function main() {
    const client = new CopilotClient();

    // Create session with filesystem MCP server
    const session = await client.createSession({
        mcpServers: {
            filesystem: {
                type: "local",
                command: "npx",
                args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
                tools: ["*"],
            },
        },
    });

    console.log("Session created:", session.sessionId);

    // The model can now use filesystem tools
    const result = await session.sendAndWait({
        prompt: "List the files in the allowed directory",
    });

    console.log("Response:", result?.data?.content);

    await session.disconnect();
    await client.stop();
}

main();

Output:

Session created: 18b3482b-bcba-40ba-9f02-ad2ac949a59a
Response: The allowed directory is `/tmp`, which contains various files
and subdirectories including temporary system files, log files, and
directories for different applications.

Sugerencia

Puede usar cualquier servidor MCP desde el directorio de servidores MCP. Entre las opciones populares se incluyen @modelcontextprotocol/server-github, @modelcontextprotocol/server-sqlitey @modelcontextprotocol/server-puppeteer.

Opciones de configuración

Servidor local/stdio

PropiedadTipoObligatorioDescription
type
"local" o "stdio"NoTipo de servidor (el valor predeterminado es local)
commandstringYesComando para ejecutar
argsstring[]YesArgumentos de comandos
envobjectNoVariables de entorno
cwdstringNoDirectorio de trabajo
toolsstring[]NoHerramientas para habilitar (["*"] para todos, [] para ninguno)
timeoutnumberNoTiempo de espera en milisegundos

Servidor remoto (HTTP/SSE)

PropiedadTipoObligatorioDescription
type
"http" o "sse"YesTipo de servidor
urlstringYesDirección URL del servidor
headersobjectNoEncabezados HTTP (por ejemplo, para la autenticación)
oauthClientIdstringNoIdentificador de cliente no vacío para un cliente de OAuth configurado estáticamente
oauthScopesstring[]NoArray no vacío de tokens de scope válidos según RFC 6749. Requiere oauthClientId; se usa cuando el desafío del servidor omite el ámbito o proporciona un ámbito vacío, antes del mecanismo alternativo de metadatos de recursos protegidos.
oauthPublicClientbooleanNoSi el cliente de OAuth configurado es público y no requiere un secreto de cliente
oauthGrantTypestringNoTipo de concesión de OAuth para el cliente configurado, como client_credentials
toolsstring[]NoHerramientas para habilitar
timeoutnumberNoTiempo de espera en milisegundos

Titularidad de OAuth para servidores remotos

Elija un modelo de propiedad de OAuth para cada intento de autenticación:

  1. Loopback administrado en tiempo de ejecución: Llame a session.mcp.oauth.login sin un URI de redirección. El entorno de ejecución abre un receptor local de callback y se encarga del descubrimiento, PKCE, la validación de estado, el intercambio de tokens, la persistencia, la actualización y la reconexión.
  2. callback hospedado administrado por el entorno de ejecución: llame a session.mcp.oauth.login con un URI de redirección HTTPS público de confianza. El anfitrión recibe la callback, pero el tiempo de ejecución sigue controlando el protocolo OAuth y las credenciales.
  3. OAuth administrado por host: use el controlador de solicitudes de autenticación MCP del SDK y devuelva un token de acceso adquirido por host. El host posee autorización y refresh.

No registre un controlador de OAuth administrado por host para un intento de autenticación que use un callback hospedado administrado en tiempo de ejecución. Espere hasta que el servidor remoto entre en el needs-auth estado y llame al método generado session.rpc.mcp.oauth.login directamente con el nombre del servidor y el URI de devolución de llamada:

{
    "serverName": "remote-mcp",
    "redirectUri": "https://agent.example.com/oauth/callback"
}

El cliente OAuth estático, CIMD o registrado dinámicamente debe anunciar ese URI exacto. El URI debe usar HTTPS y no debe contener una cadena de consulta ni un fragmento. Cuando se requiere la interacción del explorador, el resultado contiene authorizationUrl y authorizationId. Abra authorizationUrl en el explorador del usuario y conserve authorizationId con la sesión de destino.

Después de que el servidor de autorización redirija al punto de conexión, llame al método generado session.rpc.mcp.oauth.complete :

{
    "authorizationId": "<opaque-state>",
    "callbackUrl": "https://agent.example.com/oauth/callback?code=...&state=..."
}

Construya callbackUrl a partir del origen de redireccionamiento público configurado y la ruta de acceso más la consulta original del callback. No pase una dirección URL de servicio interna ni confíe en los encabezados X-Forwarded-* o Forwarded proporcionados por el cliente. El entorno de ejecución valida el origen, el puerto, la ruta de acceso, el estado y la respuesta de OAuth antes de aceptar la entrega. El intercambio de tokens, la persistencia y la reconexión de MCP, y luego la continuación, se producen de forma asincrónica.

Devolver un token de acceso rechazado al entorno de ejecución

Para una solicitud de OAuth de host con reason: "refresh" y runtimeRefreshSupported: true, el controlador puede devolver { "kind": "runtimeRefresh" } en lugar de adquirir un token de acceso de reemplazo. El entorno de ejecución realiza la renovación no interactiva mediante su autorización concedida guardada existente dentro de la operación de autorización original. No inicia un nuevo flujo de consentimiento ni llama a la RPC de actualización independiente authenticationStateChanged . El reemplazo conserva la procedencia del grant guardado, por lo que la adopción posterior de tokens almacenados con ámbito sigue estando disponible. Un token proporcionado directamente por un host no está marcado como un token almacenado y no se puede sobrescribir mediante esa ruta de adopción.

Solo devuelve esta respuesta cuando la solicitud pendiente indica que es compatible. Una funcionalidad ausente equivale a false y conserva el contrato heredado de token/cancelación. Si un controlador devuelve la transferencia de una solicitud sin la capacidad, el SDK envía cancelled en su lugar, por lo que la solicitud pendiente no permanece abierta. Un token proporcionado tiene prioridad sobre la transferencia y una cancelación sigue siendo una cancelación.

SDKCapacidadResultado de la transferencia
Node.jsrequest.runtimeRefreshSupported{ kind: "runtimeRefresh" }
Pythonrequest["runtimeRefreshSupported"]{"kind": "runtimeRefresh"}
Go
MCPAuthRuntimeRefreshHandler argumento de capacidadMCPAuthResultRuntimeRefresh()
.NETMcpAuthContext.RuntimeRefreshSupportedMcpAuthResult.RefreshInRuntime()
Java
McpAuthHandler.handleWithRuntimeRefresh argumento de capacidadMcpAuthResponse.runtimeRefresh()
ÓxidoMcpAuthHandler::handle_with_runtime_refreshMcpAuthResponse::RuntimeRefresh

La aceptación de la confirmación reconoce la transferencia, no la actualización, la reconexión o la finalización de la herramienta. Para una transferencia aceptada, mcp.oauth_completed se emite una vez, cuando la reserva de autorización original alcanza su resultado terminal. Su outcome usa solo los valores existentes: token cuando la recuperación se realizó correctamente y cancelled cuando se canceló o produjo un error. El evento persistente mcp.oauth_recovery_completed lleva el mismo requestId y serverName y distingue el resultado final, incluida la reconexión: succeeded, cancelled o failed. Las versiones del SDK anteriores a este evento lo reciben como un tipo de evento desconocido.

Hasta que el tiempo de ejecución acepte una runtimeRefresh respuesta, las respuestas existentes mantienen su significado anterior. Una respuesta de host { kind: "cancelled" } rechaza la solicitud; para una refresh solicitud, el tiempo de ejecución puede solicitar la reautorización. Si no responde ningún host, el tiempo de ejecución vuelve a su gestión local habitual de OAuth, incluidas las credenciales almacenadas en caché, y no emite ningún evento mcp.oauth_recovery_completed. Este cambio no vuelve a clasificar una respuesta de host cancelled como Stop. La invocación original solo se conserva mediante una transferencia aceptada runtimeRefresh.

Después de la aceptación, la invocación original puede reintentar después de la instalación de credenciales y volver a conectarse, superando las barreras existentes de sesión, configuración, directiva y permisos. Detener el turno principal o finalizar la sesión cancela la reserva de autorización original; la invocación detenida no puede reintentar ni publicar un resultado más adelante. Un intercambio de concesión rotatoria ya emitido puede terminar de persistir su reemplazo después de la cancelación, pero no puede instalar credenciales obsoletas, volver a conectarse o reanudar la invocación cancelada.

Una autorización guardada no disponible o una actualización con errores finaliza la invocación original sin solicitar la reautorización interactiva. Una reconexión con error también finaliza la invocación; la obtención correcta de un token no es un resultado de herramienta correcto.

Las invocaciones simultáneas se unen al mismo intento de autorización en curso y reciben su resultado terminal. Un servidor conectado, un token de acceso retenido o un intento posterior correcto no es prueba de que su intento haya tenido éxito. Cada invocación superviviente sigue comprobando su propio catálogo y el permiso de la herramienta antes de reintentar; el fallo combinado no inicia otra autorización interactiva.

Los tiempos límite HTTP de OAuth se aplican a solicitudes individuales, no a la transferencia completa ni a la consolidación del almacenamiento de concesiones. La cancelación puede completarse antes de que se liquide un intercambio emitido, y la liberación de la sesión espera a que finalicen los procesos de liquidación supervisados. No hay ninguna fecha límite de liquidación global, por lo que los hosts no deben tratar la cancelación, la aceptación de la transferencia o un tiempo de espera HTTP como prueba de que ha finalizado todo el trabajo de almacenamiento.

Diagnósticos de MCP de la sesión

Active diagnostics: { sources: { mcp: { level: "debug" } } } cuando cree o reanude una sesión para participar en los diagnósticos de MCP. Cada origen usa de forma predeterminada off. Los niveles habilitados son error, warning, info, debugy trace. Esta configuración está separada del logLevel de nivel de proceso del cliente.

Advertencia

Las entradas de diagnóstico pueden contener contenido proporcionado por el usuario o por el servidor en cada nivel habilitado: el nivel warning y superiores pueden incluir stderr del servidor, mientras que debug y trace también pueden incluir cargas útiles de MCP, argumentos de herramientas y rutas de acceso. Trate cada entrada como confidencial. No cargue automáticamente entradas como telemetría ni expórtelas sin una acción deliberada del host.

La API generada session.rpc.diagnostics permite a los hosts configurar y leer diagnósticos en memoria con ámbito de sesión y limitados. MCP es la primera y actualmente la única fuente admitida. Selecciónelo explícitamente con sources: ["mcp"] durante la lectura; la lectura no habilita la captura. Utilice un bucle de lectura que se pueda detener por superficie de salida y conserve su cursor. Un bucle de lectura posee su cursor y presentación; el entorno de ejecución posee captura, filtrado, retención, expiración del cursor y reactivaciones.

import { approveAll, CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const stop = new AbortController();
const appendLine = (line: string) => console.log(line);

await client.start();
const session = await client.createSession({
    onPermissionRequest: approveAll,
    diagnostics: { sources: { mcp: { level: "debug" } } },
});

try {
    let cursor: string | undefined;
    while (!stop.signal.aborted) {
        const page = await session.rpc.diagnostics.read({
            sources: ["mcp"],
            cursor,
            max: 100,
            waitMs: 30_000,
        });
        if (page.cursorStatus === "expired") {
            appendLine("MCP diagnostic entries were dropped.");
        }
        for (const entry of page.entries) {
            const detail = entry.details.data ? ` ${entry.details.data}` : "";
            appendLine(
                `${entry.timestamp} [${entry.level}] [${entry.source}:${entry.details.serverName}] ${entry.message}${detail}`,
            );
        }
        cursor = page.cursor;
    }
} finally {
    await session.disconnect();
    await client.stop();
}

La señal de anulación detiene el bucle después de que se complete su lectura limitada actual; no se pasa a la llamada RPC. Al deshabilitar la captura, se desbloquea una lectura pendiente.

El inicio de MCP es perezoso: habilitar o leer diagnósticos no inicia un servidor. Configure mcpServers en la creación de la sesión y, a continuación, use la sesión normalmente o llame a session.rpc.mcp.startServer({ serverName }) para un servidor instalado para solucionar problemas de inicialización sin realizar una solicitud de modelo.

Cada registro tiene source: "mcp", marca de tiempo, gravedad, mensaje y opcional agentId para agentes no raíz. Su campo tipado details contiene el ciclo de vida, el protocolo, HTTP o la categoría stderr, el nombre del servidor, un nuevo connectionId para cada intento de conexión y la dirección del protocolo opcional y los datos de diagnóstico. La retención de MCP se limita a 1024 registros y 4 MiB por sesión. Los registros codificados individuales están limitados a 16 KiB e incluyen truncated cuando se acortan. Lee de forma predeterminada 100 registros, acepta un máximo de 500 y no consume datos de otros lectores. Utilice droppedCount, cuando esté presente en un cursor expirado, para mostrar la pérdida conocida. Cada lectura correcta devuelve un cursor y el estado del cursor, incluidas las lecturas vacías. Mantenga el cursor devuelto incluso cuando no llegue ningún registro. Un cursor está asociado a su selección de origen; empiece sin cursor al cambiar esa selección. Se rechazan los orígenes que faltan, vacíos, duplicados o no admitidos, al igual que los cursores con formato incorrecto y los límites numéricos no válidos. Ni las grabaciones ni la configuración de captura se guardan en el historial de sesiones.

Llame a session.rpc.diagnostics.configure({ sources: { mcp: { level: "off" } } }) para deshabilitar la captura de MCP y borrar su búfer retenido. La operación de configuración actualiza solo los orígenes con nombre explícito y devuelve los niveles de origen efectivos. Se rechaza la configuración de origen vacía o desconocida; agregar otro origen admitido en el futuro no incluirá implícitamente a un llamador existente en él.

Detenga también el bucle de lectura del host; las lecturas, mientras el registro está desactivado, vuelven inmediatamente en lugar de esperar. Una solicitud long poll pendiente despierta cuando se deshabilita el registro. Omitir diagnostics al reanudar una sesión residente conserva su configuración actual; una sesión cargada en frío requiere una nueva aceptación. La habilitación de diagnósticos desde el estado inicial off puede iniciar la captura para una conexión MCP ya activa. Después de deshabilitar los diagnósticos con configure({ sources: { mcp: { level: "off" } } }), volver a habilitarlos puede reanudar la captura para la misma conexión activa y su identificador de conexión existente. Los registros que ya estaban en procesamiento cuando se deshabilitó el diagnóstico se descartan.

El tiempo de ejecución quita las credenciales configuradas y reconocidas estructuralmente de los diagnósticos HTTP antes de que las entradas lleguen a esta API, pero esto no es una garantía de que los secretos arbitrarios proporcionados por el servidor no estén presentes. No expone mapas de encabezados de solicitud o respuesta. Solo los metadatos seleccionados, como Content-Type, Accepty MCP-Protocol-Version, son aptos para la captura, pero sus valores siguen sin ser de confianza y pueden contener contenido confidencial. Se omiten los encabezados de autenticación, las cookies, los identificadores de sesión, los valores de consulta, el userinfo de la URL y los fragmentos. Las rutas de acceso url se conservan para solucionar problemas, por lo que no coloque credenciales en segmentos de ruta de acceso. Las cargas de protocolo y stderr también pueden contener contenido de usuario o secretos arbitrarios proporcionados por el servidor.

Solución de problemas

Herramientas que no se muestran o no se invocan

  1. Comprobación de que el servidor MCP se inicia correctamente

    • Compruebe que el comando y los argumentos son correctos
    • Asegúrese de que el proceso del servidor no se bloquea al iniciarse
    • Busca mensajes de error en stderr
  2. Comprobación de la configuración de la herramienta

    • Asegúrese de que tools está establecido en ["*"] o enumera las herramientas específicas que necesita.
    • Una matriz [] vacía significa que no hay ninguna herramienta habilitada
  3. Comprobación de la conectividad para servidores remotos

    • Asegúrese de que la dirección URL es accesible
    • Comprobación de que los encabezados de autenticación son correctos

Problemas comunes

IssueSolución
"No se encontró el servidor MCP"Comprobación de que la ruta de acceso del comando es correcta y ejecutable
"Conexión rechazada" (HTTP)Compruebe la dirección URL y asegúrese de que el servidor se está ejecutando
Errores de "tiempo de espera"Aumenta el valor de timeout o comprueba el rendimiento del servidor
Las herramientas funcionan pero no son llamadasAsegúrese de que el mensaje requiere claramente la funcionalidad de la herramienta.

Para obtener instrucciones detalladas sobre la depuración, consulte Guía de depuración del servidor MCP.

Consulte también