/**
 * Idempotent writer for Claude Code's USER-level MCP server registry (G.8).
 *
 * Writes two entries into `~/.claude.json` (or whatever path the caller
 * supplies — tests inject a tmpdir path):
 *
 *   - `opensquid`       → `node <root>/dist/mcp/server.js`
 *   - `opensquid-chat`  → `node <root>/dist/mcp/chat-bridge-server.js`
 *
 * Both entries are tagged `'@opensquid': true` — the marker contract is the
 * SAME shape as G.1's `settings-writer.ts` hook entries, which lets future
 * wizard passes (and `opensquid doctor`) distinguish entries this writer
 * owns from third-party MCP entries (claude.ai-Figma, Notion, Vercel, etc.).
 *
 * Every non-`mcpServers` key in `~/.claude.json` is preserved verbatim via
 * spread round-trip — that file holds tons of per-project state in the
 * real-world install and MUST NOT get clobbered.
 *
 * Legacy detection: an existing `opensquid` entry pointing at the broken
 * `node <abs>/opensquid/dist/index.js` shape (which silently no-ops — see
 * memory `opensquid-dist-index-entrypoint-gotcha`) is replaced with the
 * correct `dist/mcp/server.js` path. Detection trips on (a) the
 * `'@opensquid': true` marker OR (b) command='node' AND any arg ending in
 * `dist/index.js` under an `opensquid` path segment — same conservative
 * stance G.1's `LEGACY_OPENSQUID_PATTERN` takes.
 *
 * A `.bak` snapshot is written BEFORE any mutation. The marker contract is
 * the first line of defense; .bak is the last.
 *
 * Engine-vocabulary discipline: this module is the ONLY G.8 file that
 * names Claude Code's `~/.claude.json` layout. The CLI surface in
 * `../cli/mcp.ts` is harness-agnostic input/output plumbing only.
 *
 * Imported by: src/setup/cli/mcp.ts.
 */
export interface McpServerEntry {
    type?: 'stdio' | 'http';
    command?: string;
    args?: string[];
    env?: Record<string, string>;
    '@opensquid'?: boolean;
    [k: string]: unknown;
}
interface ClaudeUserConfig {
    mcpServers?: Record<string, McpServerEntry>;
    [k: string]: unknown;
}
export declare function isLegacyOpensquidEntry(entry: McpServerEntry | undefined): boolean;
export interface DesiredEntries {
    opensquid: McpServerEntry;
    'opensquid-chat': McpServerEntry;
}
export declare function buildDesiredEntries(opensquidRepoRoot: string): DesiredEntries;
export interface McpWriteResult {
    /** Entry names added fresh (no prior entry under that key). */
    added: string[];
    /** Entry names replaced (prior entry existed — opensquid-owned or legacy). */
    replaced: string[];
    /** Number of unrelated mcpServers entries preserved verbatim. */
    preserved: number;
    /** Path to the `.bak` snapshot. */
    backupPath: string;
}
/** Pure projection. Disk-untouched. Used by both writer and `--dry-run`. */
export declare function projectOpensquidMcp(input: ClaudeUserConfig, opensquidRepoRoot: string): {
    output: ClaudeUserConfig;
    added: string[];
    replaced: string[];
    preserved: number;
};
/**
 * Write opensquid's two MCP entries into `~/.claude.json` (path injected).
 * Creates a `.bak` snapshot (`{}` when the file did not exist). 2-space
 * JSON indentation matches Claude Code's own format, so `diff <file>.bak
 * <file>` highlights only the mcpServers delta.
 */
export declare function writeOpensquidMcp(claudeConfigPath: string, opensquidRepoRoot: string): Promise<McpWriteResult>;
/** ENOENT → `{}` (first-run case). All other errors propagate. */
export declare function readClaudeUserConfig(path: string): Promise<ClaudeUserConfig>;
export {};
//# sourceMappingURL=mcp-writer.d.ts.map