/** * MCP prompts (#371) — the guided workflows, as text. * * A prompt is not a tool. `prompts/get` returns messages that a client drops * into the conversation as if the human had typed them, so the directive voice * below is correct: the human is asking. Tool descriptions, by contrast, * describe a capability to a model that has not asked for anything, and stay * declarative. * * A prompt's arguments are interpolated straight into that user-role message. * The threat model assumes a human typed them, which is what picking a slash * command means — but the assumption is worth stating in a file whose opening * argument is about what may and may not occupy a user-role message. Nothing * here reaches an API, so a hostile argument is text in a message the human * can see, not a call they did not make. * * Three rules the text below follows, each with a reason: * * 1. **Never fetch on the client's behalf.** These builders are pure string * functions and make no API call. `prompts/get` is synchronous, has no * elicitation channel and no `_actions` affordance, so a prompt that * pre-fetched would turn a slash command into a multi-second stall that * can fail with an error the human cannot act on. Worse, embedding * container or build output in the returned message would place * attacker-influenceable text in a *user*-role message, outside the * `asUntrustedLogs` boundary that the tool layer puts around exactly that * text (FINDINGS #4). Naming the tool and letting the model call it keeps * the log on the one path that frames it as data. * * 2. **Name only tools that exist.** Read-only mode (#303) does not register * mutating tools, and consolidation puts two pure reads under destructive * tools: `env_vars` list and `deployment` get. So a prompt that names * `env_vars` is naming a tool that is absent from a read-only server. The * builders take a {@link PromptBuildContext} with `has()` and drop any step * whose tool is missing; a prompt whose *whole* workflow is missing is not * registered at all (see `requires` at the registration site). Structural, * so it cannot drift the way a hand-maintained list would. * * 3. **Fleet mode names the instance in the text.** The `instance` argument is * routing for tools, but a prompt does not route anything — it produces * words. So the resolved instance name is woven into the sentences and * into the tool calls the model is told to make, which is the only way the * downstream calls land on the instance the human picked. */ import type { ToolName } from './mcp-server.js'; export interface PromptBuildContext { /** * Whether a tool is registered on THIS server. Read-only mode omits every * mutating tool, so a builder must ask before naming one. */ has(tool: ToolName): boolean; /** * Fleet mode: the resolved instance this prompt targets. `null` when a * single instance is configured, in which case the text never mentions * instances at all — same bargain as the tools, where single-instance * configs pay nothing for a feature they do not have. */ instance: string | null; /** The other configured instance names, fleet mode only. Never includes {@link instance}. */ otherInstances: string[]; } export declare function troubleshootApplicationPrompt(query: string, ctx: PromptBuildContext): string; export declare function explainFailedDeployPrompt(deploymentUuid: string, ctx: PromptBuildContext): string; export declare function estateHealthPrompt(ctx: PromptBuildContext): string;