/**
 * How a deployment DECLARES an external tool server and what an elicitation round-trip looks like:
 * `McpServerSpec` (stdio / HTTP / in-process MCP), `A2aServerSpec` (the agent-to-agent peer) and the
 * elicit pair (`McpElicitRequest` / `McpElicitResponse` / `OnElicit`). Named `mcp-server-spec.ts`, not
 * `mcp.ts`: `src/core/mcp.ts` is the CLIENT, and two files a letter apart would be a worse hazard than
 * a longer name. Layer 0 vocabulary; `types.ts` re-exports every name below.
 */
import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js";
import type { ToolFamily, ToolPathTarget, ToolRenderHints, ToolRuleFace } from "./tool-face.js";
/** Definition of an MCP server to connect to for the duration of one task, then discard. */
export interface McpServerSpec {
    /** Stable name; tool names are namespaced as `<name>__<tool>` to avoid collisions. */
    name: string;
    /**
     * Where this declaration CAME FROM, in the declaring side's own words (a shell's `plugin` / `user` /
     * `project` / `local` config tiers, or anything else the deployment finds useful). Core reads
     * nothing off it: it is echoed verbatim (single-line, length-bounded) onto the wiring manifest's
     * per-server read face (`WiringManifest.mcp[].source`) so a consumer can group servers by their
     * declaring tier without keeping a side table keyed on names. Optional; absent stays absent.
     */
    source?: string;
    transport: {
        kind: "stdio";
        command: string;
        args?: string[];
        env?: Record<string, string>;
    } | {
        kind: "http";
        url: string;
        /** Static headers sent on every request (e.g. an auth bearer for the MCP server itself). */
        headers?: Record<string, string>;
        /**
         * Per-task **end-user principal** header (design/62). When set, the Runner injects the running task's
         * authenticated {@link TaskSpec.principal} as this header (e.g. `"X-Agent-Principal"`) on every call to
         * this server's tools, so the MCP server can enforce per-user RBAC. Absent {@link TaskSpec.principal}
         * ⇒ the header is **not** sent (the MCP server must default to deny/public, never admin). Overrides any
         * same-named static `headers` entry. The principal is Runner-held and the model/worker can neither read
         * nor set it (it is not a tool argument) — see {@link TaskSpec.principal}.
         */
        principalHeader?: string;
    };
    /** Optional allowlist of tool names to expose (others are dropped). ORTHOGONAL to
     *  {@link contentOrigin} and usefully paired with it (design/378 §2): the class declaration follows
     *  the server's roster, so a high-assurance deployment that wants a CLOSED tool set writes both —
     *  a tool a later refresh adds then lands outside this list and is simply not mounted. Existing
     *  semantics, no new mechanism; the refresh receipt still names every added tool either way. */
    allowTools?: string[];
    /**
     * design/99 §E23 — opt in to INBOUND elicitation for THIS server: when `true` AND a {@link RunnerDeps.onElicit}
     * seam is wired, core advertises the `elicitation` capability to this server and registers a handler, so the
     * server may send an `elicitation/create` request to ask the END USER for input mid-tool-call. **Default OFF
     * (fail-closed)**: never advertise unless explicitly wired, so a untrusted/over-eager server cannot pull a human
     * into the loop. v1 is LIVE-ONLY — `onElicit` answers synchronously on the open connection (no durable
     * suspend; a durable/cross-replica elicitation needs the deferred E22 longer-lived connection).
     */
    elicitation?: boolean;
    /**
     * Caller-side per-tool safety-axis overrides, keyed by the server's REMOTE (un-namespaced) tool name. The
     * CALLER is the trust root: unlike a server's self-declared annotations (which may only TIGHTEN), a caller
     * override is AUTHORITATIVE and may LOWER an effect (vouch a tool is `read`/`idempotent`) as well as raise it
     * (`egress` / irreversible). This is the ONLY trusted way to drop an MCP tool below the fail-closed `write`
     * default (design F). Folds over the server hints in prepare-task (caller > server hint > fail-closed write).
     *
     * A DIFFERENT AXIS from {@link contentOrigin}: this one is about what a call DOES (repeat-safety,
     * blast radius, reversibility — it feeds the approval gate); the content class is about what a call
     * BRINGS BACK (memory-write governance, no gate/policy/roster effect). Neither implies the other —
     * a read-only tool can return third-party text, and a deployment's own writer brings back nothing
     * external — so vouching on one axis never quietly vouches on the other.
     */
    toolAxes?: Record<string, {
        effect?: ToolEffect;
        egress?: boolean;
        irreversibility?: "always" | "never";
    }>;
    /**
     * design/388 §1.1 / §2.7 — the OPTIONAL per-tool FACE overlay for this server's tools (keyed by the server's
     * RAW tool name, like {@link allowTools} / {@link toolAxes}): a deployment lets an MCP tool enter a specialised
     * approval card, be confirmed by path, carry a display name / summary, or narrow its rule vocabulary. TRUSTED
     * (the deployment writes it), but validated against the MATERIALIZED schema at every listing (first mount and
     * every refresh): a `pathTarget.param` that is not a top-level property, an `approvalCard` whose keys the schema
     * lacks, a `ruleFace` naming a non-scalar key ⇒ the tool mounts WITHOUT the overlay and the leg announces
     * `config.tool_face_invalid` once; a key naming a tool the listing does not carry announces
     * `config.tool_face_undeclared` once. Applied whole or not at all.
     */
    toolFaces?: Record<string, {
        family?: ToolFamily;
        pathTarget?: ToolPathTarget;
        renderHints?: ToolRenderHints;
        ruleFace?: ToolRuleFace;
    }>;
    /**
     * design/378 — declare {@link ToolSpec.contentOrigin} on behalf of THIS SERVER'S ENTIRE TOOL SET
     * (tools a mid-task refresh adds included), with the same authority and the same responsibility a
     * directly-mounted host tool's own declaration carries.
     *
     * WHY THE SEAT EXISTS. Without it the class keys on the MOUNT SHAPE rather than on lineage: a tool
     * the deployment wrote and runs itself is structurally `"external"` the moment it arrives over the
     * MCP protocol namespace, so every call marks the session's memory externally exposed. The
     * per-name channels cannot express the fact either — {@link import("./memory.js").MemorySpecInput.trustedTools}
     * is a per-REQUEST allowlist keyed on the MINTED name (the host would have to predict the charset
     * normalization) whose own definition is "the exception channel for UNDECLARED tools", and it says
     * nothing about tools the server adds later.
     *
     * THIS IS A TRUST DECLARATION, not a routing hint. Use it only for servers inside the deployment's
     * trust boundary — a process, socket or service the deployment itself runs. Declaring a THIRD-PARTY
     * server means treating its output as content the deployment wrote: the class names are
     * BOUNDARY-relative, never topological, so neither the transport kind nor the address is evidence
     * of lineage (a stdio child can be an untrusted package; a loopback URL can be your own service) and
     * core deliberately does not gate on either. The declaration covers THE PEER THIS ENTRY CONNECTS TO
     * — authenticating that peer (socket permissions, credentials) is the host's mounting duty.
     *
     * SEMANTICS. `"local"` ⇒ invocations no longer mark this session's memory; `"execution"` ⇒ the same,
     * except that {@link import("./memory.js").MemorySpecInput.execIsExternalContent} can still upgrade
     * the class for a strict deployment (which is why this seat takes the three-value vocabulary and not
     * a single "mine" flag — an execution-shaped tool mounted over MCP must stay inside that knob's
     * reach); `"external"` is an explicit PIN, and pins are not no-ops — a declaration beats the
     * `trustedTools` allowlist, so writing it forecloses the per-name exemption for this server's tools.
     * ABSENT ⇒ the pre-378 behavior byte for byte: the protocol namespace classifies the tools
     * `"external"` (fail-closed). A value outside the vocabulary is refused at the preparation door
     * (`config.mcp_content_class`), never folded to a class.
     *
     * COVERAGE, stated honestly: the class rides this server's own mounted tools. The cross-server
     * resource faces (ListMcpResourcesTool / ReadMcpResourceTool / ReadMcpResourceDirTool) aggregate
     * over every connected server in one call, so they stay `"external"` and still mark — over-marking,
     * the safe direction. A delegated child's pool is a separate static declaration surface
     * ({@link ToolSpec.agentToolPool} entries carry their own `contentOrigin`): a deployment handing
     * this server's tools to children mirrors the value there, and not mirroring it over-marks.
     *
     * TRUST SOURCE — a DEPLOYMENT-plane key. It redefines where the trust boundary runs, which puts it
     * on the same authority plane as {@link RunnerDeps} wiring, not on the request plane. Core sees one
     * `TaskSpec` and cannot tell a deployment-baseline entry from one a request supplied, so any
     * assembly layer that accepts REQUEST-side MCP entries must reject or strip this key from them:
     * "allowed to mount a server" is not "allowed to redefine the deployment's trust boundary", and a
     * caller-supplied `"local"` would otherwise be self-authorization around the session mark. A
     * single-tenant superuser surface (a host reading its own `--mcp-config` file) IS the deployment
     * plane and needs no such gate.
     */
    contentOrigin?: ToolContentOrigin;
}
/**
 * Definition of one A2A (agent-to-agent protocol) PEER to talk to for the duration of one task.
 *
 * The peer is a remote AGENT, not a data source: it acts on its own side. That single fact sets the
 * defaults — every skill this peer advertises mounts with `egress: true` and `effect: "write"` (ruled
 * 2026-08-03), so it registers the approval gate and is never auto-allowed on a no-policy deployment,
 * and its replies reach the model inside an untrusted-data fence. {@link toolAxes} is the only trusted
 * way down from those defaults (design F: the caller is the trust root).
 *
 * Skills mount as `a2a__<peer>__<skill>` (the protocol table's second namespace).
 */
