/** * Copyright (c) 2026, Salesforce, Inc., * All rights reserved. * For full license text, see the LICENSE.txt file */ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { buildConnect, type ConnectDeps } from "../../intent/build-connect.js"; import { CONNECT_INPUT } from "../../schemas/input-schemas.js"; import { runTool } from "../../schemas/tool-adapter.js"; export type SfGqlConnectToolOptions = ConnectDeps; const inputSchema = CONNECT_INPUT.shape; export function registerSfGqlConnectTool( server: McpServer, opts: SfGqlConnectToolOptions = {}, ): void { server.registerTool( "sf_gql_connect", { description: "Connect to a Salesforce org and prime its GraphQL schema cache. With forceRefresh, re-download the schema and coherently clear all caches so subsequent tools see freshly-deployed metadata. Concurrent refreshes coalesce into a single introspection. Returns { org, instanceUrl, refreshed, cached, durationMs, warnings? } — not the standard ToolOutput envelope. If a refresh fails transiently (network/5xx) but a usable cached schema survives, returns refreshed:false with a staleness warning instead of erroring; a 401/403 auth failure during refresh instead errors with `Auth:` (a dead session makes the cached schema unusable — re-authenticate). Error convention (all sf_gql_* tools): on failure the isError text is prefixed with a category — `UserInput:` (fix the request), `Auth:` (re-authenticate the org — e.g. an expired/unauthorized session on connect or introspection), `Schema:` (introspection/cache problem), or `Internal:` (unexpected) — so you can decide whether to fix inputs, re-auth, or retry. A `Schema:` error additionally ends with a retryability token: `[retry=now]` (retry immediately — e.g. a priming-lock timeout, where no live org round-trip occurred) or `[retry=backoff]` (the org was unreachable and an automatic retry already failed — wait with increasing backoff, e.g. 2^n seconds capped around 8s, and retry serially; do not fan out concurrent retries against an org that is already failing, and note some conditions such as an org API rate limit may take longer than a few seconds to clear); ABSENCE of any `[retry=...]` token means the failure is permanent (404, missing/malformed `__schema`, GraphQL errors in the body, or no cached schema) — do not retry, fix the request or re-prime via sf_gql_connect. This token convention applies to every sf_gql_* tool, not just this one. Example error text: `Schema: introspection request failed [retry=backoff]`; extract the disposition with the end-anchored regex ` /\\s\\[retry=(now|backoff)\\]$/` (no match ⇒ permanent).", inputSchema, }, async (args) => runTool(() => buildConnect(args, opts)), ); }