@acruxcoreai/mcp-server 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +3 -2
- package/dist/bin.js +303 -11
- package/dist/bin.js.map +1 -1
- package/dist/bin.mjs +303 -11
- package/dist/bin.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +303 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +303 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/errors.ts","../src/client.ts","../src/format.ts","../src/registry-prompts.ts","../src/resources.ts","../src/toolsets/catalog.ts","../src/refs.ts","../src/toolsets/types.ts","../src/toolsets/evaluations.ts","../src/toolsets/gateway.ts","../src/toolsets/prompts.ts","../src/toolsets/traces.ts","../src/toolsets/index.ts","../src/config.ts"],"sourcesContent":["export { createAcruxCoreMcpServer, SERVER_VERSION, type BuiltServer } from './server';\nexport {\n resolveConfig,\n parseToolsets,\n ALL_TOOLSETS,\n DEFAULT_BASE_URL,\n DEFAULT_PROMPT_ALIAS,\n DEFAULT_MAX_TEXT_BYTES,\n type McpServerConfig,\n type Toolset,\n type ConfigSources,\n} from './config';\nexport { AcruxCoreClient, normalizeBaseUrl, type RequestOptions, type RawResponse } from './client';\nexport { AcruxCoreApiError, McpConfigError } from './errors';\nexport { ALL_TOOLS, selectTools, type AnyToolDefinition, type ToolContext } from './toolsets';\nexport { truncateText, okResult, errorResult, listSummary, type ToolResult } from './format';\nexport { isUuid, resolvePromptRef, resolveToolRef, resolvePromptIdAndName } from './refs';\nexport { toPromptMessages } from './registry-prompts';\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\nimport { errorResult } from './format';\nimport { registerRegistryPrompts } from './registry-prompts';\nimport { registerResources } from './resources';\nimport { selectTools } from './toolsets';\n\n/** Version reported to clients in `initialize`. Kept in step with package.json. */\nexport const SERVER_VERSION = '0.1.0';\n\n/** What the caller gets back, so a host can inspect what was registered. */\nexport interface BuiltServer {\n /** The configured MCP server, not yet connected to a transport. */\n server: McpServer;\n /** REST client the tools use. */\n client: AcruxCoreClient;\n /** Names of the tools that were registered, in listing order. */\n toolNames: string[];\n}\n\n/**\n * Builds the `instructions` string sent to clients on `initialize`.\n *\n * Worth writing carefully: it is the only place to explain the registry's *model* —\n * prompt, version, alias — and a client that misunderstands that will commit versions\n * and then wonder why nothing changed in production.\n *\n * It is built from the tools actually registered, because the model reads it as a list\n * of things it can do: naming `promote_prompt_alias` to a read-only client sends it\n * looking for a tool that is not there.\n *\n * @param toolNames - Names of the tools this server registered.\n * @param readOnly - Whether mutating tools were removed from the listing.\n * @returns The instructions text.\n */\nfunction buildInstructions(toolNames: ReadonlySet<string>, readOnly: boolean): string {\n const parts = [\n `AcruxCore is an LLM-ops platform: a prompt registry, a versioned tool catalog, an AI gateway, tracing, and evaluation.\n\nThree ideas explain almost every tool here:\n- A **prompt** is a named container. It holds no messages itself.\n- A **version** is an immutable commit of that prompt's messages. Version numbers are sequential.\n- An **alias** (\"production\", \"staging\", anything else) is a moving pointer at one version.`,\n ];\n\n if (toolNames.has('promote_prompt_alias')) {\n parts.push(\n 'Committing a version never moves an alias — promote_prompt_alias is what ships a change, and promoting an earlier version is how a rollback happens.',\n );\n }\n if (readOnly) {\n parts.push(\n 'This connection is read-only: it can list, read, render and diff, but it cannot create, commit, promote, run or change anything.',\n );\n }\n parts.push(\n 'Registry prompts are also exposed through MCP\\'s prompts primitive, so they can be used directly as templates. Tools that take a prompt or a catalog tool accept a name or a UUID.',\n );\n return parts.join('\\n\\n');\n}\n\n/**\n * Builds a fully configured AcruxCore MCP server.\n *\n * Transport-agnostic on purpose: the stdio binary and the API's hosted HTTP endpoint\n * both call this and then connect whatever transport they own. Adding a tool once makes\n * it appear on both.\n *\n * @param config - Resolved configuration, including the API key every call will carry.\n * @returns The server, its REST client, and the registered tool names.\n */\nexport function createAcruxCoreMcpServer(config: McpServerConfig): BuiltServer {\n const client = new AcruxCoreClient({\n baseUrl: config.baseUrl,\n apiKey: config.apiKey,\n timeoutMs: config.timeoutMs,\n userAgent: `acruxcore-mcp-server/${SERVER_VERSION}`,\n });\n\n const tools = selectTools(config);\n const server = new McpServer(\n { name: 'acruxcore', title: 'AcruxCore', version: SERVER_VERSION },\n {\n instructions: buildInstructions(\n new Set(tools.map((tool) => tool.name)),\n config.readOnly,\n ),\n },\n );\n\n for (const tool of tools) {\n // A tool with no arguments registers no input schema at all. The SDK validates a\n // declared schema with `z.object(shape).parse(params.arguments)`, and `arguments` is\n // optional in the protocol — so declaring an empty schema would make\n // `{\"name\":\"list_models\"}`, a perfectly legal call, fail validation. With no schema\n // the SDK skips validation entirely and the call goes through.\n const inputSchema =\n Object.keys(tool.inputSchema).length > 0 ? tool.inputSchema : undefined;\n\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n inputSchema,\n annotations: {\n title: tool.title,\n readOnlyHint: tool.readOnlyHint,\n destructiveHint: tool.destructiveHint ?? false,\n },\n },\n async (args: unknown) => {\n try {\n return await tool.handler(args, { client, config });\n } catch (error) {\n // Every failure is reported in-band rather than thrown. A thrown error becomes\n // a JSON-RPC error the model never sees, so it retries the identical call;\n // an isError result puts the API's own code and message in front of it.\n return errorResult(error, config.maxTextBytes);\n }\n },\n );\n }\n\n registerRegistryPrompts(server, client, config);\n registerResources(server, client, config);\n\n return { server, client, toolNames: tools.map((tool) => tool.name) };\n}\n","/**\n * An error returned by the AcruxCore REST API.\n *\n * The API's error envelope is `{ error: { code, message, ...details } }`. Everything\n * inside it is preserved: an MCP client's model can act on `MISSING_VARIABLES` plus the\n * `missing` array, or on `TOOL_NAME_TAKEN`, in a way it can never act on a bare\n * \"request failed\". `code` is the string the API sent, or a synthesised one\n * (`HTTP_<status>`) when a proxy returned a non-JSON body.\n */\nexport class AcruxCoreApiError extends Error {\n /** HTTP status of the failed response. `0` for a transport-level failure. */\n readonly status: number;\n\n /** AcruxCore error code, e.g. `NOT_FOUND`, `MISSING_VARIABLES`, `TOOL_NAME_TAKEN`. */\n readonly code: string;\n\n /** Any extra keys the error envelope carried beyond `code` and `message`. */\n readonly details: Record<string, unknown>;\n\n /** The request that failed, as `METHOD /path` — included in the message for context. */\n readonly request: string;\n\n /**\n * @param request - `METHOD /path` of the failed call.\n * @param status - HTTP status, or 0 when the request never completed.\n * @param code - AcruxCore error code.\n * @param message - Human-readable message, taken verbatim from the API when present.\n * @param details - Remaining keys from the error envelope.\n */\n constructor(\n request: string,\n status: number,\n code: string,\n message: string,\n details: Record<string, unknown> = {},\n ) {\n super(message);\n this.name = 'AcruxCoreApiError';\n this.request = request;\n this.status = status;\n this.code = code;\n this.details = details;\n }\n\n /**\n * Renders the error for an MCP tool result: code, status, message, and any details.\n *\n * Kept as one line per fact rather than a JSON blob because this text is what the\n * calling model reads to decide what to do next.\n *\n * @returns Multi-line text safe to put in a `CallToolResult` content block.\n */\n toToolText(): string {\n const lines = [\n `AcruxCore API error (${this.code})`,\n `Request: ${this.request}`,\n `Status: ${this.status}`,\n `Message: ${this.message}`,\n ];\n const detailKeys = Object.keys(this.details);\n if (detailKeys.length > 0) {\n lines.push(`Details: ${JSON.stringify(this.details)}`);\n }\n return lines.join('\\n');\n }\n}\n\n/**\n * A configuration problem detected before any request is made — a missing API key, an\n * unknown toolset name. Separate from {@link AcruxCoreApiError} because it is fatal at\n * startup rather than per-call, and the stdio entry point exits on it.\n */\nexport class McpConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'McpConfigError';\n }\n}\n","import { AcruxCoreApiError } from './errors';\n\n/** HTTP verbs this client issues. */\ntype Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';\n\n/** Options for a single request. */\nexport interface RequestOptions {\n /** JSON body. Omitted for GET/DELETE unless a body is genuinely needed. */\n body?: unknown;\n /** Query string parameters. `undefined` and `null` values are dropped. */\n query?: Record<string, string | number | boolean | undefined | null>;\n /** Extra request headers, e.g. the gateway's `x-trace-name`. */\n headers?: Record<string, string>;\n}\n\n/** A response body plus the headers a caller may need to read. */\nexport interface RawResponse<T> {\n data: T;\n headers: Headers;\n status: number;\n}\n\n/**\n * Appends `/api/v1` when the caller gave a bare host.\n *\n * Both forms are in the wild: the SDKs document `ACRUXCORE_BASE_URL` *with* the version\n * prefix, while someone configuring an MCP client by hand almost always pastes the\n * dashboard URL. Guessing wrong produces a 404 on every single tool call, which reads\n * like a broken server rather than a mistyped URL, so normalise instead.\n *\n * @param raw - Base URL as configured.\n * @returns A base URL ending in `/api/v1`, with no trailing slash.\n */\nexport function normalizeBaseUrl(raw: string): string {\n const trimmed = raw.trim().replace(/\\/+$/, '');\n if (/\\/api\\/v\\d+$/.test(trimmed)) return trimmed;\n return `${trimmed}/api/v1`;\n}\n\n/**\n * Thin REST client for the AcruxCore API.\n *\n * Deliberately not the published `@acruxcoreai/sdk`: the MCP server needs endpoints the\n * SDK does not surface (eval rules, audit, gateway usage), needs the raw response\n * headers the gateway returns (`x-gateway-cost-usd`, `x-gateway-trace-id`), and must\n * pass an arbitrary caller-supplied bearer token per request when hosted inside the API.\n * Wrapping the SDK would mean fighting all three.\n */\nexport class AcruxCoreClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly userAgent: string;\n\n /**\n * @param options.baseUrl - AcruxCore base URL, with or without the `/api/v1` suffix.\n * @param options.apiKey - An `acx_sk_…` API key.\n * @param options.timeoutMs - Per-request timeout. Defaults to 60s, which has to cover\n * a gateway completion, not just a database read.\n * @param options.userAgent - Sent as `user-agent`, so API request logs can tell MCP\n * traffic from SDK traffic.\n */\n constructor(options: { baseUrl: string; apiKey: string; timeoutMs?: number; userAgent?: string }) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey;\n this.timeoutMs = options.timeoutMs ?? 60_000;\n this.userAgent = options.userAgent ?? 'acruxcore-mcp-server';\n }\n\n /** The normalised base URL this client calls. */\n get resolvedBaseUrl(): string {\n return this.baseUrl;\n }\n\n /**\n * Issues one request and returns the parsed body.\n *\n * @param method - HTTP verb.\n * @param path - Path below the base URL, starting with `/`.\n * @param options - Body, query and extra headers.\n * @returns The parsed JSON body, or `undefined` for a 204.\n * @throws {AcruxCoreApiError} On any non-2xx response, or a transport failure.\n */\n async request<T = unknown>(method: Method, path: string, options: RequestOptions = {}): Promise<T> {\n const { data } = await this.requestRaw<T>(method, path, options);\n return data;\n }\n\n /**\n * Issues one request and returns the body together with status and headers.\n *\n * Used by the gateway tools, where the interesting metadata (cost, provider, trace id)\n * arrives in `x-gateway-*` headers rather than the body.\n *\n * @param method - HTTP verb.\n * @param path - Path below the base URL, starting with `/`.\n * @param options - Body, query and extra headers.\n * @returns Parsed body, status and headers.\n * @throws {AcruxCoreApiError} On any non-2xx response, or a transport failure.\n */\n async requestRaw<T = unknown>(\n method: Method,\n path: string,\n options: RequestOptions = {},\n ): Promise<RawResponse<T>> {\n const url = new URL(`${this.baseUrl}${path}`);\n for (const [key, value] of Object.entries(options.query ?? {})) {\n if (value === undefined || value === null || value === '') continue;\n url.searchParams.set(key, String(value));\n }\n\n const label = `${method} ${path}`;\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.apiKey}`,\n accept: 'application/json',\n 'user-agent': this.userAgent,\n ...options.headers,\n };\n if (options.body !== undefined) headers['content-type'] = 'application/json';\n\n let response: Response;\n try {\n response = await fetch(url.toString(), {\n method,\n headers,\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n // A transport failure carries no status. Surfacing it with the URL is the\n // difference between \"the server is down\" and \"the base URL is wrong\", which are\n // the two things a user actually needs to tell apart here.\n const reason = err instanceof Error ? err.message : String(err);\n throw new AcruxCoreApiError(\n label,\n 0,\n 'NETWORK_ERROR',\n `Could not reach AcruxCore at ${url.origin}: ${reason}`,\n );\n }\n\n const text = await response.text();\n let parsed: unknown = undefined;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!response.ok) {\n throw toApiError(label, response.status, parsed);\n }\n\n return { data: parsed as T, headers: response.headers, status: response.status };\n }\n\n /** GET shorthand. @see {@link request} */\n get<T = unknown>(path: string, query?: RequestOptions['query']): Promise<T> {\n return this.request<T>('GET', path, { query });\n }\n\n /** POST shorthand. @see {@link request} */\n post<T = unknown>(path: string, body?: unknown, options: Omit<RequestOptions, 'body'> = {}): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /** PATCH shorthand. @see {@link request} */\n patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n /** PUT shorthand. @see {@link request} */\n put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, { body });\n }\n\n /** DELETE shorthand. @see {@link request} */\n delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n\n/**\n * Turns a failed response body into an {@link AcruxCoreApiError}.\n *\n * Handles the three shapes that actually come back: our own\n * `{ error: { code, message, … } }` envelope, a plain string (nginx or a proxy), and\n * anything else (fall back to the status).\n *\n * @param label - `METHOD /path` for the failed call.\n * @param status - HTTP status.\n * @param body - Parsed response body, whatever shape it turned out to be.\n * @returns The error to throw.\n */\nfunction toApiError(label: string, status: number, body: unknown): AcruxCoreApiError {\n if (body && typeof body === 'object' && 'error' in body) {\n const envelope = (body as { error: unknown }).error;\n if (envelope && typeof envelope === 'object') {\n const { code, message, ...details } = envelope as Record<string, unknown>;\n return new AcruxCoreApiError(\n label,\n status,\n typeof code === 'string' ? code : `HTTP_${status}`,\n typeof message === 'string' ? message : `Request failed with status ${status}.`,\n details,\n );\n }\n }\n\n const message =\n typeof body === 'string' && body.trim().length > 0\n ? body.trim().slice(0, 500)\n : `Request failed with status ${status}.`;\n return new AcruxCoreApiError(label, status, `HTTP_${status}`, message);\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { AcruxCoreApiError } from './errors';\n\n/**\n * What a tool handler returns.\n *\n * Aliased to the SDK's own `CallToolResult` rather than redeclared, so a protocol\n * revision that adds a field to a tool result cannot silently drift from what we emit.\n */\nexport type ToolResult = CallToolResult;\n\n/**\n * Truncates text to a byte budget, appending a marker that says so.\n *\n * Byte-based rather than character-based because the budget exists to protect a context\n * window, and a UTF-8 multibyte character costs more than one. The cut is made on a\n * character boundary by shrinking from the end, so the result is never invalid UTF-8.\n *\n * @param text - Text to cap.\n * @param maxBytes - Maximum bytes of UTF-8 to keep.\n * @returns The text unchanged, or a truncated copy ending in a `[truncated …]` marker.\n */\nexport function truncateText(text: string, maxBytes: number): string {\n const encoder = new TextEncoder();\n if (encoder.encode(text).length <= maxBytes) return text;\n\n const marker = '\\n\\n[truncated: response exceeded the size limit — narrow the query, ' +\n 'use a smaller `limit`, or fetch one item at a time]';\n const budget = Math.max(0, maxBytes - encoder.encode(marker).length);\n\n let end = Math.min(text.length, budget);\n while (end > 0 && encoder.encode(text.slice(0, end)).length > budget) {\n // Shrink by a quarter of the overshoot: a UTF-8 character is at most 4 bytes, so\n // this always removes at least one character and converges in a few passes.\n end -= Math.ceil((encoder.encode(text.slice(0, end)).length - budget) / 4);\n }\n return text.slice(0, Math.max(0, end)) + marker;\n}\n\n/**\n * Builds a successful tool result: a one-line human summary, then the JSON payload.\n *\n * Both halves earn their place. The summary is what a model reads when it only needs to\n * know the call worked (\"Promoted alias production to version 3\"); the JSON is what it\n * reads when it needs a field. Returning only JSON makes every result a parsing job;\n * returning only prose throws away the ids the next call needs.\n *\n * @param summary - One line describing what happened.\n * @param payload - Structured data to include, or `undefined` for summary-only.\n * @param maxBytes - Byte budget for the whole result.\n * @returns An MCP `CallToolResult`-shaped object.\n */\nexport function okResult(summary: string, payload: unknown, maxBytes: number): ToolResult {\n const text =\n payload === undefined\n ? summary\n : `${summary}\\n\\n${JSON.stringify(payload, null, 2)}`;\n return { content: [{ type: 'text', text: truncateText(text, maxBytes) }] };\n}\n\n/**\n * Builds a failed tool result.\n *\n * MCP reports tool failures in-band (`isError: true`) rather than as a JSON-RPC error,\n * precisely so the model sees them and can retry differently. An `AcruxCoreApiError`\n * renders with its code and details intact; anything else renders its message.\n *\n * @param error - The thrown value.\n * @param maxBytes - Byte budget for the message.\n * @returns An MCP `CallToolResult` with `isError` set.\n */\nexport function errorResult(error: unknown, maxBytes: number): ToolResult {\n const text =\n error instanceof AcruxCoreApiError\n ? error.toToolText()\n : error instanceof Error\n ? `${error.name}: ${error.message}`\n : `Unexpected error: ${String(error)}`;\n return { content: [{ type: 'text', text: truncateText(text, maxBytes) }], isError: true };\n}\n\n/**\n * Formats the `{ data, total, page, limit }` envelope the list endpoints return.\n *\n * @param noun - Plural noun for the summary line, e.g. `prompts`.\n * @param page - The list response.\n * @returns A summary line naming how many of how many are shown.\n */\nexport function listSummary(\n noun: string,\n page: { data?: unknown[]; total?: number; page?: number; limit?: number },\n): string {\n const shown = page.data?.length ?? 0;\n const total = page.total ?? shown;\n const pageNo = page.page ?? 1;\n if (total === 0) return `No ${noun} found.`;\n return `Showing ${shown} of ${total} ${noun} (page ${pageNo}).`;\n}\n","import {\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n type GetPromptResult,\n type ListPromptsResult,\n type PromptMessage,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\n\n/** How many registry prompts one `prompts/list` page carries. */\nconst PAGE_SIZE = 25;\n\n/** How many per-prompt lookups run at once while building a page. */\nconst LOOKUP_CONCURRENCY = 8;\n\n/** A prompt row from `GET /prompts`. */\ninterface PromptRow {\n id: string;\n name: string;\n description?: string | null;\n}\n\n/** An alias row from `GET /prompts/:id/aliases`. */\ninterface AliasRow {\n alias: string;\n versionNumber: number;\n}\n\n/** A version row from `GET /prompts/:id/versions`. */\ninterface VersionRow {\n versionNumber: number;\n variables?: string[];\n}\n\n/** A registry prompt resolved to what MCP needs to advertise it. */\ninterface ResolvedPrompt {\n name: string;\n description: string;\n variables: string[];\n}\n\n/**\n * Runs an async mapper over a list with a fixed concurrency ceiling.\n *\n * Building a prompts page costs two lookups per prompt. Firing them all at once against\n * a 100-prompt registry would open 200 sockets; doing them one at a time would make the\n * listing visibly slow. Eight at a time is the compromise.\n *\n * @param items - Input items.\n * @param limit - Maximum in-flight mappers.\n * @param mapper - Async transform.\n * @returns Results in input order.\n */\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n mapper: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let next = 0;\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (true) {\n const index = next++;\n if (index >= items.length) return;\n results[index] = await mapper(items[index]);\n }\n });\n await Promise.all(workers);\n return results;\n}\n\n/**\n * Resolves one registry prompt to the alias's version and that version's variables.\n *\n * Returns `null` rather than throwing when the prompt has no version at the configured\n * alias: a half-built prompt is a normal state in a registry, and one of them must not\n * break the whole listing.\n *\n * @param client - REST client.\n * @param row - The prompt row.\n * @param alias - Alias to resolve.\n * @returns The resolved prompt, or null when the alias does not exist for it.\n */\nasync function resolvePrompt(\n client: AcruxCoreClient,\n row: PromptRow,\n alias: string,\n): Promise<ResolvedPrompt | null> {\n try {\n const [aliases, versions] = await Promise.all([\n client.get<AliasRow[]>(`/prompts/${row.id}/aliases`),\n client.get<{ data?: VersionRow[] }>(`/prompts/${row.id}/versions`, { limit: 100 }),\n ]);\n\n const match = (Array.isArray(aliases) ? aliases : []).find((a) => a.alias === alias);\n if (!match) return null;\n\n const version = (versions.data ?? []).find((v) => v.versionNumber === match.versionNumber);\n return {\n name: row.name,\n description:\n `${row.description ?? 'AcruxCore registry prompt'} ` +\n `(alias \"${alias}\", version ${match.versionNumber})`,\n variables: version?.variables ?? [],\n };\n } catch {\n // One unreadable prompt must not empty the whole list — the client would show\n // \"no prompts\" and the user would think the server was broken.\n return null;\n }\n}\n\n/**\n * Builds one page of registry prompts.\n *\n * @param client - REST client.\n * @param alias - Alias to expose.\n * @param page - 1-based page number.\n * @returns The resolved prompts and whether another page exists.\n */\nasync function listRegistryPrompts(\n client: AcruxCoreClient,\n alias: string,\n page: number,\n): Promise<{ prompts: ResolvedPrompt[]; hasMore: boolean }> {\n const listed = await client.get<{ data?: PromptRow[]; total?: number }>('/prompts', {\n page,\n limit: PAGE_SIZE,\n });\n const rows = listed.data ?? [];\n const resolved = await mapWithConcurrency(rows, LOOKUP_CONCURRENCY, (row) =>\n resolvePrompt(client, row, alias),\n );\n const total = listed.total ?? rows.length;\n return {\n prompts: resolved.filter((p): p is ResolvedPrompt => p !== null),\n hasMore: page * PAGE_SIZE < total,\n };\n}\n\n/**\n * Converts rendered registry messages into MCP prompt messages.\n *\n * MCP's `PromptMessage.role` is `user | assistant` — the protocol has no system role.\n * A registry prompt whose template opens with a system message therefore cannot\n * round-trip as-is. Emitting it as the leading `user` message keeps the instruction in\n * the conversation, in position, with its text unchanged; dropping it would silently\n * change what the prompt does.\n *\n * @param messages - Rendered messages from the render endpoint.\n * @returns MCP-shaped prompt messages.\n */\nexport function toPromptMessages(\n messages: Array<{ role?: string; content?: unknown }>,\n): PromptMessage[] {\n return messages.map((message) => ({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content: {\n type: 'text' as const,\n text: typeof message.content === 'string' ? message.content : JSON.stringify(message.content),\n },\n }));\n}\n\n/**\n * Registers the MCP prompts primitive, backed by the AcruxCore prompt registry.\n *\n * This is the piece that makes the server more than an API wrapper: a team's production\n * prompts become slash commands in the client, with the template variables as typed\n * arguments, resolved through the same alias production traffic uses.\n *\n * Handlers are set on the low-level server rather than through `registerPrompt` because\n * the list is not known at startup — it is whatever the team's registry holds right now.\n *\n * Nothing is cached. The obvious 60-second cache would be a module-level map shared by\n * every request of the hosted transport, where each request may carry a *different*\n * team's API key — a cross-tenant leak in exchange for saving one list call.\n *\n * @param server - The MCP server to register on.\n * @param client - REST client carrying the caller's API key.\n * @param config - Resolved configuration; `promptAlias` decides which alias is exposed.\n */\nexport function registerRegistryPrompts(\n server: McpServer,\n client: AcruxCoreClient,\n config: McpServerConfig,\n): void {\n server.server.registerCapabilities({ prompts: { listChanged: false } });\n\n server.server.setRequestHandler(ListPromptsRequestSchema, async (request): Promise<ListPromptsResult> => {\n const page = parseCursor(request.params?.cursor);\n const { prompts, hasMore } = await listRegistryPrompts(client, config.promptAlias, page);\n\n return {\n prompts: prompts.map((prompt) => ({\n name: prompt.name,\n title: prompt.name,\n description: prompt.description,\n arguments: prompt.variables.map((variable) => ({\n name: variable,\n description: `Template variable \"${variable}\".`,\n required: true,\n })),\n })),\n ...(hasMore ? { nextCursor: String(page + 1) } : {}),\n };\n });\n\n server.server.setRequestHandler(GetPromptRequestSchema, async (request): Promise<GetPromptResult> => {\n const { name, arguments: args } = request.params;\n const rendered = await client.post<{\n messages?: Array<{ role?: string; content?: unknown }>;\n versionNumber?: number;\n }>(`/prompts/${encodeURIComponent(name)}/${encodeURIComponent(config.promptAlias)}/render`, {\n variables: args ?? {},\n });\n\n return {\n description: `AcruxCore prompt \"${name}\" at alias \"${config.promptAlias}\" (version ${rendered.versionNumber}).`,\n messages: toPromptMessages(rendered.messages ?? []),\n };\n });\n}\n\n/**\n * Reads a page number out of an MCP cursor.\n *\n * @param cursor - Opaque cursor from the client, if any.\n * @returns A 1-based page number; 1 for anything unparseable.\n */\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) return 1;\n const page = Number(cursor);\n return Number.isInteger(page) && page > 0 ? page : 1;\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\nimport { truncateText } from './format';\n\n/** A prompt row from `GET /prompts`. */\ninterface PromptRow {\n id: string;\n name: string;\n description?: string | null;\n}\n\n/**\n * Registers the `acruxcore://` resources.\n *\n * Resources exist alongside the tools because reading and doing are different acts. A\n * client attaches a resource to context without a tool call and without the model\n * deciding to fetch it — which is exactly right for \"here is the prompt template we are\n * discussing\" or \"here is the trace that failed\". The same content is reachable through\n * `get_prompt`/`get_trace`, but only as the result of the model choosing to look.\n *\n * @param server - The MCP server to register on.\n * @param client - REST client carrying the caller's API key.\n * @param config - Resolved configuration.\n */\nexport function registerResources(\n server: McpServer,\n client: AcruxCoreClient,\n config: McpServerConfig,\n): void {\n server.registerResource(\n 'prompt-template',\n new ResourceTemplate('acruxcore://prompts/{name}/{alias}', {\n // Listing the registry at the configured alias gives the client something to show\n // in a resource picker. Every alias of every prompt would be a combinatorial list\n // nobody can scan.\n list: async () => {\n const listed = await client.get<{ data?: PromptRow[] }>('/prompts', { limit: 100 });\n return {\n resources: (listed.data ?? []).map((row) => ({\n uri: `acruxcore://prompts/${row.name}/${config.promptAlias}`,\n name: row.name,\n description: row.description ?? `AcruxCore prompt \"${row.name}\".`,\n mimeType: 'application/json',\n })),\n };\n },\n }),\n {\n title: 'AcruxCore prompt template',\n description:\n 'The raw, unrendered template of the version an alias points at, with its ' +\n 'variables and bound default model.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const name = String(variables.name);\n const alias = String(variables.alias);\n\n // The raw template, not a render: a resource is for reading what the prompt *is*,\n // and rendering would need variable values the reader has not supplied.\n const promptId = await promptIdFor(client, name);\n const aliases = await client.get<Array<{ alias: string; versionNumber: number }>>(\n `/prompts/${promptId}/aliases`,\n );\n const match = aliases.find((a) => a.alias === alias);\n if (!match) {\n throw new Error(`Prompt \"${name}\" has no alias \"${alias}\".`);\n }\n const version = await client.get<unknown>(\n `/prompts/${promptId}/versions/${match.versionNumber}`,\n );\n\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: truncateText(JSON.stringify(version, null, 2), config.maxTextBytes),\n },\n ],\n };\n },\n );\n\n server.registerResource(\n 'trace',\n new ResourceTemplate('acruxcore://traces/{traceId}', {\n // Deliberately unlisted: a team accumulates traces without limit, so enumerating\n // them into a resource picker would be useless at best. Traces are found with\n // search_traces and then addressed by id.\n list: undefined,\n }),\n {\n title: 'AcruxCore trace',\n description: 'One trace with its full span tree, tokens, cost and latency.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const trace = await client.get<unknown>(`/traces/${String(variables.traceId)}`);\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: truncateText(JSON.stringify(trace, null, 2), config.maxTextBytes),\n },\n ],\n };\n },\n );\n}\n\n/**\n * Looks up a prompt id by name for the resource handlers.\n *\n * @param client - REST client.\n * @param name - Prompt name from the URI.\n * @returns The prompt's UUID.\n * @throws {Error} When no prompt in the team carries that name.\n */\nasync function promptIdFor(client: AcruxCoreClient, name: string): Promise<string> {\n const listed = await client.get<{ data?: PromptRow[] }>('/prompts', { search: name, limit: 100 });\n const exact = (listed.data ?? []).find((row) => row.name === name);\n if (!exact) throw new Error(`No prompt named \"${name}\" in this team.`);\n return exact.id;\n}\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { resolveToolRef } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A tool reference accepted by every tool here. */\nconst toolRef = z\n .string()\n .min(1)\n .describe('Catalog tool name (e.g. \"get_weather\") or tool UUID. Names are resolved for you.');\n\n/** One name/value pair used for a header or a query parameter on an HTTP executor. */\nconst nameValueSchema = z.object({\n name: z.string().min(1).describe('Header or query parameter name.'),\n value: z\n .string()\n .describe('Value. May reference a stored secret as {{ secrets.MY_SECRET }}.'),\n});\n\n/** How a tool argument is carried into the upstream HTTP request. */\nconst argMappingSchema = z.object({\n arg: z.string().min(1).describe('Argument name from parametersSchema.'),\n in: z.enum(['query', 'path', 'header', 'body']).describe('Where the argument goes.'),\n path: z.string().optional().describe('Dotted path within the body, when `in` is \"body\".'),\n});\n\n/** Either \"your app runs it\" or a declarative HTTP call AcruxCore runs server-side. */\nconst executorSchema = z.union([\n z\n .object({ type: z.literal('client') })\n .describe('Definition only — the caller\\'s own app executes the tool.'),\n z\n .object({\n type: z.literal('http'),\n url: z.string().url().describe('Absolute upstream URL. localhost is rejected by design.'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n headers: z.array(nameValueSchema).optional(),\n query: z.array(nameValueSchema).optional(),\n bodyTemplate: z.string().optional().describe('JSON body template.'),\n argMapping: z.array(argMappingSchema).optional(),\n requestTransform: z\n .string()\n .optional()\n .describe('Full JS function source: function transform(input) { … }'),\n responseTransform: z\n .string()\n .optional()\n .describe('Full JS function source: function transform(input) { … }'),\n })\n .describe('AcruxCore executes the call server-side.'),\n]);\n\n/**\n * Tools for the Tool Catalog — the versioned registry of function definitions a prompt\n * can bind to.\n *\n * The distinction these descriptions must carry is the one people get wrong: a catalog\n * entry has a *definition* (the schema and description the model reads) and an\n * *executor* (who actually runs it). A `client` executor stores only the definition; an\n * `http` executor lets AcruxCore make the call itself.\n */\nexport const catalogTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_catalog_tools',\n title: 'List catalog tools',\n toolset: 'tools',\n readOnlyHint: true,\n description:\n 'List the tools in the team\\'s Tool Catalog. These are the function definitions a ' +\n 'prompt alias can bind to and the gateway can attach to a completion.',\n inputSchema: {\n search: z.string().optional().describe('Substring filter over name and description.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler({ search, page, limit }, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/tools', {\n search,\n page,\n limit,\n });\n return okResult(listSummary('catalog tools', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_catalog_tool',\n title: 'Get a catalog tool with its versions and aliases',\n toolset: 'tools',\n readOnlyHint: true,\n description:\n 'Read one catalog tool in full: metadata, every committed version (parameters ' +\n 'schema, executor, source) and every alias with the version it points at. Call ' +\n 'this before executing, to see whether the tool has a server-side http executor ' +\n 'or is definition-only.',\n inputSchema: { tool: toolRef },\n async handler({ tool }, { client, config }) {\n const id = await resolveToolRef(client, tool);\n const [detail, versions, aliases] = await Promise.all([\n client.get<Record<string, unknown>>(`/tools/${id}`),\n client.get<{ data?: unknown[] }>(`/tools/${id}/versions`, { limit: 100 }),\n client.get<unknown[]>(`/tools/${id}/aliases`),\n ]);\n return okResult(\n `Tool \"${detail.name}\" — ${versions.data?.length ?? 0} version(s).`,\n { tool: detail, versions: versions.data ?? [], aliases },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'sync_catalog_tool',\n title: 'Create or update a catalog tool',\n toolset: 'tools',\n readOnlyHint: false,\n description:\n 'Create-or-commit-or-nothing for one tool, addressed by name. If the name is new ' +\n 'the tool is created and v1 committed; if the spec differs from the version the ' +\n 'alias points at, a new version is committed and the alias moved; if the spec is ' +\n 'identical, nothing happens (key order does not count as a change). This is the ' +\n 'one call to use for \"add this tool\" and \"update this tool\\'s description\" alike.',\n inputSchema: {\n name: z\n .string()\n .min(1)\n .max(64)\n .describe('Tool name. Must match ^[a-zA-Z0-9_-]{1,64}$ — LLM function-name safe.'),\n description: z\n .string()\n .max(2000)\n .optional()\n .describe('What the tool does. This is text the MODEL reads, so write it for a model.'),\n parametersSchema: z\n .record(z.unknown())\n .describe('JSON Schema object for the arguments, e.g. {\"type\":\"object\",\"properties\":{…}}.'),\n executor: executorSchema,\n alias: z.string().min(1).max(64).optional().describe('Alias to move. Default \"production\".'),\n changelog: z.string().max(2000).optional().describe('Why this version changed.'),\n },\n async handler(args, { client, config }) {\n const result = await client.post<{\n toolId: string;\n versionNumber: number;\n committed: boolean;\n alias: string;\n }>('/tools/sync', {\n ...args,\n // `code` means \"derived from a decorated function in a source file\", and the\n // dashboard's ownership warnings depend on that being literally true. An MCP\n // client is not that, so it claims `api` rather than taking the endpoint default.\n source: 'api',\n });\n return okResult(\n result.committed\n ? `Committed version ${result.versionNumber} of \"${args.name}\"; alias \"${result.alias}\" now points at it.`\n : `No change — \"${args.name}\" already matches version ${result.versionNumber} at alias \"${result.alias}\".`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'execute_catalog_tool',\n title: 'Execute a catalog tool',\n toolset: 'tools',\n readOnlyHint: false,\n description:\n 'Run a catalog tool server-side and return its result. Only works for a version ' +\n 'with an \"http\" executor — a definition-only (\"client\") version returns ' +\n 'NOT_EXECUTABLE, because there is nothing for AcruxCore to call. Arguments are ' +\n 'validated against the version\\'s parameters schema before the call is made.',\n inputSchema: {\n tool: toolRef,\n arguments: z.record(z.unknown()).describe('Arguments matching the tool\\'s parameters schema.'),\n alias: z.string().optional().describe('Alias to resolve. Default \"production\".'),\n version_number: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Pin an exact version instead of following an alias.'),\n },\n async handler({ tool, ...args }, { client, config }) {\n const id = await resolveToolRef(client, tool);\n const body: Record<string, unknown> = { arguments: args.arguments };\n if (args.alias !== undefined) body.alias = args.alias;\n if (args.version_number !== undefined) body.versionNumber = args.version_number;\n\n const result = await client.post<{ status?: number; latencyMs?: number }>(\n `/tools/${id}/execute`,\n body,\n );\n return okResult(\n `Executed \"${tool}\" — upstream status ${result.status}, ${result.latencyMs}ms.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n];\n","import type { AcruxCoreClient } from './client';\nimport { AcruxCoreApiError } from './errors';\n\n/** Matches a canonical v4-shaped UUID, which is what every AcruxCore id is. */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Reports whether a reference is already an id rather than a name.\n *\n * @param ref - The user-supplied reference.\n * @returns True when it looks like a UUID.\n */\nexport function isUuid(ref: string): boolean {\n return UUID_RE.test(ref.trim());\n}\n\n/** One entry of a `{ data: [...] }` list response with a name. */\ninterface NamedRow {\n id: string;\n name: string;\n}\n\n/**\n * Resolves a prompt reference — a UUID or a prompt name — to a prompt id.\n *\n * Accepting names is not a convenience, it is what makes the tools usable by a model.\n * An assistant is told \"promote customer-support\"; requiring the UUID first costs an\n * extra round trip and invites a hallucinated id that then 404s confusingly.\n *\n * @param client - REST client.\n * @param ref - Prompt UUID or exact prompt name.\n * @returns The prompt's UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when no active prompt carries that name.\n */\nexport async function resolvePromptRef(client: AcruxCoreClient, ref: string): Promise<string> {\n return resolveNamedRef(client, '/prompts', ref, 'prompt');\n}\n\n/**\n * Resolves a catalog-tool reference — a UUID or a tool name — to a tool id.\n *\n * @param client - REST client.\n * @param ref - Tool UUID or exact tool name.\n * @returns The tool's UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when no active tool carries that name.\n */\nexport async function resolveToolRef(client: AcruxCoreClient, ref: string): Promise<string> {\n return resolveNamedRef(client, '/tools', ref, 'tool');\n}\n\n/**\n * Shared name→id lookup for the two collections that support `?search=`.\n *\n * The search endpoint is a substring match, so the exact name is picked out of the\n * results rather than trusting the first row: searching `weather` when both\n * `get_weather` and `get_weather_forecast` exist must not silently pick one.\n *\n * @param client - REST client.\n * @param path - Collection path, e.g. `/prompts`.\n * @param ref - UUID or name.\n * @param noun - Singular noun for error messages.\n * @returns The resolved UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when the name matches nothing exactly.\n */\nasync function resolveNamedRef(\n client: AcruxCoreClient,\n path: string,\n ref: string,\n noun: string,\n): Promise<string> {\n const trimmed = ref.trim();\n if (isUuid(trimmed)) return trimmed;\n\n const page = await client.get<{ data?: NamedRow[] }>(path, { search: trimmed, limit: 100 });\n const exact = (page.data ?? []).find((row) => row.name === trimmed);\n if (exact) return exact.id;\n\n const near = (page.data ?? []).map((row) => row.name).slice(0, 10);\n const hint = near.length > 0 ? ` Closest names: ${near.join(', ')}.` : '';\n throw new AcruxCoreApiError(\n `GET ${path}?search=${trimmed}`,\n 404,\n 'NOT_FOUND',\n `No ${noun} named \"${trimmed}\" in this team.${hint}`,\n );\n}\n\n/**\n * Resolves a prompt reference to both its id and its name.\n *\n * `render_prompt` and the gateway's stored-prompt path address prompts by **name**, but\n * every other prompt route addresses them by id, so a tool that does both needs the pair.\n *\n * @param client - REST client.\n * @param ref - Prompt UUID or name.\n * @returns The prompt's id and name.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when the reference matches no prompt.\n */\nexport async function resolvePromptIdAndName(\n client: AcruxCoreClient,\n ref: string,\n): Promise<{ id: string; name: string }> {\n const trimmed = ref.trim();\n if (isUuid(trimmed)) {\n const prompt = await client.get<{ id: string; name: string }>(`/prompts/${trimmed}`);\n return { id: prompt.id, name: prompt.name };\n }\n const id = await resolvePromptRef(client, trimmed);\n return { id, name: trimmed };\n}\n","import type { z, ZodRawShape } from 'zod';\nimport type { AcruxCoreClient } from '../client';\nimport type { McpServerConfig, Toolset } from '../config';\nimport type { ToolResult } from '../format';\n\n/** Everything a tool handler is given besides its own arguments. */\nexport interface ToolContext {\n /** REST client already carrying the caller's API key. */\n client: AcruxCoreClient;\n /** Resolved server configuration — handlers read `maxTextBytes` from it. */\n config: McpServerConfig;\n}\n\n/**\n * A registered tool, erased to a uniform shape so every toolset can live in one array.\n *\n * `handler` takes `unknown` here; {@link defineTool} does the one cast that restores the\n * inferred argument type at each definition site, so no individual tool needs `any`.\n */\nexport interface AnyToolDefinition {\n /** Tool name as the client sees it. Snake case, verb first. */\n name: string;\n /** Short human title for clients that show one. */\n title: string;\n /** What the model reads to decide whether to call this tool. */\n description: string;\n /** Zod raw shape for the arguments. */\n inputSchema: ZodRawShape;\n /** Which toolset this belongs to. */\n toolset: Toolset;\n /** False for anything that writes. Mutating tools are dropped in read-only mode. */\n readOnlyHint: boolean;\n /** True when a call can remove or overwrite something a user would miss. */\n destructiveHint?: boolean;\n /** Runs the tool. */\n handler: (args: unknown, ctx: ToolContext) => Promise<ToolResult>;\n}\n\n/**\n * Declares a tool with its argument type inferred from the Zod shape.\n *\n * @param def - The tool definition; `handler` receives arguments typed from `inputSchema`.\n * @returns The same definition, erased to {@link AnyToolDefinition}.\n */\nexport function defineTool<Shape extends ZodRawShape>(def: {\n name: string;\n title: string;\n description: string;\n inputSchema: Shape;\n toolset: Toolset;\n readOnlyHint: boolean;\n destructiveHint?: boolean;\n handler: (args: z.infer<z.ZodObject<Shape>>, ctx: ToolContext) => Promise<ToolResult>;\n}): AnyToolDefinition {\n return {\n ...def,\n handler: (args, ctx) => def.handler(args as z.infer<z.ZodObject<Shape>>, ctx),\n };\n}\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { resolvePromptRef } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A prior-turn message replayed ahead of an example's input during a run. */\nconst historyMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant', 'tool']),\n content: z.string(),\n});\n\n/**\n * Tools for evaluation: datasets of examples, experiments that sweep a grid of\n * (version x model) over them, and the runs that produce scores.\n *\n * The chain is fixed and the descriptions say so, because skipping a link is the common\n * mistake: a **dataset** holds examples, an **experiment** pairs a dataset with the grid\n * to sweep, and a **run** executes it asynchronously in the worker. Creating an\n * experiment scores nothing until a run is started, and a run returns immediately —\n * results arrive later.\n */\nexport const evaluationTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_datasets',\n title: 'List evaluation datasets',\n toolset: 'evaluations',\n readOnlyHint: true,\n description: 'List the team\\'s evaluation datasets with their example counts.',\n inputSchema: {\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/datasets', args);\n return okResult(listSummary('datasets', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_dataset',\n title: 'Get one dataset with its examples',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'Read one dataset: its name, dataset-level rubric (overallFeedback) and its ' +\n 'examples, each with the input variables and the per-example criteria a judge ' +\n 'scores against.',\n inputSchema: { dataset_id: z.string().uuid().describe('Dataset UUID.') },\n async handler({ dataset_id }, { client, config }) {\n const result = await client.get<{ name?: string; examples?: unknown[] }>(\n `/datasets/${dataset_id}`,\n );\n return okResult(\n `Dataset \"${result.name}\" — ${result.examples?.length ?? 0} example(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'create_dataset',\n title: 'Create an evaluation dataset',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Create an empty dataset. Add examples afterwards with add_dataset_example. ' +\n '`overall_feedback` is a rubric applied on top of each example\\'s own criteria — ' +\n 'write it as an instruction to the judge, not as a complaint about an answer.',\n inputSchema: {\n name: z.string().min(1).describe('Dataset name.'),\n overall_feedback: z\n .string()\n .optional()\n .describe('Dataset-level rubric, e.g. \"Keep responses concise and polite\".'),\n },\n async handler({ name, overall_feedback }, { client, config }) {\n const result = await client.post<{ id: string; name: string }>('/datasets', {\n name,\n overall_feedback,\n });\n return okResult(\n `Created dataset \"${result.name}\" (${result.id}). It has no examples yet.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'add_dataset_example',\n title: 'Add an example to a dataset',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Add one example. `input` is the variable bag the prompt is rendered with; ' +\n '`criteria` is what the judge checks this particular answer against. `history` ' +\n 'supplies prior conversation turns to replay before the input — omit it for a ' +\n 'single-turn example.',\n inputSchema: {\n dataset_id: z.string().uuid().describe('Dataset UUID.'),\n input: z.record(z.unknown()).describe('Template variables for this example, e.g. {\"name\":\"Bob\"}.'),\n criteria: z.string().optional().describe('What a correct answer must do.'),\n history: z\n .array(historyMessageSchema)\n .optional()\n .describe('Prior turns to replay first. Max 20 messages.'),\n },\n async handler({ dataset_id, ...body }, { client, config }) {\n const result = await client.post<{ id: string }>(`/datasets/${dataset_id}/examples`, body);\n return okResult(`Added example ${result.id}.`, result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'run_experiment',\n title: 'Create and start an experiment run',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Create an experiment over a dataset and immediately start a run of it. The grid ' +\n 'is every (version x model) pair you list. When `prompt` is given, a baseline cell ' +\n 'for its production alias is added automatically unless that version is already in ' +\n 'the grid. Returns as soon as the run is queued — the worker executes it ' +\n 'asynchronously, so poll get_experiment_run for results. Note the judge model ' +\n '(gpt-4o-mini by default) must itself be registered in the gateway or every score ' +\n 'fails.',\n inputSchema: {\n dataset_id: z.string().uuid().describe('Dataset to evaluate against.'),\n version_ids: z\n .array(z.string().uuid())\n .min(1)\n .describe('Prompt-version UUIDs to sweep. At least one.'),\n models: z.array(z.string().min(1)).min(1).describe('Gateway model public names to sweep.'),\n prompt: z\n .string()\n .optional()\n .describe('Prompt name or UUID under test — enables the automatic baseline cell.'),\n name: z.string().optional().describe('Experiment name, for the run history.'),\n alias: z\n .string()\n .optional()\n .describe('Which alias the automatic baseline points at. Default \"production\".'),\n },\n async handler(args, { client, config }) {\n const body: Record<string, unknown> = {\n dataset_id: args.dataset_id,\n version_ids: args.version_ids,\n models: args.models,\n };\n if (args.name !== undefined) body.name = args.name;\n if (args.alias !== undefined) body.alias = args.alias;\n if (args.prompt !== undefined) body.prompt_id = await resolvePromptRef(client, args.prompt);\n\n const experiment = await client.post<{ id: string; promptMismatchWarning?: string }>(\n '/experiments',\n body,\n );\n const run = await client.post<{ run_id: string; status: string }>(\n `/experiments/${experiment.id}/runs`,\n );\n\n const warning = experiment.promptMismatchWarning\n ? ` Warning: ${experiment.promptMismatchWarning}`\n : '';\n return okResult(\n `Experiment ${experiment.id} created and run ${run.run_id} is ${run.status}. ` +\n `Results arrive asynchronously — poll get_experiment_run.${warning}`,\n { experiment, run },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_experiment_runs',\n title: 'List evaluation runs',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'The run history, newest first. Each row carries the dataset and prompt evaluated, ' +\n 'the grid shape, and the scores — avgScore, passRate and topVariantLabel are null ' +\n 'rather than 0 until at least one result has been judged, so an unscored run is ' +\n 'never mistaken for one that scored badly. `kind` is \"optimize\" for optimizer ' +\n 'sweeps and \"evaluation\" otherwise.',\n inputSchema: {\n status: z\n .enum(['queued', 'running', 'succeeded', 'failed'])\n .optional()\n .describe('Lifecycle filter.'),\n dataset_id: z.string().uuid().optional().describe('Only runs over this dataset.'),\n prompt_id: z.string().uuid().optional().describe('Only runs whose experiment named this prompt.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Rows per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/runs', args);\n return okResult(listSummary('runs', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_experiment_run',\n title: 'Get a run, optionally with its comparison report',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'Read one run\\'s status and results. With include_report=true it also fetches the ' +\n 'comparison report: the full (variant x model) matrix with per-cell averages, each ' +\n 'cell\\'s delta against the same-model production baseline, a leaderboard and an ' +\n 'advisory winner. Ask for the report only once the run has succeeded — an ' +\n 'in-flight run has nothing to compare.',\n inputSchema: {\n run_id: z.string().uuid().describe('Run UUID.'),\n include_report: z.boolean().optional().describe('Also fetch the comparison report.'),\n },\n async handler({ run_id, include_report }, { client, config }) {\n const run = await client.get<{ status?: string; results?: unknown[] }>(`/runs/${run_id}`);\n let report: unknown = undefined;\n if (include_report) {\n report = await client.get(`/runs/${run_id}/report`);\n }\n return okResult(\n `Run ${run_id} is ${run.status} with ${run.results?.length ?? 0} result(s).`,\n { run, report },\n config.maxTextBytes,\n );\n },\n }),\n];\n","import { z } from 'zod';\nimport { okResult } from '../format';\nimport { resolvePromptIdAndName } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** OpenAI-shaped chat message accepted by the raw completion tool. */\nconst chatMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant', 'tool']).describe('Message role.'),\n content: z.string().describe('Message content.'),\n});\n\n/** Headers the gateway sets on every completion, worth surfacing back to the model. */\nconst GATEWAY_HEADERS = [\n 'x-gateway-request-id',\n 'x-gateway-provider',\n 'x-gateway-model',\n 'x-gateway-cost-usd',\n 'x-gateway-cache',\n 'x-gateway-trace-id',\n 'x-gateway-span-id',\n] as const;\n\n/**\n * Pulls the `x-gateway-*` metadata off a completion response.\n *\n * These are not decoration: `x-gateway-trace-id` is how the caller finds the completion\n * again in the trace explorer, and `x-gateway-cost-usd` is the only place the price of\n * the call appears. Both would be lost if only the body were returned.\n *\n * @param headers - Response headers from the gateway.\n * @returns Present headers, keyed without the `x-gateway-` prefix.\n */\nfunction gatewayMeta(headers: Headers): Record<string, string> {\n const meta: Record<string, string> = {};\n for (const name of GATEWAY_HEADERS) {\n const value = headers.get(name);\n if (value !== null && value !== '') meta[name.replace('x-gateway-', '')] = value;\n }\n return meta;\n}\n\n/** First choice's text, for the human-readable summary line. */\nfunction firstChoiceText(body: unknown): string {\n const choice = (body as { choices?: Array<{ message?: { content?: string | null } }> })?.choices?.[0];\n const content = choice?.message?.content;\n if (typeof content === 'string' && content.trim() !== '') return content.trim();\n return '(no text content — check tool_calls)';\n}\n\n/**\n * Tools that actually run models: the stored-prompt path, the raw path, the model\n * registry and spend.\n *\n * `run_prompt` is the one that matters. It is the whole platform in a single call —\n * registry render, alias resolution, bound tools, provider routing, pricing and tracing —\n * and it is what makes an MCP client able to *try* a prompt rather than only read it.\n */\nexport const gatewayTools: AnyToolDefinition[] = [\n defineTool({\n name: 'run_prompt',\n title: 'Run a stored prompt through the gateway',\n toolset: 'gateway',\n readOnlyHint: false,\n description:\n 'Render a stored prompt at an alias and send it to the model in one call. The ' +\n 'gateway resolves the alias, substitutes the variables, attaches the tools bound ' +\n 'to that alias, routes to the provider, prices the call and records a trace. ' +\n 'Omit `model` to use the version\\'s bound default model. Returns the completion ' +\n 'plus the trace id, so the run can be inspected afterwards with get_trace. ' +\n 'This is the tool for \"test this prompt\" or \"what does this prompt answer for X\".',\n inputSchema: {\n prompt: z.string().min(1).describe('Prompt name or UUID.'),\n alias: z.string().optional().describe('Alias to resolve. Default \"production\".'),\n variables: z.record(z.unknown()).optional().describe('Template variables for the render.'),\n model: z\n .string()\n .optional()\n .describe('Gateway model public name. Omit to use the version\\'s bound default model.'),\n max_tokens: z.number().int().positive().optional().describe('Cap on generated tokens.'),\n temperature: z.number().min(0).max(2).optional().describe('Sampling temperature.'),\n trace_name: z\n .string()\n .optional()\n .describe('Name to give the trace, so this run is findable later.'),\n },\n async handler(args, { client, config }) {\n const { name } = await resolvePromptIdAndName(client, args.prompt);\n const body: Record<string, unknown> = {\n prompt: {\n name,\n alias: args.alias ?? 'production',\n variables: args.variables ?? {},\n },\n };\n if (args.model !== undefined) body.model = args.model;\n if (args.max_tokens !== undefined) body.max_tokens = args.max_tokens;\n if (args.temperature !== undefined) body.temperature = args.temperature;\n\n const headers: Record<string, string> = {};\n if (args.trace_name !== undefined) {\n // Free-text headers must be percent-encoded — a raw non-ASCII value is rejected\n // by fetch before the request leaves the process. The server decodes it back.\n headers['x-trace-name'] = encodeURIComponent(args.trace_name);\n }\n\n const response = await client.requestRaw<unknown>('POST', '/gateway/chat/completions', {\n body,\n headers,\n });\n const meta = gatewayMeta(response.headers);\n return okResult(\n `Ran \"${name}\"@${args.alias ?? 'production'} on ${meta.model ?? 'the resolved model'}` +\n `${meta['cost-usd'] ? ` for $${meta['cost-usd']}` : ''}. Reply: ${firstChoiceText(\n response.data,\n ).slice(0, 400)}`,\n { completion: response.data, gateway: meta },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'chat_completion',\n title: 'Run a raw chat completion through the gateway',\n toolset: 'gateway',\n readOnlyHint: false,\n description:\n 'Send your own messages through the AcruxCore gateway — OpenAI-compatible, but ' +\n 'routed by the team\\'s provider connections, priced, budget-checked and traced. ' +\n 'Prefer run_prompt when the prompt already exists in the registry; use this for ' +\n 'a one-off. Streaming is not available over MCP: the reply comes back whole.',\n inputSchema: {\n model: z.string().min(1).describe('Gateway model public name, e.g. \"gpt-4o-mini\".'),\n messages: z.array(chatMessageSchema).min(1).describe('Chat messages, in order.'),\n max_tokens: z.number().int().positive().optional().describe('Cap on generated tokens.'),\n temperature: z.number().min(0).max(2).optional().describe('Sampling temperature.'),\n tool_refs: z\n .array(\n z.object({\n name: z.string().describe('Catalog tool name.'),\n alias: z.string().optional().describe('Tool alias. Default \"production\".'),\n version: z.number().int().positive().optional().describe('Pin an exact version instead.'),\n }),\n )\n .optional()\n .describe(\n 'Catalog tools to attach by name. Give an alias OR a version on a ref, never both.',\n ),\n trace_name: z.string().optional().describe('Name to give the trace.'),\n },\n async handler(args, { client, config }) {\n const body: Record<string, unknown> = { model: args.model, messages: args.messages };\n if (args.max_tokens !== undefined) body.max_tokens = args.max_tokens;\n if (args.temperature !== undefined) body.temperature = args.temperature;\n if (args.tool_refs !== undefined) body.tool_refs = args.tool_refs;\n\n const headers: Record<string, string> = {};\n if (args.trace_name !== undefined) headers['x-trace-name'] = encodeURIComponent(args.trace_name);\n\n const response = await client.requestRaw<unknown>('POST', '/gateway/chat/completions', {\n body,\n headers,\n });\n const meta = gatewayMeta(response.headers);\n return okResult(\n `Completion from ${meta.model ?? args.model}` +\n `${meta['cost-usd'] ? ` ($${meta['cost-usd']})` : ''}: ${firstChoiceText(\n response.data,\n ).slice(0, 400)}`,\n { completion: response.data, gateway: meta },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_models',\n title: 'List gateway models',\n toolset: 'gateway',\n readOnlyHint: true,\n description:\n 'List the models registered for this team, with the provider connection each one ' +\n 'routes to. Only these public names are valid in run_prompt, chat_completion, or a ' +\n 'version\\'s bound default model.',\n inputSchema: {},\n async handler(_args, { client, config }) {\n const models = await client.get<unknown>('/gateway/models');\n const count = Array.isArray(models)\n ? models.length\n : ((models as { data?: unknown[] })?.data?.length ?? 0);\n return okResult(`${count} registered model(s).`, models, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_gateway_usage',\n title: 'Get gateway usage and spend',\n toolset: 'gateway',\n readOnlyHint: true,\n description:\n 'Request counts, token counts, cost, cache-hit rate and error rate over a window, ' +\n 'bucketed by day, model, provider or virtual key. Defaults to the last 30 days. ' +\n 'Use this for \"what did we spend\" and \"which model costs the most\" questions.',\n inputSchema: {\n from: z.string().optional().describe('ISO date, inclusive start of the window.'),\n to: z.string().optional().describe('ISO date, exclusive end of the window.'),\n group_by: z\n .enum(['day', 'model', 'virtual_key', 'provider'])\n .optional()\n .describe('Bucket dimension. Default \"day\".'),\n virtual_key_id: z.string().uuid().optional().describe('Restrict to one virtual key.'),\n },\n async handler({ from, to, group_by, virtual_key_id }, { client, config }) {\n const usage = await client.get<{\n totals?: { requests?: number; costUsd?: number };\n buckets?: unknown[];\n }>('/gateway/usage', { from, to, group_by, virtual_key_id });\n const totals = usage.totals ?? {};\n return okResult(\n `${totals.requests ?? 0} request(s), $${totals.costUsd ?? 0} total, in ${\n usage.buckets?.length ?? 0\n } bucket(s).`,\n usage,\n config.maxTextBytes,\n );\n },\n }),\n];\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { resolvePromptIdAndName, resolvePromptRef } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A chat message as stored in a prompt version's template. */\nconst messageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant']).describe('Message role.'),\n content: z.string().describe('Template text. Jinja2/nunjucks syntax: {{ variable }}.'),\n});\n\n/** A prompt reference accepted by every tool here. */\nconst promptRef = z\n .string()\n .min(1)\n .describe('Prompt name (e.g. \"customer-support\") or prompt UUID. Names are resolved for you.');\n\n/**\n * Tools for the prompt registry: browse, read, render, and move versions between aliases.\n *\n * The mental model these descriptions have to convey, because a model that misses it\n * calls the wrong tool: a **prompt** is a named container, a **version** is an immutable\n * commit of its messages, and an **alias** (`production`, `staging`, anything else) is a\n * moving pointer at one version. Committing never moves an alias; promoting is what\n * ships a change.\n */\nexport const promptTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_prompts',\n title: 'List prompts',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'List the prompts in the AcruxCore team, newest first. Use `search` to filter by ' +\n 'name or description substring. Returns the prompt id, name and description — ' +\n 'call get_prompt for versions and aliases.',\n inputSchema: {\n search: z.string().optional().describe('Substring filter over name and description.'),\n page: z.number().int().positive().optional().describe('1-based page number. Default 1.'),\n limit: z\n .number()\n .int()\n .positive()\n .max(100)\n .optional()\n .describe('Results per page, max 100. Default 20.'),\n },\n async handler({ search, page, limit }, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/prompts', {\n search,\n page,\n limit,\n });\n return okResult(listSummary('prompts', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_prompt',\n title: 'Get a prompt with its versions and aliases',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Read one prompt in full: its metadata, every committed version (number, template ' +\n 'variables, bound default model) and every alias with the version it points at. ' +\n 'This is the tool to call before committing or promoting, because it shows which ' +\n 'version each alias is currently serving.',\n inputSchema: {\n prompt: promptRef,\n include_messages: z\n .boolean()\n .optional()\n .describe(\n 'Also fetch the full message template of the newest version. Off by default ' +\n 'because templates can be long.',\n ),\n },\n async handler({ prompt, include_messages }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n\n // Three calls, one tool: \"show me this prompt\" is a single intention, and making\n // the model chain /prompts, /versions and /aliases itself is three chances to stop\n // after the first one and answer from incomplete data.\n const [detail, versions, aliases] = await Promise.all([\n client.get<Record<string, unknown>>(`/prompts/${id}`),\n client.get<{ data?: Array<{ versionNumber: number }> }>(`/prompts/${id}/versions`, {\n limit: 100,\n }),\n client.get<unknown[]>(`/prompts/${id}/aliases`),\n ]);\n\n let latestVersion: unknown = undefined;\n const newest = versions.data?.[0]?.versionNumber;\n if (include_messages && newest !== undefined) {\n latestVersion = await client.get(`/prompts/${id}/versions/${newest}`);\n }\n\n const aliasSummary = Array.isArray(aliases)\n ? aliases\n .map((a) => {\n const row = a as { alias?: string; versionNumber?: number };\n return `${row.alias}→v${row.versionNumber}`;\n })\n .join(', ')\n : '';\n\n return okResult(\n `Prompt \"${detail.name}\" — ${versions.data?.length ?? 0} version(s); aliases: ${\n aliasSummary || 'none'\n }.`,\n { prompt: detail, versions: versions.data ?? [], aliases, latestVersion },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'render_prompt',\n title: 'Render a prompt at an alias',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Render the version an alias currently points at, substituting template variables, ' +\n 'and return the finished messages plus the tool definitions bound to that alias. ' +\n 'This renders only — it calls no model. Use run_prompt to render and get a ' +\n 'completion in one step. Missing required variables come back as a ' +\n 'MISSING_VARIABLES error naming each one.',\n inputSchema: {\n prompt: promptRef,\n alias: z\n .string()\n .optional()\n .describe('Alias to resolve. Default \"production\".'),\n variables: z\n .record(z.unknown())\n .optional()\n .describe('Template variables, e.g. {\"name\":\"Alice\"}. Required ones come from the version.'),\n },\n async handler({ prompt, alias, variables }, { client, config }) {\n const { name } = await resolvePromptIdAndName(client, prompt);\n const resolvedAlias = alias ?? 'production';\n const rendered = await client.post<{\n messages?: unknown[];\n tools?: unknown[];\n versionNumber?: number;\n }>(`/prompts/${encodeURIComponent(name)}/${encodeURIComponent(resolvedAlias)}/render`, {\n variables: variables ?? {},\n });\n return okResult(\n `Rendered \"${name}\" at alias \"${resolvedAlias}\" (version ${rendered.versionNumber}): ` +\n `${rendered.messages?.length ?? 0} message(s), ${rendered.tools?.length ?? 0} bound tool(s).`,\n rendered,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'diff_prompt_versions',\n title: 'Diff two prompt versions',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Return a unified diff between two committed versions of a prompt. The diff is ' +\n 'over the raw templates, not rendered output, so variable placeholders stay visible.',\n inputSchema: {\n prompt: promptRef,\n from_version: z.number().int().positive().describe('Version number to diff from.'),\n to_version: z.number().int().positive().describe('Version number to diff to.'),\n },\n async handler({ prompt, from_version, to_version }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const result = await client.get<{ diff?: string }>(`/prompts/${id}/versions/diff`, {\n from: from_version,\n to: to_version,\n });\n // A unified diff with no `@@` hunk means the message text is the same — the usual\n // cause is a commit that changed only the bound model. Say so, or an empty body\n // reads as a failed call.\n const identical = !(result.diff ?? '').includes('@@');\n return okResult(\n identical\n ? `The messages of v${from_version} and v${to_version} are identical. ` +\n 'The diff covers message text only; compare the bound models and settings ' +\n 'with get_prompt.'\n : `Diff of v${from_version} → v${to_version}.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'create_prompt',\n title: 'Create a prompt',\n toolset: 'prompts',\n readOnlyHint: false,\n description:\n 'Create an empty prompt container. It has no messages yet — the messages live in ' +\n 'versions, so follow this with commit_prompt_version. Fails with TOOL_NAME_TAKEN ' +\n 'style 409 semantics if the name is already used in the team.',\n inputSchema: {\n name: z\n .string()\n .min(1)\n .describe('Prompt name, used to reference it everywhere. Slug-like, e.g. \"customer-support\".'),\n description: z.string().optional().describe('What this prompt is for.'),\n },\n async handler({ name, description }, { client, config }) {\n const created = await client.post<{ id: string; name: string }>('/prompts', {\n name,\n description,\n });\n return okResult(\n `Created prompt \"${created.name}\" (${created.id}). It has no versions yet — ` +\n 'commit one with commit_prompt_version.',\n created,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'commit_prompt_version',\n title: 'Commit a prompt version',\n toolset: 'prompts',\n readOnlyHint: false,\n description:\n 'Commit a new immutable version of a prompt. Version numbers are sequential per ' +\n 'prompt. The FIRST commit auto-creates the \"production\" and \"staging\" aliases ' +\n 'pointing at v1; every later commit changes no alias at all, so nothing goes live ' +\n 'until you call promote_prompt_alias. Template variables are extracted from the ' +\n '{{ }} placeholders automatically.',\n inputSchema: {\n prompt: promptRef,\n messages: z\n .array(messageSchema)\n .min(1)\n .describe('The message template, in order. Use {{ variable }} for substitutions.'),\n model: z\n .string()\n .optional()\n .describe(\n 'Optional default gateway model for this version, by public name (e.g. ' +\n '\"gpt-4o-mini\"). Must already be registered for the team.',\n ),\n },\n async handler({ prompt, messages, model }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const version = await client.post<{\n versionNumber: number;\n variables?: string[];\n aliases?: unknown[];\n }>(`/prompts/${id}/versions`, { messages, model });\n const aliasNote = version.aliases\n ? ' Aliases production and staging were created pointing at it.'\n : ' No alias moved — promote it when you want it live.';\n return okResult(\n `Committed version ${version.versionNumber} with variables [${(version.variables ?? []).join(\n ', ',\n )}].${aliasNote}`,\n version,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'promote_prompt_alias',\n title: 'Promote an alias to a version',\n toolset: 'prompts',\n readOnlyHint: false,\n destructiveHint: true,\n description:\n 'Point an alias at a specific version number, creating the alias if it does not ' +\n 'exist. This is how a change ships, and how a rollback happens — promoting an ' +\n 'earlier version number rolls back. Promoting \"production\" changes what live ' +\n 'traffic renders immediately.',\n inputSchema: {\n prompt: promptRef,\n alias: z\n .string()\n .min(1)\n .describe('Alias to move, e.g. \"production\", \"staging\", \"canary\".'),\n version_number: z.number().int().positive().describe('Version number to point at.'),\n },\n async handler({ prompt, alias, version_number }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const result = await client.post<Record<string, unknown>>(\n `/prompts/${id}/aliases/${encodeURIComponent(alias)}/promote`,\n { version_number },\n );\n return okResult(\n `Alias \"${alias}\" now points at version ${version_number}.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n];\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A span as returned inside a trace tree, with its children. */\ninterface SpanNode {\n payload?: unknown;\n children?: SpanNode[];\n [key: string]: unknown;\n}\n\n/**\n * Removes captured input/output payloads from a span tree, in place on a copy.\n *\n * Payload capture is on by default for new teams, and a single LLM span can carry the\n * whole conversation. Reading one trace should not be able to spend a client's entire\n * context budget by accident, so the caller can ask for the shape without the contents.\n *\n * @param spans - Span tree from `GET /traces/:id`.\n * @returns A copy with every `payload` replaced by a marker.\n */\nfunction stripPayloads(spans: SpanNode[]): SpanNode[] {\n return spans.map((span) => {\n const copy: SpanNode = { ...span };\n if (copy.payload !== undefined && copy.payload !== null) {\n copy.payload = '[omitted — call get_trace with include_payloads=true]';\n }\n if (Array.isArray(copy.children)) copy.children = stripPayloads(copy.children);\n return copy;\n });\n}\n\n/**\n * Tools for observability: find runs, read one, aggregate them, and attach feedback.\n *\n * A trace is one request end to end; a span is one step inside it (`llm`, `tool`,\n * `retrieval`, …); a session groups traces belonging to one conversation. Those three\n * words appear in every description because picking the wrong level is the usual failure\n * — \"why was yesterday slow\" is `get_trace_analytics`, not a hundred `get_trace` calls.\n */\nexport const traceTools: AnyToolDefinition[] = [\n defineTool({\n name: 'search_traces',\n title: 'Search traces',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Find traces — one row per request — newest first, with cost, token count, span ' +\n 'count and duration. Filter by status, model, session, prompt version, free text, ' +\n 'or minimum latency/cost/tokens. The default window is the last 30 days. Use this ' +\n 'to locate a run, then get_trace to open it.',\n inputSchema: {\n q: z.string().optional().describe('Free text over trace/span names and span attributes.'),\n status: z.enum(['ok', 'error', 'unset']).optional().describe('Trace status filter.'),\n model: z.string().optional().describe('Exact model name on any span in the trace.'),\n session_id: z.string().optional().describe('Restrict to one session.'),\n prompt_version_id: z.string().uuid().optional().describe('Traces attributed to one prompt version.'),\n from: z.string().optional().describe('ISO 8601 start of the window.'),\n to: z.string().optional().describe('ISO 8601 end of the window.'),\n min_latency_ms: z.number().int().positive().optional().describe('Inclusive lower bound.'),\n min_cost_usd: z.number().positive().optional().describe('Inclusive lower bound.'),\n min_tokens: z.number().int().positive().optional().describe('Inclusive lower bound.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/traces', {\n q: args.q,\n status: args.status,\n model: args.model,\n session_id: args.session_id,\n prompt_version_id: args.prompt_version_id,\n from: args.from,\n to: args.to,\n min_latency_ms: args.min_latency_ms,\n min_cost_usd: args.min_cost_usd,\n min_tokens: args.min_tokens,\n page: args.page,\n limit: args.limit,\n });\n return okResult(listSummary('traces', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_trace',\n title: 'Get one trace with its span tree',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Open one trace: the header plus every span assembled into a parent/child tree, ' +\n 'each with its model, tokens, cost, latency, error message and — when the team ' +\n 'captures payloads — the input and output. Set include_payloads=false when the ' +\n 'trace is large and you only need its shape and timings.',\n inputSchema: {\n trace_id: z.string().uuid().describe('Trace UUID, from search_traces or a gateway call.'),\n include_payloads: z\n .boolean()\n .optional()\n .describe('Include captured span input/output. Default true.'),\n },\n async handler({ trace_id, include_payloads }, { client, config }) {\n const result = await client.get<{ trace?: Record<string, unknown>; spans?: SpanNode[] }>(\n `/traces/${trace_id}`,\n );\n const spans = include_payloads === false ? stripPayloads(result.spans ?? []) : result.spans;\n const header = result.trace ?? {};\n return okResult(\n `Trace \"${header.name}\" — status ${header.status}, ${header.spanCount} span(s), ` +\n `${header.totalTokens ?? 0} tokens, $${header.totalCostUsd ?? 0}.`,\n { trace: header, spans },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'get_trace_analytics',\n title: 'Aggregate trace metrics',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Aggregate span metrics over a window: request count, error rate, tokens, cost and ' +\n 'p50/p95/p99 latency, bucketed by day, model, session or prompt version. Default ' +\n 'window is the last 30 days. This is the tool for \"did latency regress\", \"which ' +\n 'model errors most\", \"what does this prompt version cost\".',\n inputSchema: {\n from: z.string().optional().describe('ISO date, start of the window.'),\n to: z.string().optional().describe('ISO date, end of the window.'),\n group_by: z\n .enum(['day', 'model', 'session', 'prompt_version'])\n .optional()\n .describe('Bucket dimension. Default \"day\".'),\n kind: z\n .enum(['llm', 'tool', 'retrieval', 'embedding', 'agent', 'chain', 'other'])\n .optional()\n .describe('Restrict to one span kind.'),\n model: z.string().optional().describe('Restrict to one exact model.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{\n totals?: { requests?: number; errorRate?: number; costUsd?: number };\n buckets?: unknown[];\n }>('/traces/analytics', args);\n const totals = result.totals ?? {};\n return okResult(\n `${totals.requests ?? 0} span(s), error rate ${totals.errorRate ?? 0}, $${\n totals.costUsd ?? 0\n }, in ${result.buckets?.length ?? 0} bucket(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_sessions',\n title: 'List sessions',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'List sessions — groups of traces belonging to one conversation — with the most ' +\n 'recent activity first. Default window is the last 30 days.',\n inputSchema: {\n q: z.string().optional().describe('Case-insensitive substring match on the session id.'),\n from: z.string().optional().describe('ISO 8601 start of the window.'),\n to: z.string().optional().describe('ISO 8601 end of the window.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/sessions', args);\n return okResult(listSummary('sessions', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_session',\n title: 'Get one session',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'One session\\'s summary plus its traces, newest first, capped at 100. Not date ' +\n 'filtered — the lookup is by session id alone.',\n inputSchema: {\n session_id: z.string().min(1).describe('The session id as your application set it.'),\n },\n async handler({ session_id }, { client, config }) {\n const result = await client.get<{ traces?: unknown[] }>(\n `/sessions/${encodeURIComponent(session_id)}`,\n );\n return okResult(\n `Session \"${session_id}\" — ${result.traces?.length ?? 0} trace(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'submit_trace_feedback',\n title: 'Attach feedback to a trace',\n toolset: 'traces',\n readOnlyHint: false,\n description:\n 'Record a rating, label and/or comment against a trace, or against one span inside ' +\n 'it. At least one of rating, label or comment is required. Feedback is what later ' +\n 'becomes an evaluation dataset via the \"from feedback\" path, so a clear label is ' +\n 'worth more than a bare rating.',\n inputSchema: {\n trace_id: z.string().uuid().describe('Trace UUID.'),\n rating: z.number().int().min(-1).max(5).optional().describe('Integer rating, -1 to 5.'),\n label: z.string().max(200).optional().describe('Short label, e.g. \"wrong_answer\".'),\n comment: z.string().max(5000).optional().describe('Free-text detail.'),\n span_id: z.string().optional().describe('Span reference, for span-level feedback.'),\n source: z\n .enum(['user', 'developer', 'end_user', 'api'])\n .optional()\n .describe('Who the feedback came from. Default \"user\".'),\n },\n async handler({ trace_id, span_id, ...rest }, { client, config }) {\n const body: Record<string, unknown> = { ...rest };\n if (span_id !== undefined) body.spanId = span_id;\n const result = await client.post<{ id?: string }>(`/traces/${trace_id}/feedback`, body);\n return okResult(`Feedback recorded on trace ${trace_id}.`, result, config.maxTextBytes);\n },\n }),\n];\n","import type { McpServerConfig } from '../config';\nimport { catalogTools } from './catalog';\nimport { evaluationTools } from './evaluations';\nimport { gatewayTools } from './gateway';\nimport { promptTools } from './prompts';\nimport { traceTools } from './traces';\nimport type { AnyToolDefinition } from './types';\n\nexport type { AnyToolDefinition, ToolContext } from './types';\nexport { defineTool } from './types';\n\n/**\n * Every tool this server can register, in the order toolsets appear to a client.\n *\n * Order is deliberate rather than alphabetical: prompts first because that is the\n * product's centre of gravity, then the things that run (gateway, tools), then the\n * things that observe (traces, evaluations).\n */\nexport const ALL_TOOLS: AnyToolDefinition[] = [\n ...promptTools,\n ...gatewayTools,\n ...catalogTools,\n ...traceTools,\n ...evaluationTools,\n];\n\n/**\n * Selects the tools a given configuration should expose.\n *\n * Read-only mode *removes* mutating tools rather than refusing them at call time. A tool\n * that is absent from `tools/list` cannot be chosen by mistake, cannot be argued with,\n * and does not need the model to have read a warning in its description — which is the\n * whole point of handing an agent a read-only key in the first place.\n *\n * @param config - Resolved server configuration.\n * @returns The tools to register, in {@link ALL_TOOLS} order.\n */\nexport function selectTools(config: McpServerConfig): AnyToolDefinition[] {\n return ALL_TOOLS.filter(\n (tool) =>\n config.toolsets.includes(tool.toolset) && (!config.readOnly || tool.readOnlyHint),\n );\n}\n","import { McpConfigError } from './errors';\n\n/** Every toolset this server can expose. */\nexport const ALL_TOOLSETS = ['prompts', 'gateway', 'tools', 'traces', 'evaluations'] as const;\n\n/** One of the five toolset names. */\nexport type Toolset = (typeof ALL_TOOLSETS)[number];\n\n/** The AcruxCore cloud API. Overridden with `ACRUXCORE_BASE_URL` when self-hosting. */\nexport const DEFAULT_BASE_URL = 'https://api.acruxcore.com/api/v1';\n\n/** Alias the prompts primitive exposes when none is configured. */\nexport const DEFAULT_PROMPT_ALIAS = 'production';\n\n/**\n * Cap on the bytes of text any single tool result may contain.\n *\n * 40 000 is roughly 10k tokens — large enough for a page of traces or a full prompt\n * version, small enough that one careless `get_trace` on a payload-heavy trace cannot\n * eat a client's whole context window.\n */\nexport const DEFAULT_MAX_TEXT_BYTES = 40_000;\n\n/** Fully resolved server configuration. */\nexport interface McpServerConfig {\n /** AcruxCore base URL, normalised to end in `/api/v1`. */\n baseUrl: string;\n /** `acx_sk_…` API key used for every call. */\n apiKey: string;\n /** Toolsets to register, in `ALL_TOOLSETS` order. */\n toolsets: Toolset[];\n /** When true, mutating tools are never registered at all. */\n readOnly: boolean;\n /** Alias the MCP prompts primitive resolves registry prompts through. */\n promptAlias: string;\n /** Per-result text cap, in bytes. */\n maxTextBytes: number;\n /** Per-request HTTP timeout, in milliseconds. */\n timeoutMs: number;\n}\n\n/** Raw inputs to {@link resolveConfig}, so it can be unit-tested without touching `process`. */\nexport interface ConfigSources {\n env: Record<string, string | undefined>;\n argv: string[];\n}\n\n/**\n * Resolves the server configuration from environment variables, then CLI flags.\n *\n * CLI wins over env on purpose: the env is usually the MCP client's global config, and a\n * flag is what the user typed for *this* server entry.\n *\n * Recognised flags: `--base-url`, `--api-key`, `--toolsets`, `--read-only`,\n * `--prompt-alias`, `--max-text-bytes`, `--timeout-ms`.\n *\n * @param sources - Environment and argv (argv without the node/script prefix).\n * @returns The resolved configuration.\n * @throws {McpConfigError} If the API key is absent, a toolset name is unknown, or a\n * numeric flag is not a positive number.\n */\nexport function resolveConfig(sources: ConfigSources): McpServerConfig {\n const { env } = sources;\n const flags = parseFlags(sources.argv);\n\n const apiKey = (flags['api-key'] ?? env.ACRUXCORE_API_KEY ?? '').trim();\n if (!apiKey) {\n throw new McpConfigError(\n 'No AcruxCore API key. Set ACRUXCORE_API_KEY (or pass --api-key). ' +\n 'Create one in the dashboard under Settings → API keys.',\n );\n }\n\n const baseUrl = (flags['base-url'] ?? env.ACRUXCORE_BASE_URL ?? DEFAULT_BASE_URL).trim();\n\n const toolsetsRaw = (flags.toolsets ?? env.ACRUXCORE_MCP_TOOLSETS ?? '').trim();\n const toolsets = parseToolsets(toolsetsRaw);\n\n const readOnly = parseBoolean(flags['read-only'] ?? env.ACRUXCORE_MCP_READ_ONLY);\n\n const promptAlias =\n (flags['prompt-alias'] ?? env.ACRUXCORE_MCP_PROMPT_ALIAS ?? DEFAULT_PROMPT_ALIAS).trim() ||\n DEFAULT_PROMPT_ALIAS;\n\n const maxTextBytes = parsePositiveInt(\n flags['max-text-bytes'] ?? env.ACRUXCORE_MCP_MAX_TEXT_BYTES,\n DEFAULT_MAX_TEXT_BYTES,\n 'max-text-bytes',\n );\n\n const timeoutMs = parsePositiveInt(\n flags['timeout-ms'] ?? env.ACRUXCORE_MCP_TIMEOUT_MS,\n 60_000,\n 'timeout-ms',\n );\n\n return { baseUrl, apiKey, toolsets, readOnly, promptAlias, maxTextBytes, timeoutMs };\n}\n\n/**\n * Parses `--flag value` and `--flag=value` pairs out of argv.\n *\n * A flag with no value (`--read-only`) maps to `\"true\"`, which is what\n * {@link parseBoolean} expects, so boolean flags need no special case at the call site.\n *\n * @param argv - Arguments after the script name.\n * @returns Flag name (without `--`) to string value.\n */\nfunction parseFlags(argv: string[]): Record<string, string | undefined> {\n const out: Record<string, string | undefined> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (!arg.startsWith('--')) continue;\n\n const eq = arg.indexOf('=');\n if (eq !== -1) {\n out[arg.slice(2, eq)] = arg.slice(eq + 1);\n continue;\n }\n\n const name = arg.slice(2);\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('--')) {\n out[name] = next;\n i++;\n } else {\n out[name] = 'true';\n }\n }\n return out;\n}\n\n/**\n * Turns a comma-separated toolset list into a validated, de-duplicated array.\n *\n * An empty value means \"all of them\" — the useful default for someone who has just\n * installed the server and does not yet know what the toolsets are.\n *\n * @param raw - Comma-separated names, `all`, or empty.\n * @returns Toolsets in `ALL_TOOLSETS` order.\n * @throws {McpConfigError} If any name is not a known toolset.\n */\nexport function parseToolsets(raw: string): Toolset[] {\n if (!raw || raw.toLowerCase() === 'all') return [...ALL_TOOLSETS];\n\n const requested = raw\n .split(',')\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean);\n\n const unknown = requested.filter((name) => !ALL_TOOLSETS.includes(name as Toolset));\n if (unknown.length > 0) {\n throw new McpConfigError(\n `Unknown toolset(s): ${unknown.join(', ')}. Valid toolsets: ${ALL_TOOLSETS.join(', ')}.`,\n );\n }\n\n // Returned in ALL_TOOLSETS order rather than request order so `tools/list` is stable\n // no matter how the user happened to type the flag.\n return ALL_TOOLSETS.filter((name) => requested.includes(name));\n}\n\n/**\n * Reads a boolean from a flag or env value.\n *\n * @param value - Raw string, possibly undefined.\n * @returns True for `true`, `1`, `yes` and `on` (case-insensitive); false otherwise.\n */\nfunction parseBoolean(value: string | undefined): boolean {\n if (value === undefined) return false;\n return ['true', '1', 'yes', 'on'].includes(value.trim().toLowerCase());\n}\n\n/**\n * Reads a positive integer, falling back to a default when unset.\n *\n * @param value - Raw string, possibly undefined.\n * @param fallback - Value to use when unset or empty.\n * @param name - Flag name, used in the error message.\n * @returns The parsed integer.\n * @throws {McpConfigError} If the value is present but not a positive integer.\n */\nfunction parsePositiveInt(value: string | undefined, fallback: number, name: string): number {\n if (value === undefined || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new McpConfigError(`--${name} must be a positive integer, got \"${value}\".`);\n }\n return parsed;\n}\n"],"mappings":"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","names":["import_mcp","message","import_zod","import_zod","import_zod","import_zod"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/errors.ts","../src/client.ts","../src/format.ts","../src/registry-prompts.ts","../src/resources.ts","../src/toolsets/catalog.ts","../src/refs.ts","../src/toolsets/types.ts","../src/toolsets/evaluations.ts","../src/optimize-report.ts","../src/toolsets/gateway.ts","../src/toolsets/prompts.ts","../src/toolsets/traces.ts","../src/toolsets/index.ts","../src/config.ts"],"sourcesContent":["export { createAcruxCoreMcpServer, SERVER_VERSION, type BuiltServer } from './server';\nexport {\n resolveConfig,\n parseToolsets,\n ALL_TOOLSETS,\n DEFAULT_BASE_URL,\n DEFAULT_PROMPT_ALIAS,\n DEFAULT_MAX_TEXT_BYTES,\n type McpServerConfig,\n type Toolset,\n type ConfigSources,\n} from './config';\nexport { AcruxCoreClient, normalizeBaseUrl, type RequestOptions, type RawResponse } from './client';\nexport { AcruxCoreApiError, McpConfigError } from './errors';\nexport { ALL_TOOLS, selectTools, type AnyToolDefinition, type ToolContext } from './toolsets';\nexport { truncateText, okResult, errorResult, listSummary, type ToolResult } from './format';\nexport { isUuid, resolvePromptRef, resolveToolRef, resolvePromptIdAndName } from './refs';\nexport { toPromptMessages } from './registry-prompts';\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\nimport { errorResult } from './format';\nimport { registerRegistryPrompts } from './registry-prompts';\nimport { registerResources } from './resources';\nimport { selectTools } from './toolsets';\n\n/** Version reported to clients in `initialize`. Kept in step with package.json. */\nexport const SERVER_VERSION = '0.2.0';\n\n/** What the caller gets back, so a host can inspect what was registered. */\nexport interface BuiltServer {\n /** The configured MCP server, not yet connected to a transport. */\n server: McpServer;\n /** REST client the tools use. */\n client: AcruxCoreClient;\n /** Names of the tools that were registered, in listing order. */\n toolNames: string[];\n}\n\n/**\n * Builds the `instructions` string sent to clients on `initialize`.\n *\n * Worth writing carefully: it is the only place to explain the registry's *model* —\n * prompt, version, alias — and a client that misunderstands that will commit versions\n * and then wonder why nothing changed in production.\n *\n * It is built from the tools actually registered, because the model reads it as a list\n * of things it can do: naming `promote_prompt_alias` to a read-only client sends it\n * looking for a tool that is not there.\n *\n * @param toolNames - Names of the tools this server registered.\n * @param readOnly - Whether mutating tools were removed from the listing.\n * @returns The instructions text.\n */\nfunction buildInstructions(toolNames: ReadonlySet<string>, readOnly: boolean): string {\n const parts = [\n `AcruxCore is an LLM-ops platform: a prompt registry, a versioned tool catalog, an AI gateway, tracing, and evaluation.\n\nThree ideas explain almost every tool here:\n- A **prompt** is a named container. It holds no messages itself.\n- A **version** is an immutable commit of that prompt's messages. Version numbers are sequential.\n- An **alias** (\"production\", \"staging\", anything else) is a moving pointer at one version.`,\n ];\n\n if (toolNames.has('promote_prompt_alias')) {\n parts.push(\n 'Committing a version never moves an alias — promote_prompt_alias is what ships a change, and promoting an earlier version is how a rollback happens.',\n );\n }\n if (readOnly) {\n parts.push(\n 'This connection is read-only: it can list, read, render and diff, but it cannot create, commit, promote, run or change anything.',\n );\n }\n parts.push(\n 'Registry prompts are also exposed through MCP\\'s prompts primitive, so they can be used directly as templates. Tools that take a prompt or a catalog tool accept a name or a UUID.',\n );\n return parts.join('\\n\\n');\n}\n\n/**\n * Builds a fully configured AcruxCore MCP server.\n *\n * Transport-agnostic on purpose: the stdio binary and the API's hosted HTTP endpoint\n * both call this and then connect whatever transport they own. Adding a tool once makes\n * it appear on both.\n *\n * @param config - Resolved configuration, including the API key every call will carry.\n * @returns The server, its REST client, and the registered tool names.\n */\nexport function createAcruxCoreMcpServer(config: McpServerConfig): BuiltServer {\n const client = new AcruxCoreClient({\n baseUrl: config.baseUrl,\n apiKey: config.apiKey,\n timeoutMs: config.timeoutMs,\n userAgent: `acruxcore-mcp-server/${SERVER_VERSION}`,\n });\n\n const tools = selectTools(config);\n const server = new McpServer(\n { name: 'acruxcore', title: 'AcruxCore', version: SERVER_VERSION },\n {\n instructions: buildInstructions(\n new Set(tools.map((tool) => tool.name)),\n config.readOnly,\n ),\n },\n );\n\n for (const tool of tools) {\n // A tool with no arguments registers no input schema at all. The SDK validates a\n // declared schema with `z.object(shape).parse(params.arguments)`, and `arguments` is\n // optional in the protocol — so declaring an empty schema would make\n // `{\"name\":\"list_models\"}`, a perfectly legal call, fail validation. With no schema\n // the SDK skips validation entirely and the call goes through.\n const inputSchema =\n Object.keys(tool.inputSchema).length > 0 ? tool.inputSchema : undefined;\n\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n inputSchema,\n annotations: {\n title: tool.title,\n readOnlyHint: tool.readOnlyHint,\n destructiveHint: tool.destructiveHint ?? false,\n },\n },\n async (args: unknown) => {\n try {\n return await tool.handler(args, { client, config });\n } catch (error) {\n // Every failure is reported in-band rather than thrown. A thrown error becomes\n // a JSON-RPC error the model never sees, so it retries the identical call;\n // an isError result puts the API's own code and message in front of it.\n return errorResult(error, config.maxTextBytes);\n }\n },\n );\n }\n\n registerRegistryPrompts(server, client, config);\n registerResources(server, client, config);\n\n return { server, client, toolNames: tools.map((tool) => tool.name) };\n}\n","/**\n * An error returned by the AcruxCore REST API.\n *\n * The API's error envelope is `{ error: { code, message, ...details } }`. Everything\n * inside it is preserved: an MCP client's model can act on `MISSING_VARIABLES` plus the\n * `missing` array, or on `TOOL_NAME_TAKEN`, in a way it can never act on a bare\n * \"request failed\". `code` is the string the API sent, or a synthesised one\n * (`HTTP_<status>`) when a proxy returned a non-JSON body.\n */\nexport class AcruxCoreApiError extends Error {\n /** HTTP status of the failed response. `0` for a transport-level failure. */\n readonly status: number;\n\n /** AcruxCore error code, e.g. `NOT_FOUND`, `MISSING_VARIABLES`, `TOOL_NAME_TAKEN`. */\n readonly code: string;\n\n /** Any extra keys the error envelope carried beyond `code` and `message`. */\n readonly details: Record<string, unknown>;\n\n /** The request that failed, as `METHOD /path` — included in the message for context. */\n readonly request: string;\n\n /**\n * @param request - `METHOD /path` of the failed call.\n * @param status - HTTP status, or 0 when the request never completed.\n * @param code - AcruxCore error code.\n * @param message - Human-readable message, taken verbatim from the API when present.\n * @param details - Remaining keys from the error envelope.\n */\n constructor(\n request: string,\n status: number,\n code: string,\n message: string,\n details: Record<string, unknown> = {},\n ) {\n super(message);\n this.name = 'AcruxCoreApiError';\n this.request = request;\n this.status = status;\n this.code = code;\n this.details = details;\n }\n\n /**\n * Renders the error for an MCP tool result: code, status, message, and any details.\n *\n * Kept as one line per fact rather than a JSON blob because this text is what the\n * calling model reads to decide what to do next.\n *\n * @returns Multi-line text safe to put in a `CallToolResult` content block.\n */\n toToolText(): string {\n const lines = [\n `AcruxCore API error (${this.code})`,\n `Request: ${this.request}`,\n `Status: ${this.status}`,\n `Message: ${this.message}`,\n ];\n const detailKeys = Object.keys(this.details);\n if (detailKeys.length > 0) {\n lines.push(`Details: ${JSON.stringify(this.details)}`);\n }\n return lines.join('\\n');\n }\n}\n\n/**\n * A configuration problem detected before any request is made — a missing API key, an\n * unknown toolset name. Separate from {@link AcruxCoreApiError} because it is fatal at\n * startup rather than per-call, and the stdio entry point exits on it.\n */\nexport class McpConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'McpConfigError';\n }\n}\n","import { AcruxCoreApiError } from './errors';\n\n/** HTTP verbs this client issues. */\ntype Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';\n\n/** Options for a single request. */\nexport interface RequestOptions {\n /** JSON body. Omitted for GET/DELETE unless a body is genuinely needed. */\n body?: unknown;\n /** Query string parameters. `undefined` and `null` values are dropped. */\n query?: Record<string, string | number | boolean | undefined | null>;\n /** Extra request headers, e.g. the gateway's `x-trace-name`. */\n headers?: Record<string, string>;\n}\n\n/** A response body plus the headers a caller may need to read. */\nexport interface RawResponse<T> {\n data: T;\n headers: Headers;\n status: number;\n}\n\n/**\n * Appends `/api/v1` when the caller gave a bare host.\n *\n * Both forms are in the wild: the SDKs document `ACRUXCORE_BASE_URL` *with* the version\n * prefix, while someone configuring an MCP client by hand almost always pastes the\n * dashboard URL. Guessing wrong produces a 404 on every single tool call, which reads\n * like a broken server rather than a mistyped URL, so normalise instead.\n *\n * @param raw - Base URL as configured.\n * @returns A base URL ending in `/api/v1`, with no trailing slash.\n */\nexport function normalizeBaseUrl(raw: string): string {\n const trimmed = raw.trim().replace(/\\/+$/, '');\n if (/\\/api\\/v\\d+$/.test(trimmed)) return trimmed;\n return `${trimmed}/api/v1`;\n}\n\n/**\n * Thin REST client for the AcruxCore API.\n *\n * Deliberately not the published `@acruxcoreai/sdk`: the MCP server needs endpoints the\n * SDK does not surface (eval rules, audit, gateway usage), needs the raw response\n * headers the gateway returns (`x-gateway-cost-usd`, `x-gateway-trace-id`), and must\n * pass an arbitrary caller-supplied bearer token per request when hosted inside the API.\n * Wrapping the SDK would mean fighting all three.\n */\nexport class AcruxCoreClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly userAgent: string;\n\n /**\n * @param options.baseUrl - AcruxCore base URL, with or without the `/api/v1` suffix.\n * @param options.apiKey - An `acx_sk_…` API key.\n * @param options.timeoutMs - Per-request timeout. Defaults to 60s, which has to cover\n * a gateway completion, not just a database read.\n * @param options.userAgent - Sent as `user-agent`, so API request logs can tell MCP\n * traffic from SDK traffic.\n */\n constructor(options: { baseUrl: string; apiKey: string; timeoutMs?: number; userAgent?: string }) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey;\n this.timeoutMs = options.timeoutMs ?? 60_000;\n this.userAgent = options.userAgent ?? 'acruxcore-mcp-server';\n }\n\n /** The normalised base URL this client calls. */\n get resolvedBaseUrl(): string {\n return this.baseUrl;\n }\n\n /**\n * Issues one request and returns the parsed body.\n *\n * @param method - HTTP verb.\n * @param path - Path below the base URL, starting with `/`.\n * @param options - Body, query and extra headers.\n * @returns The parsed JSON body, or `undefined` for a 204.\n * @throws {AcruxCoreApiError} On any non-2xx response, or a transport failure.\n */\n async request<T = unknown>(method: Method, path: string, options: RequestOptions = {}): Promise<T> {\n const { data } = await this.requestRaw<T>(method, path, options);\n return data;\n }\n\n /**\n * Issues one request and returns the body together with status and headers.\n *\n * Used by the gateway tools, where the interesting metadata (cost, provider, trace id)\n * arrives in `x-gateway-*` headers rather than the body.\n *\n * @param method - HTTP verb.\n * @param path - Path below the base URL, starting with `/`.\n * @param options - Body, query and extra headers.\n * @returns Parsed body, status and headers.\n * @throws {AcruxCoreApiError} On any non-2xx response, or a transport failure.\n */\n async requestRaw<T = unknown>(\n method: Method,\n path: string,\n options: RequestOptions = {},\n ): Promise<RawResponse<T>> {\n const url = new URL(`${this.baseUrl}${path}`);\n for (const [key, value] of Object.entries(options.query ?? {})) {\n if (value === undefined || value === null || value === '') continue;\n url.searchParams.set(key, String(value));\n }\n\n const label = `${method} ${path}`;\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.apiKey}`,\n accept: 'application/json',\n 'user-agent': this.userAgent,\n ...options.headers,\n };\n if (options.body !== undefined) headers['content-type'] = 'application/json';\n\n let response: Response;\n try {\n response = await fetch(url.toString(), {\n method,\n headers,\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n // A transport failure carries no status. Surfacing it with the URL is the\n // difference between \"the server is down\" and \"the base URL is wrong\", which are\n // the two things a user actually needs to tell apart here.\n const reason = err instanceof Error ? err.message : String(err);\n throw new AcruxCoreApiError(\n label,\n 0,\n 'NETWORK_ERROR',\n `Could not reach AcruxCore at ${url.origin}: ${reason}`,\n );\n }\n\n const text = await response.text();\n let parsed: unknown = undefined;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!response.ok) {\n throw toApiError(label, response.status, parsed);\n }\n\n return { data: parsed as T, headers: response.headers, status: response.status };\n }\n\n /** GET shorthand. @see {@link request} */\n get<T = unknown>(path: string, query?: RequestOptions['query']): Promise<T> {\n return this.request<T>('GET', path, { query });\n }\n\n /** POST shorthand. @see {@link request} */\n post<T = unknown>(path: string, body?: unknown, options: Omit<RequestOptions, 'body'> = {}): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /** PATCH shorthand. @see {@link request} */\n patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n /** PUT shorthand. @see {@link request} */\n put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, { body });\n }\n\n /** DELETE shorthand. @see {@link request} */\n delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n\n/**\n * Turns a failed response body into an {@link AcruxCoreApiError}.\n *\n * Handles the three shapes that actually come back: our own\n * `{ error: { code, message, … } }` envelope, a plain string (nginx or a proxy), and\n * anything else (fall back to the status).\n *\n * @param label - `METHOD /path` for the failed call.\n * @param status - HTTP status.\n * @param body - Parsed response body, whatever shape it turned out to be.\n * @returns The error to throw.\n */\nfunction toApiError(label: string, status: number, body: unknown): AcruxCoreApiError {\n if (body && typeof body === 'object' && 'error' in body) {\n const envelope = (body as { error: unknown }).error;\n if (envelope && typeof envelope === 'object') {\n const { code, message, ...details } = envelope as Record<string, unknown>;\n return new AcruxCoreApiError(\n label,\n status,\n typeof code === 'string' ? code : `HTTP_${status}`,\n typeof message === 'string' ? message : `Request failed with status ${status}.`,\n details,\n );\n }\n }\n\n const message =\n typeof body === 'string' && body.trim().length > 0\n ? body.trim().slice(0, 500)\n : `Request failed with status ${status}.`;\n return new AcruxCoreApiError(label, status, `HTTP_${status}`, message);\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { AcruxCoreApiError } from './errors';\n\n/**\n * What a tool handler returns.\n *\n * Aliased to the SDK's own `CallToolResult` rather than redeclared, so a protocol\n * revision that adds a field to a tool result cannot silently drift from what we emit.\n */\nexport type ToolResult = CallToolResult;\n\n/** Appended by {@link truncateText} to a result it had to cut. */\nconst TRUNCATION_MARKER =\n '\\n\\n[truncated: response exceeded the size limit — narrow the query, ' +\n 'use a smaller `limit`, or fetch one item at a time]';\n\n/**\n * Tells whether {@link okResult} had to cut a result to fit its byte budget.\n *\n * Lets a tool retry with a smaller payload instead of returning JSON cut mid-value.\n *\n * @param result - A result built by {@link okResult}.\n * @returns True when its text ends in the truncation marker.\n */\nexport function isTruncated(result: ToolResult): boolean {\n const first = result.content[0];\n return first?.type === 'text' && first.text.endsWith(TRUNCATION_MARKER);\n}\n\n/**\n * Truncates text to a byte budget, appending a marker that says so.\n *\n * Byte-based rather than character-based because the budget exists to protect a context\n * window, and a UTF-8 multibyte character costs more than one. The cut is made on a\n * character boundary by shrinking from the end, so the result is never invalid UTF-8.\n *\n * @param text - Text to cap.\n * @param maxBytes - Maximum bytes of UTF-8 to keep.\n * @returns The text unchanged, or a truncated copy ending in a `[truncated …]` marker.\n */\nexport function truncateText(text: string, maxBytes: number): string {\n const encoder = new TextEncoder();\n if (encoder.encode(text).length <= maxBytes) return text;\n\n const marker = TRUNCATION_MARKER;\n const budget = Math.max(0, maxBytes - encoder.encode(marker).length);\n\n let end = Math.min(text.length, budget);\n while (end > 0 && encoder.encode(text.slice(0, end)).length > budget) {\n // Shrink by a quarter of the overshoot: a UTF-8 character is at most 4 bytes, so\n // this always removes at least one character and converges in a few passes.\n end -= Math.ceil((encoder.encode(text.slice(0, end)).length - budget) / 4);\n }\n return text.slice(0, Math.max(0, end)) + marker;\n}\n\n/**\n * Builds a successful tool result: a one-line human summary, then the JSON payload.\n *\n * Both halves earn their place. The summary is what a model reads when it only needs to\n * know the call worked (\"Promoted alias production to version 3\"); the JSON is what it\n * reads when it needs a field. Returning only JSON makes every result a parsing job;\n * returning only prose throws away the ids the next call needs.\n *\n * @param summary - One line describing what happened.\n * @param payload - Structured data to include, or `undefined` for summary-only.\n * @param maxBytes - Byte budget for the whole result.\n * @returns An MCP `CallToolResult`-shaped object.\n */\nexport function okResult(summary: string, payload: unknown, maxBytes: number): ToolResult {\n const text =\n payload === undefined\n ? summary\n : `${summary}\\n\\n${JSON.stringify(payload, null, 2)}`;\n return { content: [{ type: 'text', text: truncateText(text, maxBytes) }] };\n}\n\n/**\n * Builds a failed tool result.\n *\n * MCP reports tool failures in-band (`isError: true`) rather than as a JSON-RPC error,\n * precisely so the model sees them and can retry differently. An `AcruxCoreApiError`\n * renders with its code and details intact; anything else renders its message.\n *\n * @param error - The thrown value.\n * @param maxBytes - Byte budget for the message.\n * @returns An MCP `CallToolResult` with `isError` set.\n */\nexport function errorResult(error: unknown, maxBytes: number): ToolResult {\n const text =\n error instanceof AcruxCoreApiError\n ? error.toToolText()\n : error instanceof Error\n ? `${error.name}: ${error.message}`\n : `Unexpected error: ${String(error)}`;\n return { content: [{ type: 'text', text: truncateText(text, maxBytes) }], isError: true };\n}\n\n/**\n * Formats the `{ data, total, page, limit }` envelope the list endpoints return.\n *\n * @param noun - Plural noun for the summary line, e.g. `prompts`.\n * @param page - The list response.\n * @returns A summary line naming how many of how many are shown.\n */\nexport function listSummary(\n noun: string,\n page: { data?: unknown[]; total?: number; page?: number; limit?: number },\n): string {\n const shown = page.data?.length ?? 0;\n const total = page.total ?? shown;\n const pageNo = page.page ?? 1;\n if (total === 0) return `No ${noun} found.`;\n return `Showing ${shown} of ${total} ${noun} (page ${pageNo}).`;\n}\n","import {\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n type GetPromptResult,\n type ListPromptsResult,\n type PromptMessage,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\n\n/** How many registry prompts one `prompts/list` page carries. */\nconst PAGE_SIZE = 25;\n\n/** How many per-prompt lookups run at once while building a page. */\nconst LOOKUP_CONCURRENCY = 8;\n\n/** A prompt row from `GET /prompts`. */\ninterface PromptRow {\n id: string;\n name: string;\n description?: string | null;\n}\n\n/** An alias row from `GET /prompts/:id/aliases`. */\ninterface AliasRow {\n alias: string;\n versionNumber: number;\n}\n\n/** A version row from `GET /prompts/:id/versions`. */\ninterface VersionRow {\n versionNumber: number;\n variables?: string[];\n}\n\n/** A registry prompt resolved to what MCP needs to advertise it. */\ninterface ResolvedPrompt {\n name: string;\n description: string;\n variables: string[];\n}\n\n/**\n * Runs an async mapper over a list with a fixed concurrency ceiling.\n *\n * Building a prompts page costs two lookups per prompt. Firing them all at once against\n * a 100-prompt registry would open 200 sockets; doing them one at a time would make the\n * listing visibly slow. Eight at a time is the compromise.\n *\n * @param items - Input items.\n * @param limit - Maximum in-flight mappers.\n * @param mapper - Async transform.\n * @returns Results in input order.\n */\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n mapper: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let next = 0;\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (true) {\n const index = next++;\n if (index >= items.length) return;\n results[index] = await mapper(items[index]);\n }\n });\n await Promise.all(workers);\n return results;\n}\n\n/**\n * Resolves one registry prompt to the alias's version and that version's variables.\n *\n * Returns `null` rather than throwing when the prompt has no version at the configured\n * alias: a half-built prompt is a normal state in a registry, and one of them must not\n * break the whole listing.\n *\n * @param client - REST client.\n * @param row - The prompt row.\n * @param alias - Alias to resolve.\n * @returns The resolved prompt, or null when the alias does not exist for it.\n */\nasync function resolvePrompt(\n client: AcruxCoreClient,\n row: PromptRow,\n alias: string,\n): Promise<ResolvedPrompt | null> {\n try {\n const [aliases, versions] = await Promise.all([\n client.get<AliasRow[]>(`/prompts/${row.id}/aliases`),\n client.get<{ data?: VersionRow[] }>(`/prompts/${row.id}/versions`, { limit: 100 }),\n ]);\n\n const match = (Array.isArray(aliases) ? aliases : []).find((a) => a.alias === alias);\n if (!match) return null;\n\n const version = (versions.data ?? []).find((v) => v.versionNumber === match.versionNumber);\n return {\n name: row.name,\n description:\n `${row.description ?? 'AcruxCore registry prompt'} ` +\n `(alias \"${alias}\", version ${match.versionNumber})`,\n variables: version?.variables ?? [],\n };\n } catch {\n // One unreadable prompt must not empty the whole list — the client would show\n // \"no prompts\" and the user would think the server was broken.\n return null;\n }\n}\n\n/**\n * Builds one page of registry prompts.\n *\n * @param client - REST client.\n * @param alias - Alias to expose.\n * @param page - 1-based page number.\n * @returns The resolved prompts and whether another page exists.\n */\nasync function listRegistryPrompts(\n client: AcruxCoreClient,\n alias: string,\n page: number,\n): Promise<{ prompts: ResolvedPrompt[]; hasMore: boolean }> {\n const listed = await client.get<{ data?: PromptRow[]; total?: number }>('/prompts', {\n page,\n limit: PAGE_SIZE,\n });\n const rows = listed.data ?? [];\n const resolved = await mapWithConcurrency(rows, LOOKUP_CONCURRENCY, (row) =>\n resolvePrompt(client, row, alias),\n );\n const total = listed.total ?? rows.length;\n return {\n prompts: resolved.filter((p): p is ResolvedPrompt => p !== null),\n hasMore: page * PAGE_SIZE < total,\n };\n}\n\n/**\n * Converts rendered registry messages into MCP prompt messages.\n *\n * MCP's `PromptMessage.role` is `user | assistant` — the protocol has no system role.\n * A registry prompt whose template opens with a system message therefore cannot\n * round-trip as-is. Emitting it as the leading `user` message keeps the instruction in\n * the conversation, in position, with its text unchanged; dropping it would silently\n * change what the prompt does.\n *\n * @param messages - Rendered messages from the render endpoint.\n * @returns MCP-shaped prompt messages.\n */\nexport function toPromptMessages(\n messages: Array<{ role?: string; content?: unknown }>,\n): PromptMessage[] {\n return messages.map((message) => ({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content: {\n type: 'text' as const,\n text: typeof message.content === 'string' ? message.content : JSON.stringify(message.content),\n },\n }));\n}\n\n/**\n * Registers the MCP prompts primitive, backed by the AcruxCore prompt registry.\n *\n * This is the piece that makes the server more than an API wrapper: a team's production\n * prompts become slash commands in the client, with the template variables as typed\n * arguments, resolved through the same alias production traffic uses.\n *\n * Handlers are set on the low-level server rather than through `registerPrompt` because\n * the list is not known at startup — it is whatever the team's registry holds right now.\n *\n * Nothing is cached. The obvious 60-second cache would be a module-level map shared by\n * every request of the hosted transport, where each request may carry a *different*\n * team's API key — a cross-tenant leak in exchange for saving one list call.\n *\n * @param server - The MCP server to register on.\n * @param client - REST client carrying the caller's API key.\n * @param config - Resolved configuration; `promptAlias` decides which alias is exposed.\n */\nexport function registerRegistryPrompts(\n server: McpServer,\n client: AcruxCoreClient,\n config: McpServerConfig,\n): void {\n server.server.registerCapabilities({ prompts: { listChanged: false } });\n\n server.server.setRequestHandler(ListPromptsRequestSchema, async (request): Promise<ListPromptsResult> => {\n const page = parseCursor(request.params?.cursor);\n const { prompts, hasMore } = await listRegistryPrompts(client, config.promptAlias, page);\n\n return {\n prompts: prompts.map((prompt) => ({\n name: prompt.name,\n title: prompt.name,\n description: prompt.description,\n arguments: prompt.variables.map((variable) => ({\n name: variable,\n description: `Template variable \"${variable}\".`,\n required: true,\n })),\n })),\n ...(hasMore ? { nextCursor: String(page + 1) } : {}),\n };\n });\n\n server.server.setRequestHandler(GetPromptRequestSchema, async (request): Promise<GetPromptResult> => {\n const { name, arguments: args } = request.params;\n const rendered = await client.post<{\n messages?: Array<{ role?: string; content?: unknown }>;\n versionNumber?: number;\n }>(`/prompts/${encodeURIComponent(name)}/${encodeURIComponent(config.promptAlias)}/render`, {\n variables: args ?? {},\n });\n\n return {\n description: `AcruxCore prompt \"${name}\" at alias \"${config.promptAlias}\" (version ${rendered.versionNumber}).`,\n messages: toPromptMessages(rendered.messages ?? []),\n };\n });\n}\n\n/**\n * Reads a page number out of an MCP cursor.\n *\n * @param cursor - Opaque cursor from the client, if any.\n * @returns A 1-based page number; 1 for anything unparseable.\n */\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) return 1;\n const page = Number(cursor);\n return Number.isInteger(page) && page > 0 ? page : 1;\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AcruxCoreClient } from './client';\nimport type { McpServerConfig } from './config';\nimport { truncateText } from './format';\n\n/** A prompt row from `GET /prompts`. */\ninterface PromptRow {\n id: string;\n name: string;\n description?: string | null;\n}\n\n/**\n * Registers the `acruxcore://` resources.\n *\n * Resources exist alongside the tools because reading and doing are different acts. A\n * client attaches a resource to context without a tool call and without the model\n * deciding to fetch it — which is exactly right for \"here is the prompt template we are\n * discussing\" or \"here is the trace that failed\". The same content is reachable through\n * `get_prompt`/`get_trace`, but only as the result of the model choosing to look.\n *\n * @param server - The MCP server to register on.\n * @param client - REST client carrying the caller's API key.\n * @param config - Resolved configuration.\n */\nexport function registerResources(\n server: McpServer,\n client: AcruxCoreClient,\n config: McpServerConfig,\n): void {\n server.registerResource(\n 'prompt-template',\n new ResourceTemplate('acruxcore://prompts/{name}/{alias}', {\n // Listing the registry at the configured alias gives the client something to show\n // in a resource picker. Every alias of every prompt would be a combinatorial list\n // nobody can scan.\n list: async () => {\n const listed = await client.get<{ data?: PromptRow[] }>('/prompts', { limit: 100 });\n return {\n resources: (listed.data ?? []).map((row) => ({\n uri: `acruxcore://prompts/${row.name}/${config.promptAlias}`,\n name: row.name,\n description: row.description ?? `AcruxCore prompt \"${row.name}\".`,\n mimeType: 'application/json',\n })),\n };\n },\n }),\n {\n title: 'AcruxCore prompt template',\n description:\n 'The raw, unrendered template of the version an alias points at, with its ' +\n 'variables and bound default model.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const name = String(variables.name);\n const alias = String(variables.alias);\n\n // The raw template, not a render: a resource is for reading what the prompt *is*,\n // and rendering would need variable values the reader has not supplied.\n const promptId = await promptIdFor(client, name);\n const aliases = await client.get<Array<{ alias: string; versionNumber: number }>>(\n `/prompts/${promptId}/aliases`,\n );\n const match = aliases.find((a) => a.alias === alias);\n if (!match) {\n throw new Error(`Prompt \"${name}\" has no alias \"${alias}\".`);\n }\n const version = await client.get<unknown>(\n `/prompts/${promptId}/versions/${match.versionNumber}`,\n );\n\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: truncateText(JSON.stringify(version, null, 2), config.maxTextBytes),\n },\n ],\n };\n },\n );\n\n server.registerResource(\n 'trace',\n new ResourceTemplate('acruxcore://traces/{traceId}', {\n // Deliberately unlisted: a team accumulates traces without limit, so enumerating\n // them into a resource picker would be useless at best. Traces are found with\n // search_traces and then addressed by id.\n list: undefined,\n }),\n {\n title: 'AcruxCore trace',\n description: 'One trace with its full span tree, tokens, cost and latency.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const trace = await client.get<unknown>(`/traces/${String(variables.traceId)}`);\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: truncateText(JSON.stringify(trace, null, 2), config.maxTextBytes),\n },\n ],\n };\n },\n );\n}\n\n/**\n * Looks up a prompt id by name for the resource handlers.\n *\n * @param client - REST client.\n * @param name - Prompt name from the URI.\n * @returns The prompt's UUID.\n * @throws {Error} When no prompt in the team carries that name.\n */\nasync function promptIdFor(client: AcruxCoreClient, name: string): Promise<string> {\n const listed = await client.get<{ data?: PromptRow[] }>('/prompts', { search: name, limit: 100 });\n const exact = (listed.data ?? []).find((row) => row.name === name);\n if (!exact) throw new Error(`No prompt named \"${name}\" in this team.`);\n return exact.id;\n}\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { resolveToolRef } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A tool reference accepted by every tool here. */\nconst toolRef = z\n .string()\n .min(1)\n .describe('Catalog tool name (e.g. \"get_weather\") or tool UUID. Names are resolved for you.');\n\n/** One name/value pair used for a header or a query parameter on an HTTP executor. */\nconst nameValueSchema = z.object({\n name: z.string().min(1).describe('Header or query parameter name.'),\n value: z\n .string()\n .describe('Value. May reference a stored secret as {{ secrets.MY_SECRET }}.'),\n});\n\n/** How a tool argument is carried into the upstream HTTP request. */\nconst argMappingSchema = z.object({\n arg: z.string().min(1).describe('Argument name from parametersSchema.'),\n in: z.enum(['query', 'path', 'header', 'body']).describe('Where the argument goes.'),\n path: z.string().optional().describe('Dotted path within the body, when `in` is \"body\".'),\n});\n\n/** Either \"your app runs it\" or a declarative HTTP call AcruxCore runs server-side. */\nconst executorSchema = z.union([\n z\n .object({ type: z.literal('client') })\n .describe('Definition only — the caller\\'s own app executes the tool.'),\n z\n .object({\n type: z.literal('http'),\n url: z.string().url().describe('Absolute upstream URL. localhost is rejected by design.'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n headers: z.array(nameValueSchema).optional(),\n query: z.array(nameValueSchema).optional(),\n bodyTemplate: z.string().optional().describe('JSON body template.'),\n argMapping: z.array(argMappingSchema).optional(),\n requestTransform: z\n .string()\n .optional()\n .describe('Full JS function source: function transform(input) { … }'),\n responseTransform: z\n .string()\n .optional()\n .describe('Full JS function source: function transform(input) { … }'),\n })\n .describe('AcruxCore executes the call server-side.'),\n]);\n\n/**\n * Tools for the Tool Catalog — the versioned registry of function definitions a prompt\n * can bind to.\n *\n * The distinction these descriptions must carry is the one people get wrong: a catalog\n * entry has a *definition* (the schema and description the model reads) and an\n * *executor* (who actually runs it). A `client` executor stores only the definition; an\n * `http` executor lets AcruxCore make the call itself.\n */\nexport const catalogTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_catalog_tools',\n title: 'List catalog tools',\n toolset: 'tools',\n readOnlyHint: true,\n description:\n 'List the tools in the team\\'s Tool Catalog. These are the function definitions a ' +\n 'prompt alias can bind to and the gateway can attach to a completion.',\n inputSchema: {\n search: z.string().optional().describe('Substring filter over name and description.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler({ search, page, limit }, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/tools', {\n search,\n page,\n limit,\n });\n return okResult(listSummary('catalog tools', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_catalog_tool',\n title: 'Get a catalog tool with its versions and aliases',\n toolset: 'tools',\n readOnlyHint: true,\n description:\n 'Read one catalog tool in full: metadata, every committed version (parameters ' +\n 'schema, executor, source) and every alias with the version it points at. Call ' +\n 'this before executing, to see whether the tool has a server-side http executor ' +\n 'or is definition-only.',\n inputSchema: { tool: toolRef },\n async handler({ tool }, { client, config }) {\n const id = await resolveToolRef(client, tool);\n const [detail, versions, aliases] = await Promise.all([\n client.get<Record<string, unknown>>(`/tools/${id}`),\n client.get<{ data?: unknown[] }>(`/tools/${id}/versions`, { limit: 100 }),\n client.get<unknown[]>(`/tools/${id}/aliases`),\n ]);\n return okResult(\n `Tool \"${detail.name}\" — ${versions.data?.length ?? 0} version(s).`,\n { tool: detail, versions: versions.data ?? [], aliases },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'sync_catalog_tool',\n title: 'Create or update a catalog tool',\n toolset: 'tools',\n readOnlyHint: false,\n description:\n 'Create-or-commit-or-nothing for one tool, addressed by name. If the name is new ' +\n 'the tool is created and v1 committed; if the spec differs from the version the ' +\n 'alias points at, a new version is committed and the alias moved; if the spec is ' +\n 'identical, nothing happens (key order does not count as a change). This is the ' +\n 'one call to use for \"add this tool\" and \"update this tool\\'s description\" alike.',\n inputSchema: {\n name: z\n .string()\n .min(1)\n .max(64)\n .describe('Tool name. Must match ^[a-zA-Z0-9_-]{1,64}$ — LLM function-name safe.'),\n description: z\n .string()\n .max(2000)\n .optional()\n .describe('What the tool does. This is text the MODEL reads, so write it for a model.'),\n parametersSchema: z\n .record(z.unknown())\n .describe('JSON Schema object for the arguments, e.g. {\"type\":\"object\",\"properties\":{…}}.'),\n executor: executorSchema,\n alias: z.string().min(1).max(64).optional().describe('Alias to move. Default \"production\".'),\n changelog: z.string().max(2000).optional().describe('Why this version changed.'),\n },\n async handler(args, { client, config }) {\n const result = await client.post<{\n toolId: string;\n versionNumber: number;\n committed: boolean;\n alias: string;\n }>('/tools/sync', {\n ...args,\n // `code` means \"derived from a decorated function in a source file\", and the\n // dashboard's ownership warnings depend on that being literally true. An MCP\n // client is not that, so it claims `api` rather than taking the endpoint default.\n source: 'api',\n });\n return okResult(\n result.committed\n ? `Committed version ${result.versionNumber} of \"${args.name}\"; alias \"${result.alias}\" now points at it.`\n : `No change — \"${args.name}\" already matches version ${result.versionNumber} at alias \"${result.alias}\".`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'execute_catalog_tool',\n title: 'Execute a catalog tool',\n toolset: 'tools',\n readOnlyHint: false,\n description:\n 'Run a catalog tool server-side and return its result. Only works for a version ' +\n 'with an \"http\" executor — a definition-only (\"client\") version returns ' +\n 'NOT_EXECUTABLE, because there is nothing for AcruxCore to call. Arguments are ' +\n 'validated against the version\\'s parameters schema before the call is made.',\n inputSchema: {\n tool: toolRef,\n arguments: z.record(z.unknown()).describe('Arguments matching the tool\\'s parameters schema.'),\n alias: z.string().optional().describe('Alias to resolve. Default \"production\".'),\n version_number: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Pin an exact version instead of following an alias.'),\n },\n async handler({ tool, ...args }, { client, config }) {\n const id = await resolveToolRef(client, tool);\n const body: Record<string, unknown> = { arguments: args.arguments };\n if (args.alias !== undefined) body.alias = args.alias;\n if (args.version_number !== undefined) body.versionNumber = args.version_number;\n\n const result = await client.post<{ status?: number; latencyMs?: number }>(\n `/tools/${id}/execute`,\n body,\n );\n return okResult(\n `Executed \"${tool}\" — upstream status ${result.status}, ${result.latencyMs}ms.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n];\n","import type { AcruxCoreClient } from './client';\nimport { AcruxCoreApiError } from './errors';\n\n/** Matches a canonical v4-shaped UUID, which is what every AcruxCore id is. */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Reports whether a reference is already an id rather than a name.\n *\n * @param ref - The user-supplied reference.\n * @returns True when it looks like a UUID.\n */\nexport function isUuid(ref: string): boolean {\n return UUID_RE.test(ref.trim());\n}\n\n/** One entry of a `{ data: [...] }` list response with a name. */\ninterface NamedRow {\n id: string;\n name: string;\n}\n\n/**\n * Resolves a prompt reference — a UUID or a prompt name — to a prompt id.\n *\n * Accepting names is not a convenience, it is what makes the tools usable by a model.\n * An assistant is told \"promote customer-support\"; requiring the UUID first costs an\n * extra round trip and invites a hallucinated id that then 404s confusingly.\n *\n * @param client - REST client.\n * @param ref - Prompt UUID or exact prompt name.\n * @returns The prompt's UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when no active prompt carries that name.\n */\nexport async function resolvePromptRef(client: AcruxCoreClient, ref: string): Promise<string> {\n return resolveNamedRef(client, '/prompts', ref, 'prompt');\n}\n\n/**\n * Resolves a catalog-tool reference — a UUID or a tool name — to a tool id.\n *\n * @param client - REST client.\n * @param ref - Tool UUID or exact tool name.\n * @returns The tool's UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when no active tool carries that name.\n */\nexport async function resolveToolRef(client: AcruxCoreClient, ref: string): Promise<string> {\n return resolveNamedRef(client, '/tools', ref, 'tool');\n}\n\n/**\n * Shared name→id lookup for the two collections that support `?search=`.\n *\n * The search endpoint is a substring match, so the exact name is picked out of the\n * results rather than trusting the first row: searching `weather` when both\n * `get_weather` and `get_weather_forecast` exist must not silently pick one.\n *\n * @param client - REST client.\n * @param path - Collection path, e.g. `/prompts`.\n * @param ref - UUID or name.\n * @param noun - Singular noun for error messages.\n * @returns The resolved UUID.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when the name matches nothing exactly.\n */\nasync function resolveNamedRef(\n client: AcruxCoreClient,\n path: string,\n ref: string,\n noun: string,\n): Promise<string> {\n const trimmed = ref.trim();\n if (isUuid(trimmed)) return trimmed;\n\n const page = await client.get<{ data?: NamedRow[] }>(path, { search: trimmed, limit: 100 });\n const exact = (page.data ?? []).find((row) => row.name === trimmed);\n if (exact) return exact.id;\n\n const near = (page.data ?? []).map((row) => row.name).slice(0, 10);\n const hint = near.length > 0 ? ` Closest names: ${near.join(', ')}.` : '';\n throw new AcruxCoreApiError(\n `GET ${path}?search=${trimmed}`,\n 404,\n 'NOT_FOUND',\n `No ${noun} named \"${trimmed}\" in this team.${hint}`,\n );\n}\n\n/**\n * Resolves a prompt reference to both its id and its name.\n *\n * `render_prompt` and the gateway's stored-prompt path address prompts by **name**, but\n * every other prompt route addresses them by id, so a tool that does both needs the pair.\n *\n * @param client - REST client.\n * @param ref - Prompt UUID or name.\n * @returns The prompt's id and name.\n * @throws {AcruxCoreApiError} `NOT_FOUND` when the reference matches no prompt.\n */\nexport async function resolvePromptIdAndName(\n client: AcruxCoreClient,\n ref: string,\n): Promise<{ id: string; name: string }> {\n const trimmed = ref.trim();\n if (isUuid(trimmed)) {\n const prompt = await client.get<{ id: string; name: string }>(`/prompts/${trimmed}`);\n return { id: prompt.id, name: prompt.name };\n }\n const id = await resolvePromptRef(client, trimmed);\n return { id, name: trimmed };\n}\n","import type { z, ZodRawShape } from 'zod';\nimport type { AcruxCoreClient } from '../client';\nimport type { McpServerConfig, Toolset } from '../config';\nimport type { ToolResult } from '../format';\n\n/** Everything a tool handler is given besides its own arguments. */\nexport interface ToolContext {\n /** REST client already carrying the caller's API key. */\n client: AcruxCoreClient;\n /** Resolved server configuration — handlers read `maxTextBytes` from it. */\n config: McpServerConfig;\n}\n\n/**\n * A registered tool, erased to a uniform shape so every toolset can live in one array.\n *\n * `handler` takes `unknown` here; {@link defineTool} does the one cast that restores the\n * inferred argument type at each definition site, so no individual tool needs `any`.\n */\nexport interface AnyToolDefinition {\n /** Tool name as the client sees it. Snake case, verb first. */\n name: string;\n /** Short human title for clients that show one. */\n title: string;\n /** What the model reads to decide whether to call this tool. */\n description: string;\n /** Zod raw shape for the arguments. */\n inputSchema: ZodRawShape;\n /** Which toolset this belongs to. */\n toolset: Toolset;\n /** False for anything that writes. Mutating tools are dropped in read-only mode. */\n readOnlyHint: boolean;\n /** True when a call can remove or overwrite something a user would miss. */\n destructiveHint?: boolean;\n /** Runs the tool. */\n handler: (args: unknown, ctx: ToolContext) => Promise<ToolResult>;\n}\n\n/**\n * Declares a tool with its argument type inferred from the Zod shape.\n *\n * @param def - The tool definition; `handler` receives arguments typed from `inputSchema`.\n * @returns The same definition, erased to {@link AnyToolDefinition}.\n */\nexport function defineTool<Shape extends ZodRawShape>(def: {\n name: string;\n title: string;\n description: string;\n inputSchema: Shape;\n toolset: Toolset;\n readOnlyHint: boolean;\n destructiveHint?: boolean;\n handler: (args: z.infer<z.ZodObject<Shape>>, ctx: ToolContext) => Promise<ToolResult>;\n}): AnyToolDefinition {\n return {\n ...def,\n handler: (args, ctx) => def.handler(args as z.infer<z.ZodObject<Shape>>, ctx),\n };\n}\n","import { z } from 'zod';\nimport { isTruncated, listSummary, okResult } from '../format';\nimport {\n bestCandidate,\n summarizeCandidates,\n type CandidateSummary,\n type OptimizeGridCell,\n type OptimizeReportCell,\n} from '../optimize-report';\nimport { resolvePromptRef } from '../refs';\nimport { defineTool, type AnyToolDefinition, type ToolContext } from './types';\n\n/** A prior-turn message replayed ahead of an example's input during a run. */\nconst historyMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant', 'tool']),\n content: z.string(),\n});\n\n/** The fields of `GET /runs/:id` the optimizer tools read. */\ninterface RunDetail {\n id: string;\n kind: 'evaluation' | 'optimize' | 'local';\n status: 'queued' | 'running' | 'succeeded' | 'failed';\n error: string | null;\n grid: OptimizeGridCell[];\n results?: { total: number; succeeded: number; errored: number };\n}\n\n/** The fields of `GET /runs/:id/report` the optimizer tools read. */\ninterface RunReportBody {\n cells: OptimizeReportCell[];\n judge?: { model: string | null };\n}\n\n/** The fields of `GET /runs/:id/candidates/:candidateId` worth showing before a promote. */\ninterface CandidateDetailBody {\n promptId: string;\n messages: unknown;\n rationale: string | null;\n}\n\n/** One row of `GET /prompts/:id/aliases`. */\ninterface AliasRow {\n alias: string;\n versionId: string;\n versionNumber: number;\n}\n\n/** A candidate's scores joined with its content, as the report tool returns it. */\ninterface CandidateWithContent extends CandidateSummary {\n rationale: string | null;\n messages?: unknown;\n /** Set when the candidate's content could not be read; its scores are still valid. */\n readError?: string;\n}\n\n/**\n * Loads an optimize run and, once it has succeeded, its per-candidate verdicts.\n *\n * Shared by the report tool and the promote tool so the safety check before a promote\n * reads exactly what the report showed.\n *\n * @param client - REST client.\n * @param runId - Run UUID.\n * @returns The run, plus its candidates when the run has succeeded.\n * @throws {Error} When the run is an ordinary evaluation, not an optimize run.\n */\nasync function loadOptimizeRun(\n client: ToolContext['client'],\n runId: string,\n): Promise<{ run: RunDetail; report: RunReportBody | null; candidates: CandidateSummary[] }> {\n const run = await client.get<RunDetail>(`/runs/${runId}`);\n // The API derives `kind` from the grid, and an optimize run's grid stays empty until\n // its rewrites are drafted, so a just-started optimize run reads as \"evaluation\". An\n // ordinary evaluation run freezes its grid when it starts, so an empty grid can only\n // be an optimize run that has not drafted yet.\n const notDraftedYet = run.grid.length === 0;\n if (run.kind !== 'optimize' && !notDraftedYet) {\n throw new Error(\n `Run ${runId} is an evaluation run, not an optimize run. Read it with get_experiment_run.`,\n );\n }\n if (run.status !== 'succeeded') return { run, report: null, candidates: [] };\n\n const report = await client.get<RunReportBody>(`/runs/${runId}/report`);\n return { run, report, candidates: summarizeCandidates(run.grid, report.cells) };\n}\n\n/**\n * Finds what an optimize run scored its rewrites against.\n *\n * @param run - A succeeded optimize run.\n * @returns The baseline version's id and the alias it was resolved through, or null for\n * the alias when the run fell back to the latest version (labelled `v<N>`).\n * @throws {Error} When the grid has no baseline cell, which a succeeded run always has.\n */\nfunction baselineOf(run: RunDetail): { versionId: string; alias: string | null } {\n const cell = run.grid.find((row) => row.isProductionBaseline && row.promptVersionId);\n if (!cell?.promptVersionId) {\n throw new Error(`Run ${run.id} has no baseline version, so a promote cannot be checked.`);\n }\n // The optimizer labels the baseline with its alias, or `v<N>` when no alias existed.\n const alias = /^v\\d+$/.test(cell.variantLabel) ? null : cell.variantLabel;\n return { versionId: cell.promptVersionId, alias };\n}\n\n/** Formats a score delta as `+12.5` / `-3.0`, or `n/a` when it could not be computed. */\nfunction formatDelta(delta: number | null): string {\n if (delta === null) return 'n/a';\n return `${delta >= 0 ? '+' : ''}${delta.toFixed(1)}`;\n}\n\n/**\n * Tools for evaluation: datasets of examples, experiments that sweep a grid of\n * (version x model) over them, and the runs that produce scores.\n *\n * The chain is fixed and the descriptions say so, because skipping a link is the common\n * mistake: a **dataset** holds examples, an **experiment** pairs a dataset with the grid\n * to sweep, and a **run** executes it asynchronously in the worker. Creating an\n * experiment scores nothing until a run is started, and a run returns immediately —\n * results arrive later.\n */\nexport const evaluationTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_datasets',\n title: 'List evaluation datasets',\n toolset: 'evaluations',\n readOnlyHint: true,\n description: 'List the team\\'s evaluation datasets with their example counts.',\n inputSchema: {\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/datasets', args);\n return okResult(listSummary('datasets', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_dataset',\n title: 'Get one dataset with its examples',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'Read one dataset: its name, dataset-level rubric (overallFeedback) and its ' +\n 'examples, each with the input variables and the per-example criteria a judge ' +\n 'scores against.',\n inputSchema: { dataset_id: z.string().uuid().describe('Dataset UUID.') },\n async handler({ dataset_id }, { client, config }) {\n const result = await client.get<{ name?: string; examples?: unknown[] }>(\n `/datasets/${dataset_id}`,\n );\n return okResult(\n `Dataset \"${result.name}\" — ${result.examples?.length ?? 0} example(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'create_dataset',\n title: 'Create an evaluation dataset',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Create an empty dataset. Add examples afterwards with add_dataset_example. ' +\n '`overall_feedback` is a rubric applied on top of each example\\'s own criteria — ' +\n 'write it as an instruction to the judge, not as a complaint about an answer.',\n inputSchema: {\n name: z.string().min(1).describe('Dataset name.'),\n overall_feedback: z\n .string()\n .optional()\n .describe('Dataset-level rubric, e.g. \"Keep responses concise and polite\".'),\n },\n async handler({ name, overall_feedback }, { client, config }) {\n const result = await client.post<{ id: string; name: string }>('/datasets', {\n name,\n overall_feedback,\n });\n return okResult(\n `Created dataset \"${result.name}\" (${result.id}). It has no examples yet.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'add_dataset_example',\n title: 'Add an example to a dataset',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Add one example. `input` is the variable bag the prompt is rendered with; ' +\n '`criteria` is what the judge checks this particular answer against. `history` ' +\n 'supplies prior conversation turns to replay before the input — omit it for a ' +\n 'single-turn example.',\n inputSchema: {\n dataset_id: z.string().uuid().describe('Dataset UUID.'),\n input: z.record(z.unknown()).describe('Template variables for this example, e.g. {\"name\":\"Bob\"}.'),\n criteria: z.string().optional().describe('What a correct answer must do.'),\n history: z\n .array(historyMessageSchema)\n .optional()\n .describe('Prior turns to replay first. Max 20 messages.'),\n },\n async handler({ dataset_id, ...body }, { client, config }) {\n const result = await client.post<{ id: string }>(`/datasets/${dataset_id}/examples`, body);\n return okResult(`Added example ${result.id}.`, result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'run_experiment',\n title: 'Create and start an experiment run',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Create an experiment over a dataset and immediately start a run of it. The grid ' +\n 'is every (version x model) pair you list. When `prompt` is given, a baseline cell ' +\n 'for its production alias is added automatically unless that version is already in ' +\n 'the grid. Returns as soon as the run is queued — the worker executes it ' +\n 'asynchronously, so poll get_experiment_run for results. Note the judge model ' +\n '(gpt-4o-mini by default) must itself be registered in the gateway or every score ' +\n 'fails.',\n inputSchema: {\n dataset_id: z.string().uuid().describe('Dataset to evaluate against.'),\n version_ids: z\n .array(z.string().uuid())\n .min(1)\n .describe('Prompt-version UUIDs to sweep. At least one.'),\n models: z.array(z.string().min(1)).min(1).describe('Gateway model public names to sweep.'),\n prompt: z\n .string()\n .optional()\n .describe('Prompt name or UUID under test — enables the automatic baseline cell.'),\n name: z.string().optional().describe('Experiment name, for the run history.'),\n alias: z\n .string()\n .optional()\n .describe('Which alias the automatic baseline points at. Default \"production\".'),\n },\n async handler(args, { client, config }) {\n const body: Record<string, unknown> = {\n dataset_id: args.dataset_id,\n version_ids: args.version_ids,\n models: args.models,\n };\n if (args.name !== undefined) body.name = args.name;\n if (args.alias !== undefined) body.alias = args.alias;\n if (args.prompt !== undefined) body.prompt_id = await resolvePromptRef(client, args.prompt);\n\n const experiment = await client.post<{ id: string; promptMismatchWarning?: string }>(\n '/experiments',\n body,\n );\n const run = await client.post<{ run_id: string; status: string }>(\n `/experiments/${experiment.id}/runs`,\n );\n\n const warning = experiment.promptMismatchWarning\n ? ` Warning: ${experiment.promptMismatchWarning}`\n : '';\n return okResult(\n `Experiment ${experiment.id} created and run ${run.run_id} is ${run.status}. ` +\n `Results arrive asynchronously — poll get_experiment_run.${warning}`,\n { experiment, run },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_experiment_runs',\n title: 'List evaluation runs',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'The run history, newest first. Each row carries the dataset and prompt evaluated, ' +\n 'the grid shape, and the scores — avgScore, passRate and topVariantLabel are null ' +\n 'rather than 0 until at least one result has been judged, so an unscored run is ' +\n 'never mistaken for one that scored badly. `kind` is \"optimize\" for optimizer ' +\n 'sweeps and \"evaluation\" otherwise.',\n inputSchema: {\n status: z\n .enum(['queued', 'running', 'succeeded', 'failed'])\n .optional()\n .describe('Lifecycle filter.'),\n dataset_id: z.string().uuid().optional().describe('Only runs over this dataset.'),\n prompt_id: z.string().uuid().optional().describe('Only runs whose experiment named this prompt.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Rows per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/runs', args);\n return okResult(listSummary('runs', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_experiment_run',\n title: 'Get a run, optionally with its comparison report',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'Read one run\\'s status and results. With include_report=true it also fetches the ' +\n 'comparison report: the full (variant x model) matrix with per-cell averages, each ' +\n 'cell\\'s delta against the same-model production baseline, a leaderboard and an ' +\n 'advisory winner. Ask for the report only once the run has succeeded — an ' +\n 'in-flight run has nothing to compare. For an optimize run, get_optimize_report ' +\n 'gives the same scores per candidate, with the ids promote_optimize_candidate needs.',\n inputSchema: {\n run_id: z.string().uuid().describe('Run UUID.'),\n include_report: z.boolean().optional().describe('Also fetch the comparison report.'),\n },\n async handler({ run_id, include_report }, { client, config }) {\n const run = await client.get<{ status?: string; results?: { total?: number } }>(\n `/runs/${run_id}`,\n );\n let report: unknown = undefined;\n if (include_report) {\n report = await client.get(`/runs/${run_id}/report`);\n }\n return okResult(\n `Run ${run_id} is ${run.status} with ${run.results?.total ?? 0} result(s).`,\n { run, report },\n config.maxTextBytes,\n );\n },\n }),\n defineTool({\n name: 'optimize_prompt',\n title: 'Start an optimizer run for a prompt',\n toolset: 'evaluations',\n readOnlyHint: false,\n description:\n 'Ask the optimizer to improve a prompt against a dataset. An optimizer model drafts ' +\n 'up to `draft_count` rewrites of the version behind `alias` (default \"production\"), ' +\n 'then every rewrite and that baseline run over the dataset on each of `models`, and ' +\n '`judge_model` scores every answer. Returns the run id as soon as the run is queued — ' +\n 'drafting and scoring take minutes, so poll get_optimize_report. Nothing is promoted ' +\n 'automatically: a rewrite only ships when promote_optimize_candidate is called. The ' +\n 'dataset\\'s examples need `criteria`, or the judge has nothing to grade against. ' +\n 'Every model named here must be registered in the gateway (see list_models).',\n inputSchema: {\n prompt: z.string().min(1).describe('Prompt name or UUID to improve.'),\n dataset_id: z.string().uuid().describe('Dataset whose examples the rewrites are scored on.'),\n models: z\n .array(z.string().min(1))\n .min(1)\n .describe('Gateway model public names to test each rewrite and the baseline on.'),\n judge_model: z.string().min(1).describe('Gateway model that scores every answer. Required.'),\n optimizer_model: z\n .string()\n .min(1)\n .optional()\n .describe('Gateway model that writes the rewrites. Default: the first entry of `models`.'),\n draft_count: z\n .number()\n .int()\n .min(1)\n .max(6)\n .optional()\n .describe('How many rewrites to draft, 1 to 6. Default 3.'),\n alias: z\n .string()\n .min(1)\n .optional()\n .describe('Alias whose version is the baseline to beat. Default \"production\".'),\n optimizer_prompt: z\n .string()\n .optional()\n .describe('Name or UUID of a team prompt to use as the optimizer\\'s instructions.'),\n },\n async handler(args, { client, config }) {\n const promptId = await resolvePromptRef(client, args.prompt);\n const body: Record<string, unknown> = {\n dataset_id: args.dataset_id,\n models: args.models,\n judge_model: args.judge_model,\n };\n if (args.optimizer_model !== undefined) body.optimizer_model = args.optimizer_model;\n if (args.draft_count !== undefined) body.draft_count = args.draft_count;\n if (args.alias !== undefined) body.alias = args.alias;\n if (args.optimizer_prompt !== undefined) {\n body.optimizer_prompt_id = await resolvePromptRef(client, args.optimizer_prompt);\n }\n\n const result = await client.post<{\n run_id: string;\n status: string;\n optimizer_model: string;\n prompt_mismatch_warning?: unknown;\n }>(`/prompts/${promptId}/optimize`, body);\n\n const warning = result.prompt_mismatch_warning\n ? ' Warning: some dataset examples were built from a different prompt — see prompt_mismatch_warning.'\n : '';\n return okResult(\n `Optimize run ${result.run_id} is ${result.status}; ${result.optimizer_model} drafts ` +\n `the rewrites, then they are scored against the ${args.alias ?? 'production'} ` +\n `baseline. Poll get_optimize_report with this run id.${warning}`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'get_optimize_report',\n title: 'Read an optimizer run\\'s candidates and scores',\n toolset: 'evaluations',\n readOnlyHint: true,\n description:\n 'Read an optimize run started by optimize_prompt. While it is queued or running this ' +\n 'returns only its status — call again later. Once it has succeeded it lists every ' +\n 'drafted rewrite with its candidate id, the optimizer\\'s rationale, the rewritten ' +\n 'messages, and its average score next to the baseline\\'s on each model. ' +\n '`beatsBaseline` is true only for a rewrite that improved on at least one model and ' +\n 'was improved or flat on every other; `recommended` is the one among those with the ' +\n 'largest gain, or null when no rewrite beat the baseline. When the rewrites are too ' +\n 'long to fit in one result, their messages are left out (`messagesOmitted`); pass ' +\n '`candidate_id` to read one rewrite in full.',\n inputSchema: {\n run_id: z.string().uuid().describe('Optimize run UUID, from optimize_prompt.'),\n candidate_id: z\n .string()\n .uuid()\n .optional()\n .describe('Return only this candidate, with its full messages.'),\n },\n async handler({ run_id, candidate_id }, { client, config }) {\n const { run, report, candidates } = await loadOptimizeRun(client, run_id);\n\n if (run.status === 'queued' || run.status === 'running') {\n return okResult(\n `Optimize run ${run_id} is ${run.status}. No scores yet — call get_optimize_report again shortly.`,\n { runId: run_id, status: run.status },\n config.maxTextBytes,\n );\n }\n if (run.status === 'failed') {\n return okResult(\n `Optimize run ${run_id} failed: ${run.error ?? 'no reason recorded'}. Nothing to promote.`,\n { runId: run_id, status: run.status, error: run.error },\n config.maxTextBytes,\n );\n }\n\n if (candidate_id !== undefined) {\n const candidate = candidates.find((row) => row.candidateId === candidate_id);\n if (!candidate) {\n throw new Error(`Candidate ${candidate_id} is not a rewrite from run ${run_id}.`);\n }\n const detail = await client.get<CandidateDetailBody>(\n `/runs/${run_id}/candidates/${candidate_id}`,\n );\n return okResult(\n `${candidate.label} (candidate_id ${candidate_id}) from optimize run ${run_id}; ` +\n `beatsBaseline: ${candidate.beatsBaseline}.`,\n {\n runId: run_id,\n candidate: { ...candidate, rationale: detail.rationale, messages: detail.messages },\n },\n config.maxTextBytes,\n );\n }\n\n // One unreadable candidate must not hide every other candidate's scores.\n const reads = await Promise.allSettled(\n candidates.map((candidate) =>\n client.get<CandidateDetailBody>(`/runs/${run_id}/candidates/${candidate.candidateId}`),\n ),\n );\n const withContent: CandidateWithContent[] = candidates.map((candidate, index) => {\n const read = reads[index]!;\n return read.status === 'fulfilled'\n ? { ...candidate, rationale: read.value.rationale, messages: read.value.messages }\n : {\n ...candidate,\n rationale: null,\n messages: null,\n readError: read.reason instanceof Error ? read.reason.message : String(read.reason),\n };\n });\n const best = bestCandidate(candidates);\n const winners = candidates.filter((candidate) => candidate.beatsBaseline).length;\n\n const summary = best\n ? `Optimize run ${run_id} succeeded. ${winners} of ${candidates.length} rewrite(s) beat ` +\n `the baseline. Recommended: ${best.label} (candidate_id ${best.candidateId}), ` +\n best.scores.map((score) => `${formatDelta(score.scoreDelta)} on ${score.model}`).join(', ') +\n '. Promote it with promote_optimize_candidate only if the user agrees.'\n : `Optimize run ${run_id} succeeded, but none of its ${candidates.length} rewrite(s) ` +\n 'beat the baseline. Nothing is worth promoting; keep the current version.';\n\n const payload = {\n runId: run_id,\n status: run.status,\n judgeModel: report?.judge?.model ?? null,\n recommended: best?.candidateId ?? null,\n baseline: (report?.cells ?? [])\n .filter((cell) => cell.isProductionBaseline)\n .map((cell) => ({\n label: cell.variantLabel,\n model: cell.model,\n avgScore: cell.avgScore,\n passRate: cell.passRate,\n })),\n candidates: withContent,\n };\n const full = okResult(summary, payload, config.maxTextBytes);\n if (!isTruncated(full)) return full;\n\n // Cutting the JSON would drop the last candidates' ids and leave invalid JSON, so\n // drop every rewrite's messages instead and keep all the ids and scores.\n return okResult(\n `${summary} The rewrites are too long to show together, so their messages are left ` +\n 'out; call get_optimize_report again with candidate_id to read one.',\n {\n ...payload,\n messagesOmitted: true,\n candidates: withContent.map(({ messages: _messages, ...rest }) => rest),\n },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'promote_optimize_candidate',\n title: 'Ship an optimizer rewrite as a new prompt version',\n toolset: 'evaluations',\n readOnlyHint: false,\n destructiveHint: true,\n description:\n 'Commit one rewrite from a succeeded optimize run as a new prompt version and move ' +\n '`alias` to it, so live traffic on that alias starts using it. `alias` defaults to the ' +\n 'alias the run was scored against (production when the run used the latest version). ' +\n 'Take `candidate_id` from get_optimize_report. Refuses a rewrite that did not beat the ' +\n 'baseline, and refuses when the alias now points at a version other than the one the ' +\n 'run scored against; set `promote_without_improvement` only when the user has ' +\n 'explicitly asked to ship that rewrite anyway. Undo by moving the alias back with ' +\n 'promote_prompt_alias.',\n inputSchema: {\n run_id: z.string().uuid().describe('Optimize run UUID.'),\n candidate_id: z.string().uuid().describe('Candidate id from get_optimize_report.'),\n alias: z\n .string()\n .min(1)\n .optional()\n .describe('Alias to move. Default: the alias the run was scored against.'),\n promote_without_improvement: z\n .boolean()\n .optional()\n .describe(\n 'Ship a rewrite that did not beat the baseline, or replace a version the run never ' +\n 'scored. Only on the user\\'s explicit say-so.',\n ),\n },\n async handler(args, { client, config }) {\n const { run, candidates } = await loadOptimizeRun(client, args.run_id);\n if (run.status !== 'succeeded') {\n throw new Error(\n `Optimize run ${args.run_id} is ${run.status}, so its rewrites are not fully scored. ` +\n 'Promote only from a succeeded run.',\n );\n }\n\n const candidate = candidates.find((row) => row.candidateId === args.candidate_id);\n if (!candidate) {\n throw new Error(\n `Candidate ${args.candidate_id} is not a rewrite from run ${args.run_id}. ` +\n 'Take the id from get_optimize_report.',\n );\n }\n if (!candidate.beatsBaseline && !args.promote_without_improvement) {\n const scores = candidate.scores\n .map((score) => `${formatDelta(score.scoreDelta)} (${score.verdict}) on ${score.model}`)\n .join(', ');\n throw new Error(\n `Refused: ${candidate.label} did not beat the baseline (${scores}). Promoting it ` +\n 'would ship a prompt that scored no better than the current one. Set ' +\n 'promote_without_improvement to true only if the user explicitly asked for this rewrite.',\n );\n }\n\n // A win only means something against the version that was scored. If the alias\n // points elsewhere now (it moved after the run, or it is a different alias), the\n // rewrite was never compared with what it would replace.\n const baseline = baselineOf(run);\n const alias = args.alias ?? baseline.alias ?? 'production';\n const detail = await client.get<CandidateDetailBody>(\n `/runs/${args.run_id}/candidates/${args.candidate_id}`,\n );\n const aliases = await client.get<AliasRow[]>(`/prompts/${detail.promptId}/aliases`);\n const live = aliases.find((row) => row.alias === alias);\n if (live && live.versionId !== baseline.versionId && !args.promote_without_improvement) {\n throw new Error(\n `Refused: alias \"${alias}\" now points at version ${live.versionNumber}, but run ` +\n `${args.run_id} scored its rewrites against a different version. Nothing compared ` +\n `${candidate.label} with version ${live.versionNumber}. Start a new optimize run ` +\n 'against this alias, or set promote_without_improvement to true only if the user ' +\n 'explicitly asked to replace it anyway.',\n );\n }\n\n const result = await client.post<{\n version: { id: string; versionNumber: number };\n alias: { alias: string };\n }>(`/runs/${args.run_id}/promote`, { prompt_candidate_id: args.candidate_id, alias });\n\n return okResult(\n `Promoted ${candidate.label} as version ${result.version.versionNumber}; alias ` +\n `\"${result.alias.alias}\" now points at it.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n];\n","/**\n * Reads an optimize run's report as \"which candidate, if any, beat the baseline\".\n *\n * The REST report (`GET /runs/:id/report`) is a (variant x model) matrix built for a\n * dashboard: it never names a candidate's id, because the UI joins that in from the run's\n * grid. An agent needs the opposite shape — one row per candidate, with the id it must\n * pass to promote and a plain yes/no on whether promoting it is an improvement. This\n * module does that join and that verdict, and nothing else, so both the report tool and\n * the promote tool's safety check read the same answer.\n */\n\n/** One frozen grid cell from `GET /runs/:id`. */\nexport interface OptimizeGridCell {\n cellKey: string;\n variantKind: string;\n variantLabel: string;\n model: string;\n promptCandidateId?: string;\n /** Set on the baseline cells: the version the rewrites were scored against. */\n promptVersionId?: string;\n isProductionBaseline?: boolean;\n}\n\n/** One cell of `GET /runs/:id/report`, reduced to the fields read here. */\nexport interface OptimizeReportCell {\n cellKey: string;\n variantLabel: string;\n model: string;\n isProductionBaseline: boolean;\n avgScore: number | null;\n passRate: number | null;\n scoredCount: number;\n exampleCount: number;\n deltaVsBaseline: {\n score: number | null;\n passRate: number | null;\n label: 'improved' | 'regressed' | 'flat' | 'unknown';\n } | null;\n}\n\n/** How one candidate scored on one model, next to the baseline on that model. */\nexport interface CandidateModelScore {\n model: string;\n avgScore: number | null;\n passRate: number | null;\n baselineAvgScore: number | null;\n /** Candidate minus baseline average score; null when either side has no scores. */\n scoreDelta: number | null;\n /** The report's own label: `improved` / `regressed` need a gap of at least 2 points. */\n verdict: 'improved' | 'regressed' | 'flat' | 'unknown';\n}\n\n/** One optimizer-drafted candidate with its scores and the promote verdict. */\nexport interface CandidateSummary {\n /** The id `promote_optimize_candidate` takes. */\n candidateId: string;\n /** `candidate-A`, `candidate-B`, … as the dashboard shows it. */\n label: string;\n scores: CandidateModelScore[];\n /**\n * True when the candidate improved on at least one model and was improved or flat on\n * every other. A candidate that is worse on one model, or has no scores on one, is not\n * called a win: the prompt is shared by every model that runs it.\n */\n beatsBaseline: boolean;\n}\n\n/**\n * Builds one {@link CandidateSummary} per candidate in the run.\n *\n * @param grid - The run's frozen grid, which carries each cell's `promptCandidateId`.\n * @param cells - The report's cells, which carry the scores and deltas.\n * @returns Candidates in label order (`candidate-A` first); ranking is {@link bestCandidate}'s job.\n */\nexport function summarizeCandidates(\n grid: OptimizeGridCell[],\n cells: OptimizeReportCell[],\n): CandidateSummary[] {\n const cellByKey = new Map(cells.map((cell) => [cell.cellKey, cell]));\n const baselineByModel = new Map(\n cells.filter((cell) => cell.isProductionBaseline).map((cell) => [cell.model, cell]),\n );\n\n const byCandidate = new Map<string, CandidateSummary>();\n for (const gridCell of grid) {\n if (gridCell.variantKind !== 'candidate' || !gridCell.promptCandidateId) continue;\n const reportCell = cellByKey.get(gridCell.cellKey);\n const baseline = baselineByModel.get(gridCell.model);\n\n let summary = byCandidate.get(gridCell.promptCandidateId);\n if (!summary) {\n summary = {\n candidateId: gridCell.promptCandidateId,\n label: gridCell.variantLabel,\n scores: [],\n beatsBaseline: false,\n };\n byCandidate.set(gridCell.promptCandidateId, summary);\n }\n summary.scores.push({\n model: gridCell.model,\n avgScore: reportCell?.avgScore ?? null,\n passRate: reportCell?.passRate ?? null,\n baselineAvgScore: baseline?.avgScore ?? null,\n scoreDelta: reportCell?.deltaVsBaseline?.score ?? null,\n verdict: reportCell?.deltaVsBaseline?.label ?? 'unknown',\n });\n }\n\n const summaries = [...byCandidate.values()];\n for (const summary of summaries) {\n // `unknown` blocks a win like `regressed` does: a model with no scored answers is a\n // model the rewrite was never shown to work on.\n summary.beatsBaseline =\n summary.scores.some((score) => score.verdict === 'improved') &&\n summary.scores.every((score) => score.verdict === 'improved' || score.verdict === 'flat');\n }\n return summaries.sort((a, b) => a.label.localeCompare(b.label));\n}\n\n/**\n * Picks the candidate to recommend: the one that beats the baseline by the largest mean\n * score delta across its models.\n *\n * @param candidates - Output of {@link summarizeCandidates}.\n * @returns The best winning candidate, or null when none beats the baseline.\n */\nexport function bestCandidate(candidates: CandidateSummary[]): CandidateSummary | null {\n let best: CandidateSummary | null = null;\n let bestDelta = -Infinity;\n for (const candidate of candidates) {\n if (!candidate.beatsBaseline) continue;\n const deltas = candidate.scores\n .map((score) => score.scoreDelta)\n .filter((delta): delta is number => delta !== null);\n const mean = deltas.reduce((sum, delta) => sum + delta, 0) / Math.max(1, deltas.length);\n if (mean > bestDelta) {\n best = candidate;\n bestDelta = mean;\n }\n }\n return best;\n}\n","import { z } from 'zod';\nimport { okResult } from '../format';\nimport { resolvePromptIdAndName } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** OpenAI-shaped chat message accepted by the raw completion tool. */\nconst chatMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant', 'tool']).describe('Message role.'),\n content: z.string().describe('Message content.'),\n});\n\n/** Headers the gateway sets on every completion, worth surfacing back to the model. */\nconst GATEWAY_HEADERS = [\n 'x-gateway-request-id',\n 'x-gateway-provider',\n 'x-gateway-model',\n 'x-gateway-cost-usd',\n 'x-gateway-cache',\n 'x-gateway-trace-id',\n 'x-gateway-span-id',\n] as const;\n\n/**\n * Pulls the `x-gateway-*` metadata off a completion response.\n *\n * These are not decoration: `x-gateway-trace-id` is how the caller finds the completion\n * again in the trace explorer, and `x-gateway-cost-usd` is the only place the price of\n * the call appears. Both would be lost if only the body were returned.\n *\n * @param headers - Response headers from the gateway.\n * @returns Present headers, keyed without the `x-gateway-` prefix.\n */\nfunction gatewayMeta(headers: Headers): Record<string, string> {\n const meta: Record<string, string> = {};\n for (const name of GATEWAY_HEADERS) {\n const value = headers.get(name);\n if (value !== null && value !== '') meta[name.replace('x-gateway-', '')] = value;\n }\n return meta;\n}\n\n/**\n * The trace pointer for a summary line, or nothing when the gateway sent no trace id.\n *\n * The id has to be in the summary, not only in the JSON below it. The JSON also carries\n * `request-id`, another UUID, and a client that grabs the first UUID it sees passes\n * that one to `get_trace` and gets a 404. Naming the argument removes the guess.\n */\nfunction traceSuffix(meta: Record<string, string>): string {\n return meta['trace-id'] ? ` Open it with get_trace, trace_id ${meta['trace-id']}.` : '';\n}\n\n/** First choice's text, for the human-readable summary line. */\nfunction firstChoiceText(body: unknown): string {\n const choice = (body as { choices?: Array<{ message?: { content?: string | null } }> })?.choices?.[0];\n const content = choice?.message?.content;\n if (typeof content === 'string' && content.trim() !== '') return content.trim();\n return '(no text content — check tool_calls)';\n}\n\n/**\n * Tools that actually run models: the stored-prompt path, the raw path, the model\n * registry and spend.\n *\n * `run_prompt` is the one that matters. It is the whole platform in a single call —\n * registry render, alias resolution, bound tools, provider routing, pricing and tracing —\n * and it is what makes an MCP client able to *try* a prompt rather than only read it.\n */\nexport const gatewayTools: AnyToolDefinition[] = [\n defineTool({\n name: 'run_prompt',\n title: 'Run a stored prompt through the gateway',\n toolset: 'gateway',\n readOnlyHint: false,\n description:\n 'Render a stored prompt at an alias and send it to the model in one call. The ' +\n 'gateway resolves the alias, substitutes the variables, attaches the tools bound ' +\n 'to that alias, routes to the provider, prices the call and records a trace. ' +\n 'Omit `model` to use the version\\'s bound default model. Returns the completion ' +\n 'plus the trace id, so the run can be inspected afterwards with get_trace. ' +\n 'This is the tool for \"test this prompt\" or \"what does this prompt answer for X\".',\n inputSchema: {\n prompt: z.string().min(1).describe('Prompt name or UUID.'),\n alias: z.string().optional().describe('Alias to resolve. Default \"production\".'),\n variables: z.record(z.unknown()).optional().describe('Template variables for the render.'),\n model: z\n .string()\n .optional()\n .describe('Gateway model public name. Omit to use the version\\'s bound default model.'),\n max_tokens: z.number().int().positive().optional().describe('Cap on generated tokens.'),\n temperature: z.number().min(0).max(2).optional().describe('Sampling temperature.'),\n trace_name: z\n .string()\n .optional()\n .describe('Name to give the trace, so this run is findable later.'),\n },\n async handler(args, { client, config }) {\n const { name } = await resolvePromptIdAndName(client, args.prompt);\n const body: Record<string, unknown> = {\n prompt: {\n name,\n alias: args.alias ?? 'production',\n variables: args.variables ?? {},\n },\n };\n if (args.model !== undefined) body.model = args.model;\n if (args.max_tokens !== undefined) body.max_tokens = args.max_tokens;\n if (args.temperature !== undefined) body.temperature = args.temperature;\n\n const headers: Record<string, string> = {};\n if (args.trace_name !== undefined) {\n // Free-text headers must be percent-encoded — a raw non-ASCII value is rejected\n // by fetch before the request leaves the process. The server decodes it back.\n headers['x-trace-name'] = encodeURIComponent(args.trace_name);\n }\n\n const response = await client.requestRaw<unknown>('POST', '/gateway/chat/completions', {\n body,\n headers,\n });\n const meta = gatewayMeta(response.headers);\n return okResult(\n `Ran \"${name}\"@${args.alias ?? 'production'} on ${meta.model ?? 'the resolved model'}` +\n `${meta['cost-usd'] ? ` for $${meta['cost-usd']}` : ''}.${traceSuffix(meta)} Reply: ` +\n firstChoiceText(response.data).slice(0, 400),\n { completion: response.data, gateway: meta },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'chat_completion',\n title: 'Run a raw chat completion through the gateway',\n toolset: 'gateway',\n readOnlyHint: false,\n description:\n 'Send your own messages through the AcruxCore gateway — OpenAI-compatible, but ' +\n 'routed by the team\\'s provider connections, priced, budget-checked and traced. ' +\n 'Prefer run_prompt when the prompt already exists in the registry; use this for ' +\n 'a one-off. Streaming is not available over MCP: the reply comes back whole.',\n inputSchema: {\n model: z.string().min(1).describe('Gateway model public name, e.g. \"gpt-4o-mini\".'),\n messages: z.array(chatMessageSchema).min(1).describe('Chat messages, in order.'),\n max_tokens: z.number().int().positive().optional().describe('Cap on generated tokens.'),\n temperature: z.number().min(0).max(2).optional().describe('Sampling temperature.'),\n tool_refs: z\n .array(\n z.object({\n name: z.string().describe('Catalog tool name.'),\n alias: z.string().optional().describe('Tool alias. Default \"production\".'),\n version: z.number().int().positive().optional().describe('Pin an exact version instead.'),\n }),\n )\n .optional()\n .describe(\n 'Catalog tools to attach by name. Give an alias OR a version on a ref, never both.',\n ),\n trace_name: z.string().optional().describe('Name to give the trace.'),\n },\n async handler(args, { client, config }) {\n const body: Record<string, unknown> = { model: args.model, messages: args.messages };\n if (args.max_tokens !== undefined) body.max_tokens = args.max_tokens;\n if (args.temperature !== undefined) body.temperature = args.temperature;\n if (args.tool_refs !== undefined) body.tool_refs = args.tool_refs;\n\n const headers: Record<string, string> = {};\n if (args.trace_name !== undefined) headers['x-trace-name'] = encodeURIComponent(args.trace_name);\n\n const response = await client.requestRaw<unknown>('POST', '/gateway/chat/completions', {\n body,\n headers,\n });\n const meta = gatewayMeta(response.headers);\n return okResult(\n `Completion from ${meta.model ?? args.model}` +\n `${meta['cost-usd'] ? ` ($${meta['cost-usd']})` : ''}.${traceSuffix(meta)} Reply: ` +\n firstChoiceText(response.data).slice(0, 400),\n { completion: response.data, gateway: meta },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_models',\n title: 'List gateway models',\n toolset: 'gateway',\n readOnlyHint: true,\n description:\n 'List the models registered for this team, with the provider connection each one ' +\n 'routes to. Only these public names are valid in run_prompt, chat_completion, or a ' +\n 'version\\'s bound default model.',\n inputSchema: {},\n async handler(_args, { client, config }) {\n const models = await client.get<unknown>('/gateway/models');\n const count = Array.isArray(models)\n ? models.length\n : ((models as { data?: unknown[] })?.data?.length ?? 0);\n return okResult(`${count} registered model(s).`, models, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_gateway_usage',\n title: 'Get gateway usage and spend',\n toolset: 'gateway',\n readOnlyHint: true,\n description:\n 'Request counts, token counts, cost, cache-hit rate and error rate over a window, ' +\n 'bucketed by day, model, provider or virtual key. Defaults to the last 30 days. ' +\n 'Use this for \"what did we spend\" and \"which model costs the most\" questions.',\n inputSchema: {\n from: z.string().optional().describe('ISO date, inclusive start of the window.'),\n to: z.string().optional().describe('ISO date, exclusive end of the window.'),\n group_by: z\n .enum(['day', 'model', 'virtual_key', 'provider'])\n .optional()\n .describe('Bucket dimension. Default \"day\".'),\n virtual_key_id: z.string().uuid().optional().describe('Restrict to one virtual key.'),\n },\n async handler({ from, to, group_by, virtual_key_id }, { client, config }) {\n const usage = await client.get<{\n totals?: { requests?: number; costUsd?: number };\n buckets?: unknown[];\n }>('/gateway/usage', { from, to, group_by, virtual_key_id });\n const totals = usage.totals ?? {};\n return okResult(\n `${totals.requests ?? 0} request(s), $${totals.costUsd ?? 0} total, in ${\n usage.buckets?.length ?? 0\n } bucket(s).`,\n usage,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'get_spending_limits',\n title: 'Get budgets and virtual-key limits',\n toolset: 'gateway',\n readOnlyHint: true,\n description:\n 'Every spend budget on the team — team-wide or on one virtual key — with its period, ' +\n 'limit, live spend, what is left and when it resets, plus each virtual key\\'s rate ' +\n 'limits and model/provider allow-lists. Use this after a gateway call is refused with ' +\n 'HTTP 402 (budget spent) or 429 (rate limit) to see which limit caused it. Read-only: ' +\n 'budgets and keys are changed in the dashboard.',\n inputSchema: {},\n async handler(_args, { client, config }) {\n const [budgets, keys] = await Promise.all([\n client.get<BudgetRow[]>('/gateway/budgets'),\n client.get<VirtualKeyRow[]>('/gateway/keys'),\n ]);\n const keyNames = new Map(keys.map((k) => [k.id, k.name]));\n const limits = budgets.map((b) => ({\n id: b.id,\n scope: b.virtualKeyId === null ? 'team' : 'virtual_key',\n virtualKeyId: b.virtualKeyId,\n virtualKeyName: b.virtualKeyId === null ? null : (keyNames.get(b.virtualKeyId) ?? null),\n period: b.period,\n limitUsd: b.limitUsd,\n spendUsd: b.spendUsd,\n remainingUsd: Math.max(0, b.limitUsd - b.spendUsd),\n exhausted: b.spendUsd >= b.limitUsd,\n resetsAt: b.resetsAt,\n }));\n\n const summary =\n limits.length === 0\n ? `No budgets on this team, so the gateway never refuses a call for spend. ${keys.length} virtual key(s).`\n : `${limits.length} budget(s), ${keys.length} virtual key(s). ` +\n limits\n .map(\n (l) =>\n `${l.scope === 'team' ? 'Team' : `Key \"${l.virtualKeyName ?? l.virtualKeyId}\"`} ` +\n `${l.period}: $${l.spendUsd} of $${l.limitUsd} spent` +\n (l.exhausted ? ' (EXHAUSTED)' : '') +\n (l.resetsAt ? `, resets ${l.resetsAt}` : ''),\n )\n .join('; ') +\n '.';\n return okResult(summary, { budgets: limits, virtualKeys: keys }, config.maxTextBytes);\n },\n }),\n];\n\n/** One row of `GET /gateway/budgets`. */\ninterface BudgetRow {\n id: string;\n virtualKeyId: string | null;\n period: string;\n limitUsd: number;\n spendUsd: number;\n resetsAt: string | null;\n}\n\n/** One row of `GET /gateway/keys` — already masked by the API: no token, no hash. */\ninterface VirtualKeyRow {\n id: string;\n name: string;\n [field: string]: unknown;\n}\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { resolvePromptIdAndName, resolvePromptRef } from '../refs';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A chat message as stored in a prompt version's template. */\nconst messageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant']).describe('Message role.'),\n content: z.string().describe('Template text. Jinja2/nunjucks syntax: {{ variable }}.'),\n});\n\n/** A prompt reference accepted by every tool here. */\nconst promptRef = z\n .string()\n .min(1)\n .describe('Prompt name (e.g. \"customer-support\") or prompt UUID. Names are resolved for you.');\n\n/**\n * Tools for the prompt registry: browse, read, render, and move versions between aliases.\n *\n * The mental model these descriptions have to convey, because a model that misses it\n * calls the wrong tool: a **prompt** is a named container, a **version** is an immutable\n * commit of its messages, and an **alias** (`production`, `staging`, anything else) is a\n * moving pointer at one version. Committing never moves an alias; promoting is what\n * ships a change.\n */\nexport const promptTools: AnyToolDefinition[] = [\n defineTool({\n name: 'list_prompts',\n title: 'List prompts',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'List the prompts in the AcruxCore team, newest first. Use `search` to filter by ' +\n 'name or description substring. Returns the prompt id, name and description — ' +\n 'call get_prompt for versions and aliases.',\n inputSchema: {\n search: z.string().optional().describe('Substring filter over name and description.'),\n page: z.number().int().positive().optional().describe('1-based page number. Default 1.'),\n limit: z\n .number()\n .int()\n .positive()\n .max(100)\n .optional()\n .describe('Results per page, max 100. Default 20.'),\n },\n async handler({ search, page, limit }, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/prompts', {\n search,\n page,\n limit,\n });\n return okResult(listSummary('prompts', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_prompt',\n title: 'Get a prompt with its versions and aliases',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Read one prompt in full: its metadata, every committed version (number, template ' +\n 'variables, bound default model) and every alias with the version it points at. ' +\n 'This is the tool to call before committing or promoting, because it shows which ' +\n 'version each alias is currently serving.',\n inputSchema: {\n prompt: promptRef,\n include_messages: z\n .boolean()\n .optional()\n .describe(\n 'Also fetch the full message template of the newest version. Off by default ' +\n 'because templates can be long.',\n ),\n },\n async handler({ prompt, include_messages }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n\n // Three calls, one tool: \"show me this prompt\" is a single intention, and making\n // the model chain /prompts, /versions and /aliases itself is three chances to stop\n // after the first one and answer from incomplete data.\n const [detail, versions, aliases] = await Promise.all([\n client.get<Record<string, unknown>>(`/prompts/${id}`),\n client.get<{ data?: Array<{ versionNumber: number }> }>(`/prompts/${id}/versions`, {\n limit: 100,\n }),\n client.get<unknown[]>(`/prompts/${id}/aliases`),\n ]);\n\n let latestVersion: unknown = undefined;\n const newest = versions.data?.[0]?.versionNumber;\n if (include_messages && newest !== undefined) {\n latestVersion = await client.get(`/prompts/${id}/versions/${newest}`);\n }\n\n const aliasSummary = Array.isArray(aliases)\n ? aliases\n .map((a) => {\n const row = a as { alias?: string; versionNumber?: number };\n return `${row.alias}→v${row.versionNumber}`;\n })\n .join(', ')\n : '';\n\n return okResult(\n `Prompt \"${detail.name}\" — ${versions.data?.length ?? 0} version(s); aliases: ${\n aliasSummary || 'none'\n }.`,\n { prompt: detail, versions: versions.data ?? [], aliases, latestVersion },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'render_prompt',\n title: 'Render a prompt at an alias',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Render the version an alias currently points at, substituting template variables, ' +\n 'and return the finished messages plus the tool definitions bound to that alias. ' +\n 'This renders only — it calls no model. Use run_prompt to render and get a ' +\n 'completion in one step. Missing required variables come back as a ' +\n 'MISSING_VARIABLES error naming each one.',\n inputSchema: {\n prompt: promptRef,\n alias: z\n .string()\n .optional()\n .describe('Alias to resolve. Default \"production\".'),\n variables: z\n .record(z.unknown())\n .optional()\n .describe('Template variables, e.g. {\"name\":\"Alice\"}. Required ones come from the version.'),\n },\n async handler({ prompt, alias, variables }, { client, config }) {\n const { name } = await resolvePromptIdAndName(client, prompt);\n const resolvedAlias = alias ?? 'production';\n const rendered = await client.post<{\n messages?: unknown[];\n tools?: unknown[];\n versionNumber?: number;\n }>(`/prompts/${encodeURIComponent(name)}/${encodeURIComponent(resolvedAlias)}/render`, {\n variables: variables ?? {},\n });\n return okResult(\n `Rendered \"${name}\" at alias \"${resolvedAlias}\" (version ${rendered.versionNumber}): ` +\n `${rendered.messages?.length ?? 0} message(s), ${rendered.tools?.length ?? 0} bound tool(s).`,\n rendered,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'diff_prompt_versions',\n title: 'Diff two prompt versions',\n toolset: 'prompts',\n readOnlyHint: true,\n description:\n 'Return a unified diff between two committed versions of a prompt. The diff is ' +\n 'over the raw templates, not rendered output, so variable placeholders stay visible.',\n inputSchema: {\n prompt: promptRef,\n from_version: z.number().int().positive().describe('Version number to diff from.'),\n to_version: z.number().int().positive().describe('Version number to diff to.'),\n },\n async handler({ prompt, from_version, to_version }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const result = await client.get<{ diff?: string }>(`/prompts/${id}/versions/diff`, {\n from: from_version,\n to: to_version,\n });\n // A unified diff with no `@@` hunk means the message text is the same — the usual\n // cause is a commit that changed only the bound model. Say so, or an empty body\n // reads as a failed call.\n const identical = !(result.diff ?? '').includes('@@');\n return okResult(\n identical\n ? `The messages of v${from_version} and v${to_version} are identical. ` +\n 'The diff covers message text only; compare the bound models and settings ' +\n 'with get_prompt.'\n : `Diff of v${from_version} → v${to_version}.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'create_prompt',\n title: 'Create a prompt',\n toolset: 'prompts',\n readOnlyHint: false,\n description:\n 'Create an empty prompt container. It has no messages yet — the messages live in ' +\n 'versions, so follow this with commit_prompt_version. Fails with TOOL_NAME_TAKEN ' +\n 'style 409 semantics if the name is already used in the team.',\n inputSchema: {\n name: z\n .string()\n .min(1)\n .describe('Prompt name, used to reference it everywhere. Slug-like, e.g. \"customer-support\".'),\n description: z.string().optional().describe('What this prompt is for.'),\n },\n async handler({ name, description }, { client, config }) {\n const created = await client.post<{ id: string; name: string }>('/prompts', {\n name,\n description,\n });\n return okResult(\n `Created prompt \"${created.name}\" (${created.id}). It has no versions yet — ` +\n 'commit one with commit_prompt_version.',\n created,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'commit_prompt_version',\n title: 'Commit a prompt version',\n toolset: 'prompts',\n readOnlyHint: false,\n description:\n 'Commit a new immutable version of a prompt. Version numbers are sequential per ' +\n 'prompt. The FIRST commit auto-creates the \"production\" and \"staging\" aliases ' +\n 'pointing at v1; every later commit changes no alias at all, so nothing goes live ' +\n 'until you call promote_prompt_alias. Template variables are extracted from the ' +\n '{{ }} placeholders automatically.',\n inputSchema: {\n prompt: promptRef,\n messages: z\n .array(messageSchema)\n .min(1)\n .describe('The message template, in order. Use {{ variable }} for substitutions.'),\n model: z\n .string()\n .optional()\n .describe(\n 'Optional default gateway model for this version, by public name (e.g. ' +\n '\"gpt-4o-mini\"). Must already be registered for the team.',\n ),\n },\n async handler({ prompt, messages, model }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const version = await client.post<{\n versionNumber: number;\n variables?: string[];\n aliases?: unknown[];\n }>(`/prompts/${id}/versions`, { messages, model });\n const aliasNote = version.aliases\n ? ' Aliases production and staging were created pointing at it.'\n : ' No alias moved — promote it when you want it live.';\n return okResult(\n `Committed version ${version.versionNumber} with variables [${(version.variables ?? []).join(\n ', ',\n )}].${aliasNote}`,\n version,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'promote_prompt_alias',\n title: 'Promote an alias to a version',\n toolset: 'prompts',\n readOnlyHint: false,\n destructiveHint: true,\n description:\n 'Point an alias at a specific version number, creating the alias if it does not ' +\n 'exist. This is how a change ships, and how a rollback happens — promoting an ' +\n 'earlier version number rolls back. Promoting \"production\" changes what live ' +\n 'traffic renders immediately.',\n inputSchema: {\n prompt: promptRef,\n alias: z\n .string()\n .min(1)\n .describe('Alias to move, e.g. \"production\", \"staging\", \"canary\".'),\n version_number: z.number().int().positive().describe('Version number to point at.'),\n },\n async handler({ prompt, alias, version_number }, { client, config }) {\n const id = await resolvePromptRef(client, prompt);\n const result = await client.post<Record<string, unknown>>(\n `/prompts/${id}/aliases/${encodeURIComponent(alias)}/promote`,\n { version_number },\n );\n return okResult(\n `Alias \"${alias}\" now points at version ${version_number}.`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n];\n","import { z } from 'zod';\nimport { listSummary, okResult } from '../format';\nimport { defineTool, type AnyToolDefinition } from './types';\n\n/** A span as returned inside a trace tree, with its children. */\ninterface SpanNode {\n payload?: unknown;\n children?: SpanNode[];\n [key: string]: unknown;\n}\n\n/**\n * Removes captured input/output payloads from a span tree, in place on a copy.\n *\n * Payload capture is on by default for new teams, and a single LLM span can carry the\n * whole conversation. Reading one trace should not be able to spend a client's entire\n * context budget by accident, so the caller can ask for the shape without the contents.\n *\n * @param spans - Span tree from `GET /traces/:id`.\n * @returns A copy with every `payload` replaced by a marker.\n */\nfunction stripPayloads(spans: SpanNode[]): SpanNode[] {\n return spans.map((span) => {\n const copy: SpanNode = { ...span };\n if (copy.payload !== undefined && copy.payload !== null) {\n copy.payload = '[omitted — call get_trace with include_payloads=true]';\n }\n if (Array.isArray(copy.children)) copy.children = stripPayloads(copy.children);\n return copy;\n });\n}\n\n/**\n * Tools for observability: find runs, read one, aggregate them, and attach feedback.\n *\n * A trace is one request end to end; a span is one step inside it (`llm`, `tool`,\n * `retrieval`, …); a session groups traces belonging to one conversation. Those three\n * words appear in every description because picking the wrong level is the usual failure\n * — \"why was yesterday slow\" is `get_trace_analytics`, not a hundred `get_trace` calls.\n */\nexport const traceTools: AnyToolDefinition[] = [\n defineTool({\n name: 'search_traces',\n title: 'Search traces',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Find traces — one row per request — newest first, with cost, token count, span ' +\n 'count and duration. Filter by status, model, session, prompt version, free text, ' +\n 'or minimum latency/cost/tokens. The default window is the last 30 days. Use this ' +\n 'to locate a run, then get_trace to open it.',\n inputSchema: {\n q: z.string().optional().describe('Free text over trace/span names and span attributes.'),\n status: z.enum(['ok', 'error', 'unset']).optional().describe('Trace status filter.'),\n model: z.string().optional().describe('Exact model name on any span in the trace.'),\n session_id: z.string().optional().describe('Restrict to one session.'),\n prompt_version_id: z.string().uuid().optional().describe('Traces attributed to one prompt version.'),\n from: z.string().optional().describe('ISO 8601 start of the window.'),\n to: z.string().optional().describe('ISO 8601 end of the window.'),\n min_latency_ms: z.number().int().positive().optional().describe('Inclusive lower bound.'),\n min_cost_usd: z.number().positive().optional().describe('Inclusive lower bound.'),\n min_tokens: z.number().int().positive().optional().describe('Inclusive lower bound.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/traces', {\n q: args.q,\n status: args.status,\n model: args.model,\n session_id: args.session_id,\n prompt_version_id: args.prompt_version_id,\n from: args.from,\n to: args.to,\n min_latency_ms: args.min_latency_ms,\n min_cost_usd: args.min_cost_usd,\n min_tokens: args.min_tokens,\n page: args.page,\n limit: args.limit,\n });\n return okResult(listSummary('traces', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_trace',\n title: 'Get one trace with its span tree',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Open one trace: the header plus every span assembled into a parent/child tree, ' +\n 'each with its model, tokens, cost, latency, error message and — when the team ' +\n 'captures payloads — the input and output. Set include_payloads=false when the ' +\n 'trace is large and you only need its shape and timings.',\n inputSchema: {\n trace_id: z.string().uuid().describe('Trace UUID, from search_traces or a gateway call.'),\n include_payloads: z\n .boolean()\n .optional()\n .describe('Include captured span input/output. Default true.'),\n },\n async handler({ trace_id, include_payloads }, { client, config }) {\n const result = await client.get<{ trace?: Record<string, unknown>; spans?: SpanNode[] }>(\n `/traces/${trace_id}`,\n );\n const spans = include_payloads === false ? stripPayloads(result.spans ?? []) : result.spans;\n const header = result.trace ?? {};\n return okResult(\n `Trace \"${header.name}\" — status ${header.status}, ${header.spanCount} span(s), ` +\n `${header.totalTokens ?? 0} tokens, $${header.totalCostUsd ?? 0}.`,\n { trace: header, spans },\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'get_trace_analytics',\n title: 'Aggregate trace metrics',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'Aggregate span metrics over a window: request count, error rate, tokens, cost and ' +\n 'p50/p95/p99 latency, bucketed by day, model, session or prompt version. Default ' +\n 'window is the last 30 days. This is the tool for \"did latency regress\", \"which ' +\n 'model errors most\", \"what does this prompt version cost\".',\n inputSchema: {\n from: z.string().optional().describe('ISO date, start of the window.'),\n to: z.string().optional().describe('ISO date, end of the window.'),\n group_by: z\n .enum(['day', 'model', 'session', 'prompt_version'])\n .optional()\n .describe('Bucket dimension. Default \"day\".'),\n kind: z\n .enum(['llm', 'tool', 'retrieval', 'embedding', 'agent', 'chain', 'other'])\n .optional()\n .describe('Restrict to one span kind.'),\n model: z.string().optional().describe('Restrict to one exact model.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{\n totals?: { requests?: number; errorRate?: number; costUsd?: number };\n buckets?: unknown[];\n }>('/traces/analytics', args);\n const totals = result.totals ?? {};\n return okResult(\n `${totals.requests ?? 0} span(s), error rate ${totals.errorRate ?? 0}, $${\n totals.costUsd ?? 0\n }, in ${result.buckets?.length ?? 0} bucket(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'list_sessions',\n title: 'List sessions',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'List sessions — groups of traces belonging to one conversation — with the most ' +\n 'recent activity first. Default window is the last 30 days.',\n inputSchema: {\n q: z.string().optional().describe('Case-insensitive substring match on the session id.'),\n from: z.string().optional().describe('ISO 8601 start of the window.'),\n to: z.string().optional().describe('ISO 8601 end of the window.'),\n page: z.number().int().positive().optional().describe('1-based page number.'),\n limit: z.number().int().positive().max(100).optional().describe('Results per page, max 100.'),\n },\n async handler(args, { client, config }) {\n const result = await client.get<{ data?: unknown[]; total?: number }>('/sessions', args);\n return okResult(listSummary('sessions', result), result, config.maxTextBytes);\n },\n }),\n\n defineTool({\n name: 'get_session',\n title: 'Get one session',\n toolset: 'traces',\n readOnlyHint: true,\n description:\n 'One session\\'s summary plus its traces, newest first, capped at 100. Not date ' +\n 'filtered — the lookup is by session id alone.',\n inputSchema: {\n session_id: z.string().min(1).describe('The session id as your application set it.'),\n },\n async handler({ session_id }, { client, config }) {\n const result = await client.get<{ traces?: unknown[] }>(\n `/sessions/${encodeURIComponent(session_id)}`,\n );\n return okResult(\n `Session \"${session_id}\" — ${result.traces?.length ?? 0} trace(s).`,\n result,\n config.maxTextBytes,\n );\n },\n }),\n\n defineTool({\n name: 'submit_trace_feedback',\n title: 'Attach feedback to a trace',\n toolset: 'traces',\n readOnlyHint: false,\n description:\n 'Record a rating, label and/or comment against a trace, or against one span inside ' +\n 'it. At least one of rating, label or comment is required. Feedback is what later ' +\n 'becomes an evaluation dataset via the \"from feedback\" path, so a clear label is ' +\n 'worth more than a bare rating.',\n inputSchema: {\n trace_id: z.string().uuid().describe('Trace UUID.'),\n rating: z.number().int().min(-1).max(5).optional().describe('Integer rating, -1 to 5.'),\n label: z.string().max(200).optional().describe('Short label, e.g. \"wrong_answer\".'),\n comment: z.string().max(5000).optional().describe('Free-text detail.'),\n span_id: z.string().optional().describe('Span reference, for span-level feedback.'),\n source: z\n .enum(['user', 'developer', 'end_user', 'api'])\n .optional()\n .describe('Who the feedback came from. Default \"user\".'),\n },\n async handler({ trace_id, span_id, ...rest }, { client, config }) {\n const body: Record<string, unknown> = { ...rest };\n if (span_id !== undefined) body.spanId = span_id;\n const result = await client.post<{ id?: string }>(`/traces/${trace_id}/feedback`, body);\n return okResult(`Feedback recorded on trace ${trace_id}.`, result, config.maxTextBytes);\n },\n }),\n];\n","import type { McpServerConfig } from '../config';\nimport { catalogTools } from './catalog';\nimport { evaluationTools } from './evaluations';\nimport { gatewayTools } from './gateway';\nimport { promptTools } from './prompts';\nimport { traceTools } from './traces';\nimport type { AnyToolDefinition } from './types';\n\nexport type { AnyToolDefinition, ToolContext } from './types';\nexport { defineTool } from './types';\n\n/**\n * Every tool this server can register, in the order toolsets appear to a client.\n *\n * Order is deliberate rather than alphabetical: prompts first because that is the\n * product's centre of gravity, then the things that run (gateway, tools), then the\n * things that observe (traces, evaluations).\n */\nexport const ALL_TOOLS: AnyToolDefinition[] = [\n ...promptTools,\n ...gatewayTools,\n ...catalogTools,\n ...traceTools,\n ...evaluationTools,\n];\n\n/**\n * Selects the tools a given configuration should expose.\n *\n * Read-only mode *removes* mutating tools rather than refusing them at call time. A tool\n * that is absent from `tools/list` cannot be chosen by mistake, cannot be argued with,\n * and does not need the model to have read a warning in its description — which is the\n * whole point of handing an agent a read-only key in the first place.\n *\n * @param config - Resolved server configuration.\n * @returns The tools to register, in {@link ALL_TOOLS} order.\n */\nexport function selectTools(config: McpServerConfig): AnyToolDefinition[] {\n return ALL_TOOLS.filter(\n (tool) =>\n config.toolsets.includes(tool.toolset) && (!config.readOnly || tool.readOnlyHint),\n );\n}\n","import { McpConfigError } from './errors';\n\n/** Every toolset this server can expose. */\nexport const ALL_TOOLSETS = ['prompts', 'gateway', 'tools', 'traces', 'evaluations'] as const;\n\n/** One of the five toolset names. */\nexport type Toolset = (typeof ALL_TOOLSETS)[number];\n\n/** The AcruxCore cloud API. Overridden with `ACRUXCORE_BASE_URL` when self-hosting. */\nexport const DEFAULT_BASE_URL = 'https://api.acruxcore.com/api/v1';\n\n/** Alias the prompts primitive exposes when none is configured. */\nexport const DEFAULT_PROMPT_ALIAS = 'production';\n\n/**\n * Cap on the bytes of text any single tool result may contain.\n *\n * 40 000 is roughly 10k tokens — large enough for a page of traces or a full prompt\n * version, small enough that one careless `get_trace` on a payload-heavy trace cannot\n * eat a client's whole context window.\n */\nexport const DEFAULT_MAX_TEXT_BYTES = 40_000;\n\n/** Fully resolved server configuration. */\nexport interface McpServerConfig {\n /** AcruxCore base URL, normalised to end in `/api/v1`. */\n baseUrl: string;\n /** `acx_sk_…` API key used for every call. */\n apiKey: string;\n /** Toolsets to register, in `ALL_TOOLSETS` order. */\n toolsets: Toolset[];\n /** When true, mutating tools are never registered at all. */\n readOnly: boolean;\n /** Alias the MCP prompts primitive resolves registry prompts through. */\n promptAlias: string;\n /** Per-result text cap, in bytes. */\n maxTextBytes: number;\n /** Per-request HTTP timeout, in milliseconds. */\n timeoutMs: number;\n}\n\n/** Raw inputs to {@link resolveConfig}, so it can be unit-tested without touching `process`. */\nexport interface ConfigSources {\n env: Record<string, string | undefined>;\n argv: string[];\n}\n\n/**\n * Resolves the server configuration from environment variables, then CLI flags.\n *\n * CLI wins over env on purpose: the env is usually the MCP client's global config, and a\n * flag is what the user typed for *this* server entry.\n *\n * Recognised flags: `--base-url`, `--api-key`, `--toolsets`, `--read-only`,\n * `--prompt-alias`, `--max-text-bytes`, `--timeout-ms`.\n *\n * @param sources - Environment and argv (argv without the node/script prefix).\n * @returns The resolved configuration.\n * @throws {McpConfigError} If the API key is absent, a toolset name is unknown, or a\n * numeric flag is not a positive number.\n */\nexport function resolveConfig(sources: ConfigSources): McpServerConfig {\n const { env } = sources;\n const flags = parseFlags(sources.argv);\n\n const apiKey = (flags['api-key'] ?? env.ACRUXCORE_API_KEY ?? '').trim();\n if (!apiKey) {\n throw new McpConfigError(\n 'No AcruxCore API key. Set ACRUXCORE_API_KEY (or pass --api-key). ' +\n 'Create one in the dashboard under Settings → API keys.',\n );\n }\n\n const baseUrl = (flags['base-url'] ?? env.ACRUXCORE_BASE_URL ?? DEFAULT_BASE_URL).trim();\n\n const toolsetsRaw = (flags.toolsets ?? env.ACRUXCORE_MCP_TOOLSETS ?? '').trim();\n const toolsets = parseToolsets(toolsetsRaw);\n\n const readOnly = parseBoolean(flags['read-only'] ?? env.ACRUXCORE_MCP_READ_ONLY);\n\n const promptAlias =\n (flags['prompt-alias'] ?? env.ACRUXCORE_MCP_PROMPT_ALIAS ?? DEFAULT_PROMPT_ALIAS).trim() ||\n DEFAULT_PROMPT_ALIAS;\n\n const maxTextBytes = parsePositiveInt(\n flags['max-text-bytes'] ?? env.ACRUXCORE_MCP_MAX_TEXT_BYTES,\n DEFAULT_MAX_TEXT_BYTES,\n 'max-text-bytes',\n );\n\n const timeoutMs = parsePositiveInt(\n flags['timeout-ms'] ?? env.ACRUXCORE_MCP_TIMEOUT_MS,\n 60_000,\n 'timeout-ms',\n );\n\n return { baseUrl, apiKey, toolsets, readOnly, promptAlias, maxTextBytes, timeoutMs };\n}\n\n/**\n * Parses `--flag value` and `--flag=value` pairs out of argv.\n *\n * A flag with no value (`--read-only`) maps to `\"true\"`, which is what\n * {@link parseBoolean} expects, so boolean flags need no special case at the call site.\n *\n * @param argv - Arguments after the script name.\n * @returns Flag name (without `--`) to string value.\n */\nfunction parseFlags(argv: string[]): Record<string, string | undefined> {\n const out: Record<string, string | undefined> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (!arg.startsWith('--')) continue;\n\n const eq = arg.indexOf('=');\n if (eq !== -1) {\n out[arg.slice(2, eq)] = arg.slice(eq + 1);\n continue;\n }\n\n const name = arg.slice(2);\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('--')) {\n out[name] = next;\n i++;\n } else {\n out[name] = 'true';\n }\n }\n return out;\n}\n\n/**\n * Turns a comma-separated toolset list into a validated, de-duplicated array.\n *\n * An empty value means \"all of them\" — the useful default for someone who has just\n * installed the server and does not yet know what the toolsets are.\n *\n * @param raw - Comma-separated names, `all`, or empty.\n * @returns Toolsets in `ALL_TOOLSETS` order.\n * @throws {McpConfigError} If any name is not a known toolset.\n */\nexport function parseToolsets(raw: string): Toolset[] {\n if (!raw || raw.toLowerCase() === 'all') return [...ALL_TOOLSETS];\n\n const requested = raw\n .split(',')\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean);\n\n const unknown = requested.filter((name) => !ALL_TOOLSETS.includes(name as Toolset));\n if (unknown.length > 0) {\n throw new McpConfigError(\n `Unknown toolset(s): ${unknown.join(', ')}. Valid toolsets: ${ALL_TOOLSETS.join(', ')}.`,\n );\n }\n\n // Returned in ALL_TOOLSETS order rather than request order so `tools/list` is stable\n // no matter how the user happened to type the flag.\n return ALL_TOOLSETS.filter((name) => requested.includes(name));\n}\n\n/**\n * Reads a boolean from a flag or env value.\n *\n * @param value - Raw string, possibly undefined.\n * @returns True for `true`, `1`, `yes` and `on` (case-insensitive); false otherwise.\n */\nfunction parseBoolean(value: string | undefined): boolean {\n if (value === undefined) return false;\n return ['true', '1', 'yes', 'on'].includes(value.trim().toLowerCase());\n}\n\n/**\n * Reads a positive integer, falling back to a default when unset.\n *\n * @param value - Raw string, possibly undefined.\n * @param fallback - Value to use when unset or empty.\n * @param name - Flag name, used in the error message.\n * @returns The parsed integer.\n * @throws {McpConfigError} If the value is present but not a positive integer.\n */\nfunction parsePositiveInt(value: string | undefined, fallback: number, name: string): number {\n if (value === undefined || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new McpConfigError(`--${name} must be a positive integer, got \"${value}\".`);\n }\n return parsed;\n}\n"],"mappings":"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","names":["import_mcp","message","import_zod","import_zod","import_zod","import_zod"]}
|