export interface A2aServerSpec {
    /** Stable local name for this peer; it becomes the namespace segment of every mounted tool name. */
    name: string;
    /** The peer's service URL. Doubles as the origin the well-known agent-card paths resolve against, and
     *  as the JSON-RPC endpoint when the card does not name a different one. */
    url: string;
    /** Explicit agent-card location, when the peer does not publish at a well-known path. Set ⇒ it is used
     *  ALONE (no well-known probing behind the operator's back). */
    cardUrl?: string;
    /** Static headers sent on every request to this peer (e.g. an auth bearer). */
    headers?: Record<string, string>;
    /**
     * Per-task **end-user principal** header (design/62), same contract as the MCP side: when set, the
     * Runner injects the running task's authenticated {@link TaskSpec.principal} under this header name on
     * every call to this peer, so the peer can enforce per-user authorization. Absent principal ⇒ the
     * header is not sent (the peer must then default to deny/public, never admin). Overrides any same-named
     * static entry in {@link headers}. The principal is Runner-held: the model can neither read nor set it.
     */
    principalHeader?: string;
    /** Optional allowlist of skill ids to expose (others are not mounted). */
    allowSkills?: string[];
    /**
     * Caller-side per-skill safety-axis overrides, keyed by the peer's REMOTE skill id. The CALLER is the
     * trust root, so this may LOWER the fail-closed default (`egress:true` + `effect:"write"`) as well as
     * raise it — e.g. `{ egress: false, effect: "read" }` vouches that a skill only reads. Note that
     * lowering `effect` WITHOUT clearing `egress` is a contradiction prepare-task refuses by design (an
     * external write must be repeat-unsafe).
     */
    toolAxes?: Record<string, {
        effect?: ToolEffect;
        egress?: boolean;
        irreversibility?: "always" | "never";
    }>;
}
/**
 * design/99 §E23 — an INBOUND MCP elicitation request (a connected server asking the END USER for input
 * mid-tool-call). Handed to the deployment's {@link RunnerDeps.onElicit} seam. **UNTRUSTED**: `message` /
 * `requestedSchema` / `url` are SERVER-controlled — core never interprets `requestedSchema`; a consumer that
 * shows `message` to a human MUST fence it (`delimitUntrusted`).
 */
