/** * Copyright (c) 2026, Salesforce, Inc., * All rights reserved. * For full license text, see the LICENSE.txt file */ import { z } from "zod"; /** * Some MCP clients/models JSON-stringify complex tool arguments (e.g. send * `"25"` for a number or `'{"x":1}'` for an object). This coerces such a * string back to its parsed value so the real value validates — lossless, * and scoped to strings that LOOK like JSON (object/array/number) so `$var` * placeholders and enum strings (e.g. scope "MINE") are left untouched. * Same "tolerate predictable client encoding quirks" philosophy as the * detailOrderBy array-collapse shim. */ export declare const coerceJsonArg: (v: unknown) => unknown; /** Wrap a schema so a JSON-stringified value is coerced before validation. */ export declare const jsonCoercible: (schema: z.ZodTypeAny) => z.ZodEffects; /** * Wrap an enum (or any string schema) so Unicode control/format chars are * STRIPPED from a string value before validation (W-23336443). Motivation: a * `z.enum` rejection is reflected VERBATIM by the MCP SDK's input validation, * which runs UPSTREAM of `runTool` — so the adapter's `neutralizeControlChars` * never executes, and a poisoned value like `"describe_object‮"` reaches * the host raw inside `received '…'`. `JSON.stringify` (which the SDK uses) * escapes only C0, so DEL and the entire Cf class (bidi overrides, zero-width) * survive. Stripping here closes that channel two ways: a control-char-poisoned * but otherwise-valid value strips to the valid enum member (accepted, no * message), and a genuinely-invalid value rejects with a message free of raw * control chars. * * This upstream path also strips U+2028/U+2029 (via {@link stripLineSeparators}), * matching what every envelope sink does in `tool-adapter.ts`: those separators * are NOT Cc/Cf so `stripControlChars` correctly ignores them, but left raw in * host-visible text they trip a Claude.AI 408 (MCP TS SDK #2155) — and this * rejection message reaches the host BEFORE the envelope's own line-separator * strip can run, so it must strip them itself. * * Why `z.preprocess` and not `.refine`: preprocess can TRANSFORM (strip) the * value, and — verified against the SDK's zod-to-json-schema converter — the * wrapper PRESERVES the published JSON-Schema `enum` and `description`, so the * advertised allowed-value list the LLM sees is unchanged. `.refine` can only * reject, not strip. * * CAVEAT: applying this to a `z.discriminatedUnion` discriminator member is * pointless, though not harmful. It is NOT harmful because zod's discriminator- * map builder recurses through a `z.preprocess` wrapper (`getDiscriminator` * reads `ZodEffects.innerType()`), so construction does NOT throw and clean * values still route correctly (verified against zod 3.25.76 on AGGREGATE_INPUT). * It is POINTLESS because discrimination reads the RAW `ctx.data[discriminator]` * to pick a branch BEFORE that branch's preprocess ever runs — so the strip * cannot influence branch selection. A discriminator that matches no branch * raises `invalid_union_discriminator`, whose issue lists only the EXPECTED * options and does NOT echo the received value — so, unlike a plain * `invalid_enum_value`, there is no verbatim-reflection channel there to close. * The aggregate `function` discriminators are therefore left un-wrapped per * W-23336443; only plain enums (invalid_enum_value DOES echo `received`) need it. */ export declare const enumStripControlChars: (schema: T) => z.ZodEffects; /** A string that looks like a JSON object/array literal — used so the advertised * schema accepts a stringified object/array; coerceJsonArg then parses it. A * `{`/`[`-prefixed but invalid-JSON string is accepted as a literal (rare; the * model reliably sends valid JSON) rather than erroring. */ export declare const jsonLiteralString: () => z.ZodString; /** A string of digits — a stringified positive integer for `first`. */ export declare const intLiteralString: () => z.ZodString; /** A JSON-quoted string literal, e.g. "\"$first\"" or "\"25\"" — some models * double-encode args. coerceJsonArg unwraps it before validation. */ export declare const quotedString: () => z.ZodString; /** * Zod string validator that enforces the GraphQL Name production. Returned * schema is `.describe()`-tagged with the supplied description so it appears * in the MCP tool's advertised JSON Schema. */ export declare const graphqlName: (description: string) => z.ZodString; /** * Zod validator for a dotted field path (`Id`, `Owner.Name`, …). Each * `.`-separated segment must be a valid GraphQL Name. Applied to every * caller-supplied field-selection input (`returnFields`, `fields`, * `parentFields`, child-relationship `fields`) so a selection-set breakout is * rejected at the MCP boundary (W-22735537); the builders carry the matching * `assertDottedGraphqlName` guard for direct (CLI / eval) callers. */ export declare const dottedGraphqlName: (description: string) => z.ZodString; export declare const scopeArg: (description: string) => z.ZodString; export declare const orgAlias: (description: string) => z.ZodString; /** * `_OrderBy` shape. A FACTORY (not a shared instance): each call returns * a fresh schema so the MCP SDK's zod-to-json-schema converter INLINES it at every * use site instead of collapsing reuse into cross-`$ref`s (which intermittently * dropped union branches in the advertised schema). */ export declare const orderByObject: () => z.ZodRecord; /** * A bare top-level `$varName` string standing in for an entire `filter` / * `orderBy` / `first` argument. A FACTORY (not a shared instance) so the advertised * JSON Schema inlines it at every use site rather than emitting cross-`$ref`s. */ export declare const varPlaceholder: () => z.ZodString; /** * Build a `childRelationships[]` element schema. The `orderBy` schema is a * parameter because tools differ on whether they advertise the array shape * (`sf_gql_list`: union; `sf_gql_detail`: singleton with array-collapse * preprocess). Everything else — `relationshipName`, `fields`, `first`, * `filter` — is identical across callers. * * `relationshipName` flows into a rendered field-path position in the * resulting query, so it carries the same GraphQL Name constraint as * top-level `object` — same failure mode if it's invalid. */ export declare const childRelationshipSchema: (orderBy: z.ZodTypeAny) => z.ZodObject<{ relationshipName: z.ZodString; fields: z.ZodArray; first: z.ZodOptional>; filter: z.ZodOptional>; orderBy: z.ZodOptional>; }, "strip", z.ZodTypeAny, { relationshipName: string; fields: string[]; filter?: any; orderBy?: any; first?: any; }, { relationshipName: string; fields: string[]; filter?: unknown; orderBy?: unknown; first?: unknown; }>;