import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { type Config } from "./config.js"; import type { ToolContext, ToolDefinition } from "./tools/types.js"; export declare const SERVER_NAME = "specguard-mcp"; export declare const SERVER_VERSION: string; export interface CreateServerOptions { /** Overrides the tools served. Defaults to the registry. Tests pass their own. */ readonly tools?: readonly ToolDefinition[]; readonly config?: Config; readonly runCommand?: ToolContext["runCommand"]; readonly fetch?: typeof globalThis.fetch; } /** * Builds the MCP server: two request handlers over the tool registry, and no * knowledge of any tool in particular. * * Everything a tool touches the world with — config, subprocesses, `fetch` — is * resolved once here and handed down as a `ToolContext`. That is what makes the * whole surface testable without a SpecGuard deployment or an installed gem, and * it is a property a tool added later inherits rather than has to arrange. * * The transport is NOT chosen here. `createServer` returns an unconnected * `Server`, and `bin/specguard-mcp.ts` connects it to stdio. SPGD-310 scopes * stdio only and puts HTTP/SSE in a later follow-up; keeping the choice out of * this file is what makes that follow-up a new entrypoint rather than a change * to the server. */ export declare function createServer(options?: CreateServerOptions): Server; /** * This package's version, read from the package manifest rather than kept as a * literal beside it. * * The literal this replaced was written at bootstrap and never revisited: the * release bot bumps `package.json` alone, so every initialize handshake after * the first release told every client the bridge was still the bootstrap * version. Nothing caught the drift in that bootstrap era: then, every reader * cell of the constant relayed the stale literal unchecked, and no test named * it. That era is over. Whatever a reader cell does with `SERVER_VERSION`, it * now sees the tracked value — and the suite now names the constant too. The * per-request User-Agent (`requestUserAgent()` in * `src/support/specguard-api.ts`) stamps `specguard-mcp/` onto every * outbound call, and the transport tests assert that header against this very * constant. The manifest-walk change kept `SERVER_VERSION` a const export and * left every reader cell's access to it untouched; the ONLY change is that * its value now tracks the release instead of the bootstrap. * * `SERVER_VERSION`'s module-scope initialization is the single read: the walk * runs once at import, and every later reader cell sees the cached result. * * The read is a walk UP from this module to the package root, bounded and * name-checked — the shape specguard-ts landed for the same disease (its * fixed `../package.json` read resolved against the module's OWN directory and * answered `"0.0.0"` in every built layout). The layouts this bridge ships * put the compiled module at `dist/src/server.js`, `.test-build/src/server.js` * (the test build), or `src/server.ts` (the dev loader), and an install at * `node_modules/specguard-mcp/dist/src/` — in each, walking up finds the * manifest that names this package, where a fixed relative read would name * `dist/package.json` / `.test-build/package.json` (both absent; `files` * ships dist only, so src/ is not even present in an installed tree). The * name check keeps an ancestor manifest — a monorepo or a vendoring * application's package.json — from being mistaken for this package's, and a * tree with no matching manifest answers the `"0.0.0"` sentinel without * throwing: `createServer` must never gain a failure mode, and a version * that says "unknown" is honest where a crashed boot is not. * * `start` is the injection seam the tests drive the fallback and name-check * arms through: a filesystem path whose directory the walk begins from, * defaulting to this module's own file. Production always takes the default; * tests pass temp-tree paths so the walk can be exercised in layouts the * repo does not ship. */ export declare function readPackageVersion(start?: string): string;