export interface McpElicitRequest {
    /** The {@link McpServerSpec.name} of the server that issued the request. */
    server: string;
    /** The server's human-facing prompt (UNTRUSTED — fence before display). */
    message: string;
    /** Form mode: the server's requested input schema (a flat object of scalars). OPAQUE to core. */
    requestedSchema?: unknown;
    /**
     * URL mode: a server-controlled URL the user is asked to visit (UNTRUSTED — a phishing/social-engineering
     * surface; a consumer MUST scrutinize/fence it before showing it). **Inactive**: core advertises FORM mode
     * only, so the SDK rejects url-mode requests before this seam — the field is never populated today.
     *
     * Where url mode is heading (MCP revision `2026-07-28`), because the earlier note here ("reserved for a
     * future url-mode opt-in") pointed at machinery that no longer exists: the revision REMOVES the
     * `2025-11-25` url-mode correlator (`elicitationId`) and the `notifications/elicitation/complete`
     * notification that went with it. A url interaction is instead carried by the revision's multi-round-trip
     * request flow — the server answers with an input-required result, the client RETRIES the original
     * request, and the server correlates across retries through its OWN opaque request state rather than a
     * client-visible id. The one thing both shapes agree on is the server-supplied URL itself, which is what
     * this field holds. So the field stays; anything that would have hung off the removed correlator must not
     * be added here without re-reading the protocol revision core actually speaks.
     */
    url?: string;
    /** The running task's authenticated end-user (design/62), if any — for routing the prompt to the right human. */
    principal?: string;
}
/** design/99 §E23 — the deployment's answer to an {@link McpElicitRequest} (returned to the MCP server). */
export interface McpElicitResponse {
    action: "accept" | "decline" | "cancel";
    /** Submitted values (accept only); core passes them through opaquely, never validated against the schema. */
    content?: Record<string, string | number | boolean | string[]>;
}
/**
 * design/99 §E23 — the LIVE-ONLY inbound-elicitation seam. A deployment provides it (e.g. the sema shell
 * prompts the user at the terminal) and returns the answer SYNCHRONOUSLY; core replies to the server on the
 * still-open connection. Absent ⇒ no server is advertised the elicitation capability (fail-closed). Not a
 * durable suspend — a crash/replica-change loses an in-flight elicitation (acceptable for an interactive shell).
 *
 * 🔴 THROTTLING IS THE DEPLOYMENT'S JOB: once a server is opted in, it may issue elicitations at any frequency
 * (one per tool call, or many) — core imposes NO rate/count limit (an elicitation is not a tool call and does
 * not ride the policy gate). `onElicit` is the choke point: throttle, aggregate, or `decline`/`cancel` an
 * over-eager or untrusted server here (the request's `AbortSignal` is forwarded so a deadline can cancel it).
 */
export type OnElicit = (req: McpElicitRequest, signal?: AbortSignal) => Promise<McpElicitResponse>;
