From d8f8f394f9787125fa2f868efa2f5c161f89152c Mon Sep 17 00:00:00 2001 From: cneicy Date: Thu, 20 Aug 2026 17:39:36 +0800 Subject: [PATCH] refactor: use CraftTable naming in OAuth client --- dist/cli.js | 8 ++++---- dist/cli.js.map | 4 ++-- src/oauthProvider.ts | 2 +- src/remote.ts | 8 ++++---- test/configAndOAuth.test.ts | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dist/cli.js b/dist/cli.js index dcd880a..7404cd7 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -505,7 +505,7 @@ var OAuthCallbackServer = class { // src/oauthProvider.ts import { randomBytes, timingSafeEqual } from "node:crypto"; -var GameCraftOAuthProvider = class { +var CraftTableOAuthProvider = class { constructor(options, tokenStore, discoveryStore, onRedirect, state = randomBytes(32).toString("base64url")) { this.options = options; this.tokenStore = tokenStore; @@ -577,7 +577,7 @@ var GameCraftOAuthProvider = class { async function connectRemote(options, tokenStore, discoveryStore, serviceToken = process.env.CRAFTTABLE_MCP_TOKEN?.trim()) { const tokens = await tokenStore.get(credentialAccount(options)); if (tokens) { - const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, () => { + const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, () => { throw new Error("OAuth login is required; run `crafttable-mcp login`"); }); return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, { authProvider: provider }), "oauth"); @@ -594,7 +594,7 @@ async function loginRemote(options, tokenStore, discoveryStore, input = { browse `)); await requireOAuthProtectedResourceMetadata(options.url); let authorizationUrl; - const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, async (url) => { + const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, async (url) => { authorizationUrl = url; if (!input.browser) { writeLine(`Open this URL to log in: @@ -603,7 +603,7 @@ ${url.toString()}`); } try { await open(url.toString(), { wait: false }); - writeLine("Opened the system browser for Game-CraftTable login."); + writeLine("Opened the system browser for CraftTable login."); } catch (error) { writeLine(`Could not open the browser (${errorMessage(error)}). Open this URL manually: ${url.toString()}`); diff --git a/dist/cli.js.map b/dist/cli.js.map index b873fea..861f4ab 100644 --- a/dist/cli.js.map +++ b/dist/cli.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/cli.ts", "../src/agents.ts", "../src/config.ts", "../src/bridge.ts", "../src/remote.ts", "../src/callbackServer.ts", "../src/oauthProvider.ts", "../src/credentials.ts"], - "sourcesContent": ["#!/usr/bin/env node\n\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { configureAgents, type AgentTarget, unconfigureAgents } from \"./agents.js\";\nimport { serveBridge } from \"./bridge.js\";\nimport { type ClientOptions, credentialAccount, DiscoveryStore, resolveClientOptions } from \"./config.js\";\nimport { KeyringTokenStore } from \"./credentials.js\";\nimport { connectRemote, loginRemote, logoutRemote } from \"./remote.js\";\n\ntype ConnectionFlags = { url?: string; clientId?: string; callbackPort?: string };\n\nconst program = new Command()\n .name(\"crafttable-mcp\")\n .description(\"OAuth client and stdio bridge for CraftTable MCP\")\n .version(\"0.1.3\");\n\nwithConnection(program.command(\"login\").description(\"Log in through the system browser\"))\n .option(\"--no-browser\", \"print the authorization URL instead of opening it\")\n .option(\"--timeout \", \"OAuth callback timeout\", \"600000\")\n .action(async (flags: ConnectionFlags & { browser: boolean; timeout: string }) => {\n const options = connectionOptions(flags);\n const timeoutMs = positiveInteger(flags.timeout, \"OAuth callback timeout\");\n const result = await loginRemote(options, new KeyringTokenStore(), new DiscoveryStore(), { browser: flags.browser, timeoutMs });\n printJson({ loggedIn: true, alreadyAuthenticated: result.alreadyAuthenticated, server: options.url.toString(), tools: result.toolCount });\n });\n\nwithConnection(program.command(\"status\").description(\"Check saved login state and remote MCP connectivity\"))\n .action(async (flags: ConnectionFlags) => {\n const options = connectionOptions(flags);\n const tokens = await new KeyringTokenStore().get(credentialAccount(options));\n const connection = await connectRemote(options, new KeyringTokenStore(), new DiscoveryStore());\n try {\n const tools = await connection.client.listTools();\n printJson({\n loggedIn: Boolean(tokens),\n authentication: connection.authentication,\n connected: true,\n server: options.url.toString(),\n tools: tools.tools.length,\n });\n } finally {\n await connection.close();\n }\n });\n\nwithConnection(program.command(\"logout\").description(\"Revoke OAuth tokens and remove the local credential\"))\n .option(\"--local-only\", \"remove local credentials without contacting the authorization server\")\n .action(async (flags: ConnectionFlags & { localOnly?: boolean }) => {\n const options = connectionOptions(flags);\n const result = await logoutRemote(options, new KeyringTokenStore(), new DiscoveryStore(), Boolean(flags.localOnly));\n printJson({ loggedIn: false, credentialRemoved: result.hadCredential, revoked: result.revoked, localOnly: Boolean(flags.localOnly) });\n });\n\nwithConnection(program.command(\"tools\").description(\"List remote MCP tools\"))\n .action(async (flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson(await client.listTools())));\n\nwithConnection(program.command(\"resources\").description(\"List remote MCP resources and resource templates\"))\n .action(async (flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson({\n resources: (await client.listResources()).resources,\n resourceTemplates: (await client.listResourceTemplates()).resourceTemplates,\n })));\n\nwithConnection(program.command(\"read \").description(\"Read an MCP resource\"))\n .action(async (uri: string, flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson(await client.readResource({ uri }))));\n\nwithConnection(program.command(\"call [json]\").description(\"Call an MCP tool\"))\n .action(async (tool: string, json: string | undefined, flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => {\n printJson(await client.callTool({ name: tool, arguments: parseObject(json ?? \"{}\") }));\n }));\n\nwithConnection(program.command(\"serve\").description(\"Run the local stdio bridge\"))\n .action(async (flags: ConnectionFlags) => {\n await serveBridge(connectionOptions(flags), new KeyringTokenStore(), new DiscoveryStore());\n });\n\nfor (const operation of [\"configure\", \"unconfigure\"] as const) {\n withConnection(program.command(`${operation} `).description(`${operation === \"configure\" ? \"Add\" : \"Remove\"} the stdio bridge and CraftTable Skill in Codex, Claude Code, or OpenCode`))\n .option(\"--dry-run\", \"show the planned changes without writing\")\n .option(\"--force\", \"replace a conflicting entry without prompting\")\n .action(async (agent: AgentTarget, flags: ConnectionFlags & { dryRun?: boolean; force?: boolean }) => {\n const cliEntry = fileURLToPath(import.meta.url);\n if (!cliEntry.endsWith(\".js\")) throw new Error(\"Agent configuration requires the built CLI; run `npm --prefix apps/mcp-client run build` first\");\n const input = {\n target: agent,\n options: connectionOptions(flags),\n cliEntry,\n dryRun: Boolean(flags.dryRun),\n force: Boolean(flags.force),\n };\n const result = operation === \"configure\" ? await configureAgents(input) : await unconfigureAgents(input);\n printJson({ result });\n });\n}\n\nfunction withConnection(command: Command): Command {\n return command\n .option(\"--url \", \"MCP Streamable HTTP URL\")\n .option(\"--client-id \", \"pre-registered OAuth public client ID\")\n .option(\"--callback-port \", \"fixed localhost OAuth callback port\");\n}\n\nfunction connectionOptions(flags: ConnectionFlags): ClientOptions {\n return resolveClientOptions(flags);\n}\n\nasync function withClient(options: ClientOptions, action: (client: Awaited>[\"client\"]) => Promise): Promise {\n const connection = await connectRemote(options, new KeyringTokenStore(), new DiscoveryStore());\n try {\n await action(connection.client);\n } finally {\n await connection.close();\n }\n}\n\nfunction parseObject(raw: string): Record {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new Error(\"Tool arguments must be a JSON object\");\n }\n if (!value || Array.isArray(value) || typeof value !== \"object\") throw new Error(\"Tool arguments must be a JSON object\");\n return value as Record;\n}\n\nfunction positiveInteger(value: string, name: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) throw new Error(`${name} must be a positive integer`);\n return parsed;\n}\n\nfunction printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nprogram.parseAsync().catch((error: unknown) => {\n process.stderr.write(`CraftTable MCP failed: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n});\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { applyEdits, modify, parse } from \"jsonc-parser\";\nimport spawn from \"cross-spawn\";\nimport type { ClientOptions } from \"./config.js\";\nimport { errorMessage } from \"./config.js\";\n\nexport const SERVER_NAME = \"crafttable\";\nexport type AgentName = \"codex\" | \"claude\" | \"opencode\";\nexport type AgentTarget = AgentName | \"all\";\nexport type SkillAction = \"installed\" | \"replaced\" | \"removed\" | \"unchanged\" | \"absent\" | \"preserved\" | \"would-install\" | \"would-replace\" | \"would-remove\" | \"would-preserve\";\n\nexport type CommandResult = { code: number; stdout: string; stderr: string };\nexport interface CommandRunner {\n run(command: string, args: string[]): Promise;\n}\n\nexport type ConfigureInput = {\n target: AgentTarget;\n options: ClientOptions;\n cliEntry: string;\n nodePath?: string;\n dryRun?: boolean;\n force?: boolean;\n env?: NodeJS.ProcessEnv;\n runner?: CommandRunner;\n confirm?: (message: string) => Promise;\n opencodePath?: string;\n skillSource?: string;\n skillPaths?: Partial>;\n};\n\nexport type ConfigureResult = {\n agent: AgentName;\n action: \"added\" | \"replaced\" | \"removed\" | \"unchanged\" | \"absent\" | \"would-add\" | \"would-replace\" | \"would-remove\";\n skillAction: SkillAction;\n};\n\nexport async function configureAgents(input: ConfigureInput): Promise {\n const agents = expandTarget(input.target);\n const command = launchCommand(input.options, input.cliEntry, input.nodePath ?? process.execPath);\n const runner = input.runner ?? new SpawnCommandRunner();\n const results: ConfigureResult[] = [];\n for (const agent of agents) {\n const mcpResult = agent === \"opencode\"\n ? await configureOpenCode(input, command)\n : await configureCliAgent(agent, command, input, runner);\n const skillAction = await configureAgentSkill(agent, input);\n results.push({ ...mcpResult, skillAction });\n }\n return results;\n}\n\nexport async function unconfigureAgents(input: ConfigureInput): Promise {\n const agents = expandTarget(input.target);\n const runner = input.runner ?? new SpawnCommandRunner();\n const results: ConfigureResult[] = [];\n for (const agent of agents) {\n let mcpResult: Omit;\n if (agent === \"opencode\") {\n mcpResult = await unconfigureOpenCode(input);\n } else {\n mcpResult = await unconfigureCliAgent(agent, input, runner);\n }\n const skillAction = await unconfigureAgentSkill(agent, input);\n results.push({ ...mcpResult, skillAction });\n }\n return results;\n}\n\nasync function unconfigureCliAgent(\n agent: \"codex\" | \"claude\",\n input: ConfigureInput,\n runner: CommandRunner,\n): Promise> {\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n const existing = await probeCliAgent(agent, runner);\n if (!existing.exists) return { agent, action: \"absent\" };\n if (input.dryRun) return { agent, action: \"would-remove\" };\n const args = agent === \"codex\"\n ? [\"mcp\", \"remove\", SERVER_NAME]\n : [\"mcp\", \"remove\", \"--scope\", \"user\", SERVER_NAME];\n await requireSuccess(runner.run(executable, args), `${agent} MCP removal`);\n return { agent, action: \"removed\" };\n}\n\nexport function launchCommand(options: ClientOptions, cliEntry: string, nodePath: string): string[] {\n return [\n path.resolve(nodePath),\n path.resolve(cliEntry),\n \"serve\",\n \"--url\", options.url.toString(),\n \"--client-id\", options.clientId,\n \"--callback-port\", String(options.callbackPort),\n ];\n}\n\nasync function configureCliAgent(\n agent: \"codex\" | \"claude\",\n command: string[],\n input: ConfigureInput,\n runner: CommandRunner,\n): Promise> {\n const existing = await probeCliAgent(agent, runner);\n if (existing.exists && outputMatchesCommand(existing.output, command)) return { agent, action: \"unchanged\" };\n if (existing.exists && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`${agent} already has a different ${SERVER_NAME} MCP entry; use --force to replace it`);\n if (!await confirm(`${agent} already has a different ${SERVER_NAME} MCP entry. Replace it?`)) {\n throw new Error(`${agent} MCP configuration was not changed`);\n }\n }\n const action = existing.exists ? \"replaced\" : \"added\";\n if (input.dryRun) return { agent, action: existing.exists ? \"would-replace\" : \"would-add\" };\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n if (existing.exists) {\n const removeArgs = agent === \"codex\"\n ? [\"mcp\", \"remove\", SERVER_NAME]\n : [\"mcp\", \"remove\", \"--scope\", \"user\", SERVER_NAME];\n await requireSuccess(runner.run(executable, removeArgs), `${agent} MCP replacement cleanup`);\n }\n const addArgs = agent === \"codex\"\n ? [\"mcp\", \"add\", SERVER_NAME, \"--\", ...command]\n : [\"mcp\", \"add\", \"--scope\", \"user\", SERVER_NAME, \"--\", ...command];\n await requireSuccess(runner.run(executable, addArgs), `${agent} MCP registration`);\n return { agent, action };\n}\n\nasync function probeCliAgent(agent: \"codex\" | \"claude\", runner: CommandRunner): Promise<{ exists: boolean; output: string }> {\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n const args = agent === \"codex\"\n ? [\"mcp\", \"get\", SERVER_NAME, \"--json\"]\n : [\"mcp\", \"get\", SERVER_NAME];\n const result = await runner.run(executable, args);\n if (result.code === 0) return { exists: true, output: result.stdout };\n const combined = `${result.stdout}\\n${result.stderr}`;\n if (/not found|does not exist|no mcp server|not configured|unknown server/i.test(combined)) return { exists: false, output: combined };\n throw new Error(`Could not inspect ${agent} MCP configuration: ${safeCommandError(result)}`);\n}\n\nfunction outputMatchesCommand(output: string, command: string[]): boolean {\n try {\n const document = JSON.parse(output) as unknown;\n if (findCommand(document, command)) return true;\n } catch {\n // Claude currently returns a human-readable record.\n }\n return command.every((part) => output.includes(part));\n}\n\nfunction findCommand(value: unknown, command: string[]): boolean {\n if (!value || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return value.some((item) => findCommand(item, command));\n const record = value as Record;\n if (typeof record.command === \"string\" && Array.isArray(record.args)) {\n const candidate = [record.command, ...record.args.filter((item): item is string => typeof item === \"string\")];\n if (candidate.length === command.length && candidate.every((item, index) => item === command[index])) return true;\n }\n return Object.values(record).some((item) => findCommand(item, command));\n}\n\nasync function configureOpenCode(input: ConfigureInput, command: string[]): Promise> {\n const filePath = input.opencodePath ?? defaultOpenCodePath(input.env);\n const original = await readOptionalFile(filePath) ?? \"{}\\n\";\n const document = parse(original) as { mcp?: Record } | undefined;\n const existing = document?.mcp?.[SERVER_NAME] as { type?: unknown; command?: unknown; enabled?: unknown } | undefined;\n const desired = { type: \"local\", command, enabled: true };\n if (existing && existing.type === desired.type && existing.enabled === true && arraysEqual(existing.command, command)) {\n return { agent: \"opencode\", action: \"unchanged\" };\n }\n if (existing && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`opencode already has a different ${SERVER_NAME} MCP entry; use --force to replace it`);\n if (!await confirm(`opencode already has a different ${SERVER_NAME} MCP entry. Replace it?`)) {\n throw new Error(\"opencode MCP configuration was not changed\");\n }\n }\n if (input.dryRun) return { agent: \"opencode\", action: existing ? \"would-replace\" : \"would-add\" };\n const updated = applyEdits(original, modify(original, [\"mcp\", SERVER_NAME], desired, {\n formattingOptions: { insertSpaces: true, tabSize: 2, eol: \"\\n\" },\n }));\n await backupAndAtomicWrite(filePath, updated, await readOptionalFile(filePath) !== undefined);\n return { agent: \"opencode\", action: existing ? \"replaced\" : \"added\" };\n}\n\nasync function unconfigureOpenCode(input: ConfigureInput): Promise> {\n const filePath = input.opencodePath ?? defaultOpenCodePath(input.env);\n const original = await readOptionalFile(filePath);\n if (original === undefined) return { agent: \"opencode\", action: \"absent\" };\n const document = parse(original) as { mcp?: Record } | undefined;\n if (!document?.mcp || !(SERVER_NAME in document.mcp)) return { agent: \"opencode\", action: \"absent\" };\n if (input.dryRun) return { agent: \"opencode\", action: \"would-remove\" };\n const updated = applyEdits(original, modify(original, [\"mcp\", SERVER_NAME], undefined, {\n formattingOptions: { insertSpaces: true, tabSize: 2, eol: \"\\n\" },\n }));\n await backupAndAtomicWrite(filePath, updated, true);\n return { agent: \"opencode\", action: \"removed\" };\n}\n\nexport function defaultOpenCodePath(env: NodeJS.ProcessEnv = process.env): string {\n const base = env.XDG_CONFIG_HOME || (process.platform === \"win32\"\n ? path.join(env.USERPROFILE || os.homedir(), \".config\")\n : path.join(os.homedir(), \".config\"));\n return path.join(base, \"opencode\", \"opencode.json\");\n}\n\nexport function bundledSkillPath(cliEntry: string): string {\n return path.resolve(path.dirname(cliEntry), \"..\", \"skills\", SERVER_NAME);\n}\n\nexport function defaultSkillPath(agent: AgentName, env: NodeJS.ProcessEnv = process.env): string {\n const home = env.USERPROFILE || env.HOME || os.homedir();\n if (agent === \"codex\") return path.join(env.CODEX_HOME || path.join(home, \".codex\"), \"skills\", SERVER_NAME);\n if (agent === \"claude\") return path.join(home, \".claude\", \"skills\", SERVER_NAME);\n return path.join(path.dirname(defaultOpenCodePath(env)), \"skills\", SERVER_NAME);\n}\n\nasync function configureAgentSkill(agent: AgentName, input: ConfigureInput): Promise {\n const source = input.skillSource ?? bundledSkillPath(input.cliEntry);\n const destination = input.skillPaths?.[agent] ?? defaultSkillPath(agent, input.env);\n const sourceFiles = await readSkillDirectory(source, true);\n if (!sourceFiles) throw new Error(`Bundled Skill directory is missing: ${source}`);\n const existingFiles = await readSkillDirectory(destination, false);\n if (existingFiles && skillFilesEqual(existingFiles, sourceFiles)) return \"unchanged\";\n\n if (existingFiles && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`${agent} already has a different ${SERVER_NAME} Skill; use --force to replace it`);\n if (!await confirm(`${agent} already has a different ${SERVER_NAME} Skill. Replace it?`)) {\n throw new Error(`${agent} Skill configuration was not changed`);\n }\n }\n\n if (input.dryRun) return existingFiles ? \"would-replace\" : \"would-install\";\n if (existingFiles) await backupSkillDirectory(destination);\n await replaceSkillDirectory(source, destination, Boolean(existingFiles));\n return existingFiles ? \"replaced\" : \"installed\";\n}\n\nasync function unconfigureAgentSkill(agent: AgentName, input: ConfigureInput): Promise {\n const source = input.skillSource ?? bundledSkillPath(input.cliEntry);\n const destination = input.skillPaths?.[agent] ?? defaultSkillPath(agent, input.env);\n const existingFiles = await readSkillDirectory(destination, false);\n if (!existingFiles) return \"absent\";\n const sourceFiles = await readSkillDirectory(source, true);\n if (!sourceFiles) throw new Error(`Bundled Skill directory is missing: ${source}`);\n const managed = skillFilesEqual(existingFiles, sourceFiles);\n if (!managed && !input.force) return input.dryRun ? \"would-preserve\" : \"preserved\";\n if (input.dryRun) return \"would-remove\";\n if (!managed) await backupSkillDirectory(destination);\n await rm(destination, { recursive: true, force: true });\n return \"removed\";\n}\n\nasync function readSkillDirectory(directory: string, required: boolean): Promise | undefined> {\n const files = new Map();\n const walk = async (current: string, relative: string): Promise => {\n const entries = await readdir(current, { withFileTypes: true });\n entries.sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of entries) {\n const entryPath = path.join(current, entry.name);\n const entryRelative = relative ? path.join(relative, entry.name) : entry.name;\n if (entry.isDirectory()) {\n await walk(entryPath, entryRelative);\n } else if (entry.isFile()) {\n files.set(entryRelative, await readFile(entryPath));\n } else {\n throw new Error(`Skill directory contains an unsupported entry: ${entryPath}`);\n }\n }\n };\n try {\n await walk(directory, \"\");\n } catch (error) {\n if (!required && (error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n if (!files.has(\"SKILL.md\")) throw new Error(`Skill directory is missing SKILL.md: ${directory}`);\n return files;\n}\n\nfunction skillFilesEqual(left: Map, right: Map): boolean {\n if (left.size !== right.size) return false;\n return [...left].every(([name, value]) => right.get(name)?.equals(value) === true);\n}\n\nasync function backupSkillDirectory(directory: string): Promise {\n const backup = `${directory}.crafttable-mcp.backup`;\n try {\n await cp(directory, backup, { recursive: true, force: false, errorOnExist: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n }\n return backup;\n}\n\nasync function replaceSkillDirectory(source: string, destination: string, existed: boolean): Promise {\n await mkdir(path.dirname(destination), { recursive: true });\n const temporary = `${destination}.${process.pid}.${randomUUID()}.tmp`;\n await cp(source, temporary, { recursive: true, force: false, errorOnExist: true });\n try {\n if (existed) await rm(destination, { recursive: true, force: true });\n await rename(temporary, destination);\n } catch (error) {\n if (existed && !await pathExists(destination)) {\n const backup = `${destination}.crafttable-mcp.backup`;\n if (await pathExists(backup)) await cp(backup, destination, { recursive: true });\n }\n throw error;\n } finally {\n await rm(temporary, { recursive: true, force: true });\n }\n}\n\nasync function pathExists(filePath: string): Promise {\n try {\n await stat(filePath);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n\nasync function backupAndAtomicWrite(filePath: string, updated: string, existed: boolean): Promise {\n await mkdir(path.dirname(filePath), { recursive: true });\n if (existed) {\n try {\n await copyFile(filePath, `${filePath}.crafttable-mcp.backup`, constants.COPYFILE_EXCL);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n }\n }\n const temporary = `${filePath}.${process.pid}.tmp`;\n await writeFile(temporary, updated, \"utf8\");\n await rename(temporary, filePath);\n}\n\nasync function readOptionalFile(filePath: string): Promise {\n try {\n return await readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nfunction arraysEqual(value: unknown, expected: string[]): boolean {\n return Array.isArray(value) && value.length === expected.length && value.every((item, index) => item === expected[index]);\n}\n\nfunction expandTarget(target: AgentTarget): AgentName[] {\n if (target === \"all\") return [\"codex\", \"claude\", \"opencode\"];\n if ([\"codex\", \"claude\", \"opencode\"].includes(target)) return [target as AgentName];\n throw new Error(\"Agent must be one of: codex, claude, opencode, all\");\n}\n\nasync function terminalConfirm(message: string): Promise {\n const readline = createInterface({ input: process.stdin, output: process.stderr });\n try {\n return /^y(es)?$/i.test((await readline.question(`${message} [y/N] `)).trim());\n } finally {\n readline.close();\n }\n}\n\nasync function requireSuccess(resultPromise: Promise, operation: string): Promise {\n const result = await resultPromise;\n if (result.code !== 0) throw new Error(`${operation} failed: ${safeCommandError(result)}`);\n}\n\nfunction safeCommandError(result: CommandResult): string {\n return (result.stderr || result.stdout || `exit code ${result.code}`).trim();\n}\n\nexport class SpawnCommandRunner implements CommandRunner {\n run(command: string, args: string[]): Promise {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, { shell: false, windowsHide: true, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.setEncoding(\"utf8\").on(\"data\", (chunk) => { stdout += String(chunk); });\n child.stderr?.setEncoding(\"utf8\").on(\"data\", (chunk) => { stderr += String(chunk); });\n child.once(\"error\", (error) => reject(new Error(`Could not run ${command}: ${errorMessage(error)}`)));\n child.once(\"close\", (code) => resolve({ code: code ?? 1, stdout, stderr }));\n });\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { OAuthDiscoveryState } from \"@modelcontextprotocol/sdk/client/auth.js\";\n\nexport const DEFAULT_MCP_URL = \"https://crafttable.crash.work/mcp\";\nexport const DEFAULT_CLIENT_ID = \"crafttable-mcp-cli\";\nexport const DEFAULT_CALLBACK_PORT = 48321;\nexport const OAUTH_SCOPES = \"openid profile email offline_access\";\n\nexport type ClientOptions = {\n url: URL;\n clientId: string;\n callbackPort: number;\n};\n\nexport function resolveClientOptions(input: {\n url?: string;\n clientId?: string;\n callbackPort?: string | number;\n env?: NodeJS.ProcessEnv;\n} = {}): ClientOptions {\n const env = input.env ?? process.env;\n const url = validateMcpUrl(input.url ?? env.CRAFTTABLE_MCP_URL ?? DEFAULT_MCP_URL);\n const clientId = (input.clientId ?? env.CRAFTTABLE_MCP_OAUTH_CLIENT_ID ?? DEFAULT_CLIENT_ID).trim();\n if (!clientId) throw new Error(\"OAuth client ID must not be empty\");\n const callbackPort = Number(input.callbackPort ?? env.CRAFTTABLE_MCP_OAUTH_CALLBACK_PORT ?? DEFAULT_CALLBACK_PORT);\n if (!Number.isInteger(callbackPort) || callbackPort < 1 || callbackPort > 65535) {\n throw new Error(\"OAuth callback port must be an integer between 1 and 65535\");\n }\n return { url, clientId, callbackPort };\n}\n\nexport function validateMcpUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"MCP URL must be an absolute URL\");\n }\n if (url.username || url.password || url.search || url.hash) {\n throw new Error(\"MCP URL must not include credentials, query parameters, or a fragment\");\n }\n const local = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && local)) {\n throw new Error(\"MCP URL must use HTTPS unless it targets localhost\");\n }\n url.pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n return url;\n}\n\nexport function credentialAccount(options: Pick): string {\n return createHash(\"sha256\").update(`${options.url.toString()}\\0${options.clientId}`).digest(\"hex\");\n}\n\nexport function platformConfigDir(env: NodeJS.ProcessEnv = process.env, platform = process.platform): string {\n if (platform === \"win32\") return path.join(env.APPDATA || path.join(os.homedir(), \"AppData\", \"Roaming\"), \"GameCraftTable\", \"mcp-client\");\n if (platform === \"darwin\") return path.join(os.homedir(), \"Library\", \"Application Support\", \"GameCraftTable\", \"mcp-client\");\n return path.join(env.XDG_CONFIG_HOME || path.join(os.homedir(), \".config\"), \"gamecrafttable\", \"mcp-client\");\n}\n\ntype DiscoveryFile = {\n version: 1;\n entries: Record;\n};\n\nexport class DiscoveryStore {\n readonly filePath: string;\n\n constructor(configDir = platformConfigDir()) {\n this.filePath = path.join(configDir, \"discovery.json\");\n }\n\n async get(account: string): Promise {\n return (await this.read()).entries[account];\n }\n\n async set(account: string, state: OAuthDiscoveryState): Promise {\n const document = await this.read();\n document.entries[account] = state;\n await atomicWriteJson(this.filePath, document);\n }\n\n async delete(account: string): Promise {\n const document = await this.read();\n if (!(account in document.entries)) return;\n delete document.entries[account];\n await atomicWriteJson(this.filePath, document);\n }\n\n private async read(): Promise {\n try {\n const value = JSON.parse(await readFile(this.filePath, \"utf8\")) as Partial;\n return { version: 1, entries: value.entries && typeof value.entries === \"object\" ? value.entries : {} };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { version: 1, entries: {} };\n throw new Error(`Could not read OAuth discovery cache: ${errorMessage(error)}`);\n }\n }\n}\n\nexport async function atomicWriteJson(filePath: string, value: unknown): Promise {\n await mkdir(path.dirname(filePath), { recursive: true });\n const temporary = `${filePath}.${process.pid}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, { encoding: \"utf8\", mode: 0o600 });\n await rename(temporary, filePath);\n}\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { DiscoveryStore } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\nimport { connectRemote } from \"./remote.js\";\n\nexport async function serveBridge(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n serviceToken = process.env.CRAFTTABLE_MCP_TOKEN?.trim(),\n): Promise {\n const upstream = await connectRemote(options, tokenStore, discoveryStore, serviceToken);\n if (upstream.authentication === \"service-token\") {\n process.stderr.write(\"CraftTable MCP: using the legacy service-account token path.\\n\");\n }\n const server = createProxyServer(upstream.client);\n const transport = new StdioServerTransport();\n const close = async (): Promise => {\n await server.close().catch(() => undefined);\n await upstream.close().catch(() => undefined);\n };\n process.once(\"SIGINT\", () => void close());\n process.once(\"SIGTERM\", () => void close());\n try {\n await server.connect(transport);\n } catch (error) {\n await close();\n throw error;\n }\n}\n\nexport function createProxyServer(upstream: {\n listTools: (params?: { cursor?: string }) => Promise;\n callTool: (params: { name: string; arguments?: Record }) => Promise;\n listResources: (params?: { cursor?: string }) => Promise;\n listResourceTemplates: (params?: { cursor?: string }) => Promise;\n readResource: (params: { uri: string }) => Promise;\n}): Server {\n const server = new Server({ name: \"crafttable-mcp-stdio-bridge\", version: \"0.1.3\" }, {\n capabilities: {\n tools: {},\n resources: {},\n },\n });\n server.setRequestHandler(ListToolsRequestSchema, (request) => upstream.listTools(request.params) as never);\n server.setRequestHandler(CallToolRequestSchema, (request) => upstream.callTool(request.params) as never);\n server.setRequestHandler(ListResourcesRequestSchema, (request) => upstream.listResources(request.params) as never);\n server.setRequestHandler(ListResourceTemplatesRequestSchema, (request) => upstream.listResourceTemplates(request.params) as never);\n server.setRequestHandler(ReadResourceRequestSchema, (request) => upstream.readResource(request.params) as never);\n return server;\n}\n", "import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport open from \"open\";\nimport { OAuthCallbackServer } from \"./callbackServer.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { credentialAccount, DiscoveryStore, errorMessage } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\nimport { GameCraftOAuthProvider } from \"./oauthProvider.js\";\n\nexport type RemoteConnection = {\n client: Client;\n transport: StreamableHTTPClientTransport;\n authentication: \"oauth\" | \"service-token\";\n close: () => Promise;\n};\n\nexport async function connectRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n serviceToken = process.env.CRAFTTABLE_MCP_TOKEN?.trim(),\n): Promise {\n const tokens = await tokenStore.get(credentialAccount(options));\n if (tokens) {\n const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, () => {\n throw new Error(\"OAuth login is required; run `crafttable-mcp login`\");\n });\n return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, { authProvider: provider }), \"oauth\");\n }\n if (serviceToken) {\n return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, {\n requestInit: { headers: { authorization: `Bearer ${serviceToken}` } },\n }), \"service-token\");\n }\n throw new Error(\"Not logged in; run `crafttable-mcp login` or set CRAFTTABLE_MCP_TOKEN for the legacy service-account path\");\n}\n\nexport async function loginRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n input: { browser: boolean; timeoutMs?: number; writeLine?: (value: string) => void } = { browser: true },\n): Promise<{ alreadyAuthenticated: boolean; toolCount: number }> {\n const writeLine = input.writeLine ?? ((value) => process.stderr.write(`${value}\\n`));\n await requireOAuthProtectedResourceMetadata(options.url);\n let authorizationUrl: URL | undefined;\n const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, async (url) => {\n authorizationUrl = url;\n if (!input.browser) {\n writeLine(`Open this URL to log in:\\n${url.toString()}`);\n return;\n }\n try {\n await open(url.toString(), { wait: false });\n writeLine(\"Opened the system browser for Game-CraftTable login.\");\n } catch (error) {\n writeLine(`Could not open the browser (${errorMessage(error)}). Open this URL manually:\\n${url.toString()}`);\n }\n });\n const callback = new OAuthCallbackServer(options.callbackPort, (state) => provider.validateState(state));\n await callback.listen();\n const firstClient = new Client({ name: \"crafttable-mcp-cli\", version: \"0.1.3\" });\n const firstTransport = new StreamableHTTPClientTransport(options.url, { authProvider: provider });\n try {\n try {\n await firstClient.connect(firstTransport);\n const tools = await firstClient.listTools();\n return { alreadyAuthenticated: true, toolCount: tools.tools.length };\n } catch (error) {\n if (!(error instanceof UnauthorizedError) && !authorizationUrl) throw error;\n const { code } = await callback.wait(input.timeoutMs);\n await firstTransport.finishAuth(code);\n }\n } finally {\n await firstClient.close().catch(() => undefined);\n await callback.close().catch(() => undefined);\n }\n\n const connection = await connectRemote(options, tokenStore, discoveryStore, \"\");\n try {\n const tools = await connection.client.listTools();\n return { alreadyAuthenticated: false, toolCount: tools.tools.length };\n } finally {\n await connection.close();\n }\n}\n\nexport async function logoutRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n localOnly: boolean,\n fetchFn: typeof fetch = fetch,\n): Promise<{ hadCredential: boolean; revoked: boolean }> {\n const account = credentialAccount(options);\n const tokens = await tokenStore.get(account);\n if (tokens && !localOnly) {\n const endpoint = await discoverRevocationEndpoint(options.url, fetchFn);\n await revokeTokens(endpoint, options.clientId, tokens, fetchFn);\n }\n await tokenStore.delete(account);\n await discoveryStore.delete(account);\n return { hadCredential: Boolean(tokens), revoked: Boolean(tokens && !localOnly) };\n}\n\nasync function connectWithTransport(\n options: ClientOptions,\n transport: StreamableHTTPClientTransport,\n authentication: RemoteConnection[\"authentication\"],\n): Promise {\n const client = new Client({ name: \"crafttable-mcp-cli\", version: \"0.1.3\" });\n try {\n await client.connect(transport);\n } catch (error) {\n await client.close().catch(() => undefined);\n if (error instanceof UnauthorizedError) throw new Error(\"OAuth login is required; run `crafttable-mcp login`\");\n throw error;\n }\n return {\n client,\n transport,\n authentication,\n close: () => client.close(),\n };\n}\n\nasync function discoverRevocationEndpoint(resource: URL, fetchFn: typeof fetch): Promise {\n const protectedMetadata = await requireOAuthProtectedResourceMetadata(resource, fetchFn);\n const issuer = Array.isArray(protectedMetadata.authorization_servers)\n ? protectedMetadata.authorization_servers.find((value): value is string => typeof value === \"string\")\n : undefined;\n if (!issuer) throw new Error(\"OAuth protected-resource metadata has no authorization server\");\n const issuerUrl = new URL(issuer);\n const candidates = [\n new URL(`${issuerUrl.toString().replace(/\\/$/, \"\")}/.well-known/openid-configuration`),\n new URL(`/.well-known/openid-configuration${issuerUrl.pathname === \"/\" ? \"\" : issuerUrl.pathname}`, issuerUrl.origin),\n ];\n for (const candidate of candidates) {\n const response = await fetchFn(candidate, { headers: { accept: \"application/json\" } });\n if (!response.ok) continue;\n try {\n const metadata = await response.json() as { revocation_endpoint?: unknown };\n if (typeof metadata.revocation_endpoint === \"string\") return new URL(metadata.revocation_endpoint);\n } catch {\n // Try the next standards-compatible discovery location.\n }\n }\n throw new Error(\"OAuth authorization server does not advertise a revocation endpoint\");\n}\n\nexport async function requireOAuthProtectedResourceMetadata(\n resource: URL,\n fetchFn: typeof fetch = fetch,\n): Promise<{ authorization_servers?: unknown }> {\n const metadataUrl = new URL(`/.well-known/oauth-protected-resource${resource.pathname === \"/\" ? \"\" : resource.pathname}`, resource.origin);\n let response: Response;\n try {\n response = await fetchFn(metadataUrl, { headers: { accept: \"application/json\" } });\n } catch (error) {\n throw new Error(`Could not reach OAuth protected-resource metadata at ${metadataUrl}: ${errorMessage(error)}`);\n }\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!response.ok) {\n throw new Error(`OAuth is not enabled for ${resource}; protected-resource metadata at ${metadataUrl} returned HTTP ${response.status}`);\n }\n if (!contentType.includes(\"application/json\")) {\n throw new Error(`OAuth is not enabled for ${resource}; protected-resource metadata at ${metadataUrl} returned ${contentType || \"an unknown content type\"} instead of JSON`);\n }\n try {\n return await response.json() as { authorization_servers?: unknown };\n } catch {\n throw new Error(`OAuth protected-resource metadata at ${metadataUrl} is not valid JSON`);\n }\n}\n\nasync function revokeTokens(endpoint: URL, clientId: string, tokens: OAuthTokens, fetchFn: typeof fetch): Promise {\n const candidates = [tokens.refresh_token\n ? { token: tokens.refresh_token, hint: \"refresh_token\" }\n : { token: tokens.access_token, hint: \"access_token\" }];\n for (const value of candidates) {\n const response = await fetchFn(endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({ token: value.token, token_type_hint: value.hint, client_id: clientId }),\n });\n if (!response.ok) throw new Error(`OAuth token revocation returned HTTP ${response.status}; local credentials were retained`);\n }\n}\n", "import { createServer, type Server } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nexport type OAuthCallback = { code: string };\n\nexport class OAuthCallbackServer {\n private server?: Server;\n private resolveResult?: (value: OAuthCallback) => void;\n private rejectResult?: (reason: Error) => void;\n private readonly result = new Promise((resolve, reject) => {\n this.resolveResult = resolve;\n this.rejectResult = reject;\n });\n\n constructor(\n private readonly port: number,\n private readonly validateState: (state: string | null) => boolean,\n ) {\n // A very fast browser callback can arrive before loginRemote starts awaiting it.\n // Keep rejection handled while preserving the original promise for wait().\n void this.result.catch(() => undefined);\n }\n\n async listen(): Promise {\n if (this.server) throw new Error(\"OAuth callback server is already running\");\n this.server = createServer((request, response) => {\n const url = new URL(request.url ?? \"/\", `http://127.0.0.1:${this.port}`);\n if (request.method !== \"GET\" || url.pathname !== \"/oauth/callback\") {\n response.writeHead(404, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"Not found\");\n return;\n }\n const oauthError = url.searchParams.get(\"error\");\n if (oauthError) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth login failed. Return to the terminal.\");\n this.rejectResult?.(new Error(`OAuth authorization failed: ${oauthError}`));\n return;\n }\n if (!this.validateState(url.searchParams.get(\"state\"))) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth state did not match. Return to the terminal.\");\n this.rejectResult?.(new Error(\"OAuth callback state did not match\"));\n return;\n }\n const code = url.searchParams.get(\"code\");\n if (!code) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth authorization code is missing.\");\n this.rejectResult?.(new Error(\"OAuth callback did not include an authorization code\"));\n return;\n }\n response.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" }).end(\"CraftTable MCP

Login complete. You can close this window.

\");\n this.resolveResult?.({ code });\n });\n await new Promise((resolve, reject) => {\n const onError = (error: Error) => reject(new Error(`Could not listen on OAuth callback port ${this.port}: ${error.message}`));\n this.server!.once(\"error\", onError);\n this.server!.listen(this.port, \"127.0.0.1\", () => {\n this.server!.off(\"error\", onError);\n resolve();\n });\n });\n const address = this.server.address() as AddressInfo | null;\n if (!address || address.port !== this.port) throw new Error(`OAuth callback server did not bind port ${this.port}`);\n }\n\n async wait(timeoutMs = 10 * 60 * 1000): Promise {\n let timeout: NodeJS.Timeout | undefined;\n try {\n return await Promise.race([\n this.result,\n new Promise((_resolve, reject) => {\n timeout = setTimeout(() => reject(new Error(\"OAuth callback timed out\")), timeoutMs);\n }),\n ]);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n\n async close(): Promise {\n if (!this.server) return;\n const server = this.server;\n this.server = undefined;\n await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));\n }\n}\n", "import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type { OAuthClientProvider, OAuthDiscoveryState } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { credentialAccount, DiscoveryStore, OAUTH_SCOPES } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\n\nexport class GameCraftOAuthProvider implements OAuthClientProvider {\n readonly redirectUrl: URL;\n readonly clientMetadata: OAuthClientMetadata;\n private readonly account: string;\n private readonly expectedState: string;\n private codeVerifierValue?: string;\n\n constructor(\n private readonly options: ClientOptions,\n private readonly tokenStore: TokenStore,\n private readonly discoveryStore: DiscoveryStore,\n private readonly onRedirect: (url: URL) => void | Promise,\n state = randomBytes(32).toString(\"base64url\"),\n ) {\n this.redirectUrl = new URL(`http://127.0.0.1:${options.callbackPort}/oauth/callback`);\n this.clientMetadata = {\n client_name: \"CraftTable MCP CLI\",\n redirect_uris: [this.redirectUrl.toString()],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: OAUTH_SCOPES,\n };\n this.account = credentialAccount(options);\n this.expectedState = state;\n }\n\n state(): string {\n return this.expectedState;\n }\n\n validateState(value: string | null): boolean {\n if (!value) return false;\n const expected = Buffer.from(this.expectedState);\n const actual = Buffer.from(value);\n return expected.length === actual.length && timingSafeEqual(expected, actual);\n }\n\n clientInformation(): OAuthClientInformationMixed {\n return { client_id: this.options.clientId };\n }\n\n tokens(): Promise {\n return this.tokenStore.get(this.account);\n }\n\n saveTokens(tokens: OAuthTokens): Promise {\n return this.tokenStore.set(this.account, tokens);\n }\n\n redirectToAuthorization(url: URL): void | Promise {\n return this.onRedirect(url);\n }\n\n saveCodeVerifier(codeVerifier: string): void {\n this.codeVerifierValue = codeVerifier;\n }\n\n codeVerifier(): string {\n if (!this.codeVerifierValue) throw new Error(\"OAuth PKCE verifier is missing or expired\");\n return this.codeVerifierValue;\n }\n\n discoveryState(): Promise {\n return this.discoveryStore.get(this.account);\n }\n\n saveDiscoveryState(state: OAuthDiscoveryState): Promise {\n return this.discoveryStore.set(this.account, state);\n }\n\n async invalidateCredentials(scope: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): Promise {\n if (scope === \"all\" || scope === \"tokens\") await this.tokenStore.delete(this.account);\n if (scope === \"all\" || scope === \"discovery\") await this.discoveryStore.delete(this.account);\n if (scope === \"all\" || scope === \"verifier\") this.codeVerifierValue = undefined;\n }\n}\n", "import { randomUUID } from \"node:crypto\";\nimport type { OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nexport const KEYRING_SERVICE = \"CraftTable MCP\";\nconst KEYRING_CHUNK_SIZE = 1000;\n\ntype CredentialEntry = {\n getPassword(): Promise;\n setPassword(password: string): Promise;\n deleteCredential(): Promise;\n};\n\ntype CredentialEntryFactory = (account: string) => Promise;\n\ntype ChunkManifest = {\n version: 2;\n generation: string;\n chunks: number;\n};\n\nexport interface TokenStore {\n get(account: string): Promise;\n set(account: string, tokens: OAuthTokens): Promise;\n delete(account: string): Promise;\n}\n\nexport class KeyringTokenStore implements TokenStore {\n constructor(private readonly entryFactory: CredentialEntryFactory = keyringEntry) {}\n\n async get(account: string): Promise {\n let serialized: string | undefined;\n try {\n serialized = await this.readPassword(account);\n } catch (error) {\n throw keyringError(error);\n }\n if (!serialized) return undefined;\n\n const manifest = parseChunkManifest(serialized);\n if (manifest) {\n try {\n const chunks = await Promise.all(Array.from({ length: manifest.chunks }, (_, index) =>\n this.readPassword(chunkAccount(account, manifest.generation, index))));\n if (chunks.some((chunk) => chunk === undefined)) throw new Error(\"missing credential chunk\");\n serialized = Buffer.from(chunks.join(\"\"), \"base64\").toString(\"utf8\");\n } catch (error) {\n if (error instanceof Error && error.message === \"missing credential chunk\") throw invalidCredentialError();\n throw keyringError(error);\n }\n }\n\n try {\n const value = JSON.parse(serialized) as OAuthTokens;\n if (!value.access_token || !value.token_type) throw new Error(\"missing token fields\");\n return value;\n } catch {\n throw invalidCredentialError();\n }\n }\n\n async set(account: string, tokens: OAuthTokens): Promise {\n const encoded = Buffer.from(JSON.stringify(tokens), \"utf8\").toString(\"base64\");\n const chunks = splitCredential(encoded);\n const generation = randomUUID().replaceAll(\"-\", \"\");\n const manifest: ChunkManifest = { version: 2, generation, chunks: chunks.length };\n let previous: string | undefined;\n const writtenAccounts: string[] = [];\n\n try {\n previous = await this.readPassword(account);\n for (const [index, chunk] of chunks.entries()) {\n const partAccount = chunkAccount(account, generation, index);\n await (await this.entryFactory(partAccount)).setPassword(chunk);\n writtenAccounts.push(partAccount);\n }\n await (await this.entryFactory(account)).setPassword(JSON.stringify(manifest));\n } catch (error) {\n await Promise.allSettled(writtenAccounts.map((partAccount) => this.deletePassword(partAccount)));\n throw keyringError(error);\n }\n\n const previousManifest = previous && parseChunkManifest(previous);\n if (previousManifest) {\n await Promise.allSettled(Array.from({ length: previousManifest.chunks }, (_, index) =>\n this.deletePassword(chunkAccount(account, previousManifest.generation, index))));\n }\n }\n\n async delete(account: string): Promise {\n try {\n const serialized = await this.readPassword(account);\n const manifest = serialized ? parseChunkManifest(serialized) : undefined;\n await this.deletePassword(account);\n if (manifest) {\n await Promise.all(Array.from({ length: manifest.chunks }, (_, index) =>\n this.deletePassword(chunkAccount(account, manifest.generation, index))));\n }\n } catch (error) {\n throw keyringError(error);\n }\n }\n\n private async readPassword(account: string): Promise {\n try {\n return await (await this.entryFactory(account)).getPassword();\n } catch (error) {\n if (isMissingCredential(error)) return undefined;\n throw error;\n }\n }\n\n private async deletePassword(account: string): Promise {\n try {\n await (await this.entryFactory(account)).deleteCredential();\n } catch (error) {\n if (!isMissingCredential(error)) throw error;\n }\n }\n}\n\nfunction splitCredential(value: string): string[] {\n const chunks: string[] = [];\n for (let offset = 0; offset < value.length; offset += KEYRING_CHUNK_SIZE) {\n chunks.push(value.slice(offset, offset + KEYRING_CHUNK_SIZE));\n }\n return chunks.length ? chunks : [\"\"];\n}\n\nfunction chunkAccount(account: string, generation: string, index: number): string {\n return `${account}:v2:${generation}:${index}`;\n}\n\nfunction parseChunkManifest(value: string): ChunkManifest | undefined {\n try {\n const parsed = JSON.parse(value) as Partial;\n if (parsed.version !== 2 || typeof parsed.generation !== \"string\" || !/^[0-9a-f]{32}$/.test(parsed.generation)\n || !Number.isInteger(parsed.chunks) || (parsed.chunks ?? 0) < 1 || (parsed.chunks ?? 0) > 100) return undefined;\n return parsed as ChunkManifest;\n } catch {\n return undefined;\n }\n}\n\nfunction isMissingCredential(error: unknown): boolean {\n const message = String((error as Error)?.message ?? error).toLowerCase();\n return message.includes(\"no entry\") || message.includes(\"not found\");\n}\n\nfunction invalidCredentialError(): Error {\n return new Error(\"The saved CraftTable MCP credential is invalid; run `crafttable-mcp logout --local-only` and log in again\");\n}\n\nasync function keyringEntry(account: string): Promise {\n try {\n const { AsyncEntry } = await import(\"@napi-rs/keyring\");\n return new AsyncEntry(KEYRING_SERVICE, account);\n } catch (error) {\n throw keyringError(error);\n }\n}\n\nfunction keyringError(error: unknown): Error {\n if (error instanceof Error && error.message.startsWith(\"The operating-system credential store is unavailable\")) return error;\n const detail = error instanceof Error ? error.message : String(error);\n return new Error(`The operating-system credential store is unavailable (${detail}). Enable Windows Credential Manager, macOS Keychain, or a Secret Service provider, then retry; plaintext token storage is not supported.`);\n}\n"], - "mappings": "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", + "sourcesContent": ["#!/usr/bin/env node\n\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { configureAgents, type AgentTarget, unconfigureAgents } from \"./agents.js\";\nimport { serveBridge } from \"./bridge.js\";\nimport { type ClientOptions, credentialAccount, DiscoveryStore, resolveClientOptions } from \"./config.js\";\nimport { KeyringTokenStore } from \"./credentials.js\";\nimport { connectRemote, loginRemote, logoutRemote } from \"./remote.js\";\n\ntype ConnectionFlags = { url?: string; clientId?: string; callbackPort?: string };\n\nconst program = new Command()\n .name(\"crafttable-mcp\")\n .description(\"OAuth client and stdio bridge for CraftTable MCP\")\n .version(\"0.1.3\");\n\nwithConnection(program.command(\"login\").description(\"Log in through the system browser\"))\n .option(\"--no-browser\", \"print the authorization URL instead of opening it\")\n .option(\"--timeout \", \"OAuth callback timeout\", \"600000\")\n .action(async (flags: ConnectionFlags & { browser: boolean; timeout: string }) => {\n const options = connectionOptions(flags);\n const timeoutMs = positiveInteger(flags.timeout, \"OAuth callback timeout\");\n const result = await loginRemote(options, new KeyringTokenStore(), new DiscoveryStore(), { browser: flags.browser, timeoutMs });\n printJson({ loggedIn: true, alreadyAuthenticated: result.alreadyAuthenticated, server: options.url.toString(), tools: result.toolCount });\n });\n\nwithConnection(program.command(\"status\").description(\"Check saved login state and remote MCP connectivity\"))\n .action(async (flags: ConnectionFlags) => {\n const options = connectionOptions(flags);\n const tokens = await new KeyringTokenStore().get(credentialAccount(options));\n const connection = await connectRemote(options, new KeyringTokenStore(), new DiscoveryStore());\n try {\n const tools = await connection.client.listTools();\n printJson({\n loggedIn: Boolean(tokens),\n authentication: connection.authentication,\n connected: true,\n server: options.url.toString(),\n tools: tools.tools.length,\n });\n } finally {\n await connection.close();\n }\n });\n\nwithConnection(program.command(\"logout\").description(\"Revoke OAuth tokens and remove the local credential\"))\n .option(\"--local-only\", \"remove local credentials without contacting the authorization server\")\n .action(async (flags: ConnectionFlags & { localOnly?: boolean }) => {\n const options = connectionOptions(flags);\n const result = await logoutRemote(options, new KeyringTokenStore(), new DiscoveryStore(), Boolean(flags.localOnly));\n printJson({ loggedIn: false, credentialRemoved: result.hadCredential, revoked: result.revoked, localOnly: Boolean(flags.localOnly) });\n });\n\nwithConnection(program.command(\"tools\").description(\"List remote MCP tools\"))\n .action(async (flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson(await client.listTools())));\n\nwithConnection(program.command(\"resources\").description(\"List remote MCP resources and resource templates\"))\n .action(async (flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson({\n resources: (await client.listResources()).resources,\n resourceTemplates: (await client.listResourceTemplates()).resourceTemplates,\n })));\n\nwithConnection(program.command(\"read \").description(\"Read an MCP resource\"))\n .action(async (uri: string, flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => printJson(await client.readResource({ uri }))));\n\nwithConnection(program.command(\"call [json]\").description(\"Call an MCP tool\"))\n .action(async (tool: string, json: string | undefined, flags: ConnectionFlags) => withClient(connectionOptions(flags), async (client) => {\n printJson(await client.callTool({ name: tool, arguments: parseObject(json ?? \"{}\") }));\n }));\n\nwithConnection(program.command(\"serve\").description(\"Run the local stdio bridge\"))\n .action(async (flags: ConnectionFlags) => {\n await serveBridge(connectionOptions(flags), new KeyringTokenStore(), new DiscoveryStore());\n });\n\nfor (const operation of [\"configure\", \"unconfigure\"] as const) {\n withConnection(program.command(`${operation} `).description(`${operation === \"configure\" ? \"Add\" : \"Remove\"} the stdio bridge and CraftTable Skill in Codex, Claude Code, or OpenCode`))\n .option(\"--dry-run\", \"show the planned changes without writing\")\n .option(\"--force\", \"replace a conflicting entry without prompting\")\n .action(async (agent: AgentTarget, flags: ConnectionFlags & { dryRun?: boolean; force?: boolean }) => {\n const cliEntry = fileURLToPath(import.meta.url);\n if (!cliEntry.endsWith(\".js\")) throw new Error(\"Agent configuration requires the built CLI; run `npm --prefix apps/mcp-client run build` first\");\n const input = {\n target: agent,\n options: connectionOptions(flags),\n cliEntry,\n dryRun: Boolean(flags.dryRun),\n force: Boolean(flags.force),\n };\n const result = operation === \"configure\" ? await configureAgents(input) : await unconfigureAgents(input);\n printJson({ result });\n });\n}\n\nfunction withConnection(command: Command): Command {\n return command\n .option(\"--url \", \"MCP Streamable HTTP URL\")\n .option(\"--client-id \", \"pre-registered OAuth public client ID\")\n .option(\"--callback-port \", \"fixed localhost OAuth callback port\");\n}\n\nfunction connectionOptions(flags: ConnectionFlags): ClientOptions {\n return resolveClientOptions(flags);\n}\n\nasync function withClient(options: ClientOptions, action: (client: Awaited>[\"client\"]) => Promise): Promise {\n const connection = await connectRemote(options, new KeyringTokenStore(), new DiscoveryStore());\n try {\n await action(connection.client);\n } finally {\n await connection.close();\n }\n}\n\nfunction parseObject(raw: string): Record {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new Error(\"Tool arguments must be a JSON object\");\n }\n if (!value || Array.isArray(value) || typeof value !== \"object\") throw new Error(\"Tool arguments must be a JSON object\");\n return value as Record;\n}\n\nfunction positiveInteger(value: string, name: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) throw new Error(`${name} must be a positive integer`);\n return parsed;\n}\n\nfunction printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nprogram.parseAsync().catch((error: unknown) => {\n process.stderr.write(`CraftTable MCP failed: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n});\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { applyEdits, modify, parse } from \"jsonc-parser\";\nimport spawn from \"cross-spawn\";\nimport type { ClientOptions } from \"./config.js\";\nimport { errorMessage } from \"./config.js\";\n\nexport const SERVER_NAME = \"crafttable\";\nexport type AgentName = \"codex\" | \"claude\" | \"opencode\";\nexport type AgentTarget = AgentName | \"all\";\nexport type SkillAction = \"installed\" | \"replaced\" | \"removed\" | \"unchanged\" | \"absent\" | \"preserved\" | \"would-install\" | \"would-replace\" | \"would-remove\" | \"would-preserve\";\n\nexport type CommandResult = { code: number; stdout: string; stderr: string };\nexport interface CommandRunner {\n run(command: string, args: string[]): Promise;\n}\n\nexport type ConfigureInput = {\n target: AgentTarget;\n options: ClientOptions;\n cliEntry: string;\n nodePath?: string;\n dryRun?: boolean;\n force?: boolean;\n env?: NodeJS.ProcessEnv;\n runner?: CommandRunner;\n confirm?: (message: string) => Promise;\n opencodePath?: string;\n skillSource?: string;\n skillPaths?: Partial>;\n};\n\nexport type ConfigureResult = {\n agent: AgentName;\n action: \"added\" | \"replaced\" | \"removed\" | \"unchanged\" | \"absent\" | \"would-add\" | \"would-replace\" | \"would-remove\";\n skillAction: SkillAction;\n};\n\nexport async function configureAgents(input: ConfigureInput): Promise {\n const agents = expandTarget(input.target);\n const command = launchCommand(input.options, input.cliEntry, input.nodePath ?? process.execPath);\n const runner = input.runner ?? new SpawnCommandRunner();\n const results: ConfigureResult[] = [];\n for (const agent of agents) {\n const mcpResult = agent === \"opencode\"\n ? await configureOpenCode(input, command)\n : await configureCliAgent(agent, command, input, runner);\n const skillAction = await configureAgentSkill(agent, input);\n results.push({ ...mcpResult, skillAction });\n }\n return results;\n}\n\nexport async function unconfigureAgents(input: ConfigureInput): Promise {\n const agents = expandTarget(input.target);\n const runner = input.runner ?? new SpawnCommandRunner();\n const results: ConfigureResult[] = [];\n for (const agent of agents) {\n let mcpResult: Omit;\n if (agent === \"opencode\") {\n mcpResult = await unconfigureOpenCode(input);\n } else {\n mcpResult = await unconfigureCliAgent(agent, input, runner);\n }\n const skillAction = await unconfigureAgentSkill(agent, input);\n results.push({ ...mcpResult, skillAction });\n }\n return results;\n}\n\nasync function unconfigureCliAgent(\n agent: \"codex\" | \"claude\",\n input: ConfigureInput,\n runner: CommandRunner,\n): Promise> {\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n const existing = await probeCliAgent(agent, runner);\n if (!existing.exists) return { agent, action: \"absent\" };\n if (input.dryRun) return { agent, action: \"would-remove\" };\n const args = agent === \"codex\"\n ? [\"mcp\", \"remove\", SERVER_NAME]\n : [\"mcp\", \"remove\", \"--scope\", \"user\", SERVER_NAME];\n await requireSuccess(runner.run(executable, args), `${agent} MCP removal`);\n return { agent, action: \"removed\" };\n}\n\nexport function launchCommand(options: ClientOptions, cliEntry: string, nodePath: string): string[] {\n return [\n path.resolve(nodePath),\n path.resolve(cliEntry),\n \"serve\",\n \"--url\", options.url.toString(),\n \"--client-id\", options.clientId,\n \"--callback-port\", String(options.callbackPort),\n ];\n}\n\nasync function configureCliAgent(\n agent: \"codex\" | \"claude\",\n command: string[],\n input: ConfigureInput,\n runner: CommandRunner,\n): Promise> {\n const existing = await probeCliAgent(agent, runner);\n if (existing.exists && outputMatchesCommand(existing.output, command)) return { agent, action: \"unchanged\" };\n if (existing.exists && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`${agent} already has a different ${SERVER_NAME} MCP entry; use --force to replace it`);\n if (!await confirm(`${agent} already has a different ${SERVER_NAME} MCP entry. Replace it?`)) {\n throw new Error(`${agent} MCP configuration was not changed`);\n }\n }\n const action = existing.exists ? \"replaced\" : \"added\";\n if (input.dryRun) return { agent, action: existing.exists ? \"would-replace\" : \"would-add\" };\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n if (existing.exists) {\n const removeArgs = agent === \"codex\"\n ? [\"mcp\", \"remove\", SERVER_NAME]\n : [\"mcp\", \"remove\", \"--scope\", \"user\", SERVER_NAME];\n await requireSuccess(runner.run(executable, removeArgs), `${agent} MCP replacement cleanup`);\n }\n const addArgs = agent === \"codex\"\n ? [\"mcp\", \"add\", SERVER_NAME, \"--\", ...command]\n : [\"mcp\", \"add\", \"--scope\", \"user\", SERVER_NAME, \"--\", ...command];\n await requireSuccess(runner.run(executable, addArgs), `${agent} MCP registration`);\n return { agent, action };\n}\n\nasync function probeCliAgent(agent: \"codex\" | \"claude\", runner: CommandRunner): Promise<{ exists: boolean; output: string }> {\n const executable = agent === \"codex\" ? \"codex\" : \"claude\";\n const args = agent === \"codex\"\n ? [\"mcp\", \"get\", SERVER_NAME, \"--json\"]\n : [\"mcp\", \"get\", SERVER_NAME];\n const result = await runner.run(executable, args);\n if (result.code === 0) return { exists: true, output: result.stdout };\n const combined = `${result.stdout}\\n${result.stderr}`;\n if (/not found|does not exist|no mcp server|not configured|unknown server/i.test(combined)) return { exists: false, output: combined };\n throw new Error(`Could not inspect ${agent} MCP configuration: ${safeCommandError(result)}`);\n}\n\nfunction outputMatchesCommand(output: string, command: string[]): boolean {\n try {\n const document = JSON.parse(output) as unknown;\n if (findCommand(document, command)) return true;\n } catch {\n // Claude currently returns a human-readable record.\n }\n return command.every((part) => output.includes(part));\n}\n\nfunction findCommand(value: unknown, command: string[]): boolean {\n if (!value || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return value.some((item) => findCommand(item, command));\n const record = value as Record;\n if (typeof record.command === \"string\" && Array.isArray(record.args)) {\n const candidate = [record.command, ...record.args.filter((item): item is string => typeof item === \"string\")];\n if (candidate.length === command.length && candidate.every((item, index) => item === command[index])) return true;\n }\n return Object.values(record).some((item) => findCommand(item, command));\n}\n\nasync function configureOpenCode(input: ConfigureInput, command: string[]): Promise> {\n const filePath = input.opencodePath ?? defaultOpenCodePath(input.env);\n const original = await readOptionalFile(filePath) ?? \"{}\\n\";\n const document = parse(original) as { mcp?: Record } | undefined;\n const existing = document?.mcp?.[SERVER_NAME] as { type?: unknown; command?: unknown; enabled?: unknown } | undefined;\n const desired = { type: \"local\", command, enabled: true };\n if (existing && existing.type === desired.type && existing.enabled === true && arraysEqual(existing.command, command)) {\n return { agent: \"opencode\", action: \"unchanged\" };\n }\n if (existing && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`opencode already has a different ${SERVER_NAME} MCP entry; use --force to replace it`);\n if (!await confirm(`opencode already has a different ${SERVER_NAME} MCP entry. Replace it?`)) {\n throw new Error(\"opencode MCP configuration was not changed\");\n }\n }\n if (input.dryRun) return { agent: \"opencode\", action: existing ? \"would-replace\" : \"would-add\" };\n const updated = applyEdits(original, modify(original, [\"mcp\", SERVER_NAME], desired, {\n formattingOptions: { insertSpaces: true, tabSize: 2, eol: \"\\n\" },\n }));\n await backupAndAtomicWrite(filePath, updated, await readOptionalFile(filePath) !== undefined);\n return { agent: \"opencode\", action: existing ? \"replaced\" : \"added\" };\n}\n\nasync function unconfigureOpenCode(input: ConfigureInput): Promise> {\n const filePath = input.opencodePath ?? defaultOpenCodePath(input.env);\n const original = await readOptionalFile(filePath);\n if (original === undefined) return { agent: \"opencode\", action: \"absent\" };\n const document = parse(original) as { mcp?: Record } | undefined;\n if (!document?.mcp || !(SERVER_NAME in document.mcp)) return { agent: \"opencode\", action: \"absent\" };\n if (input.dryRun) return { agent: \"opencode\", action: \"would-remove\" };\n const updated = applyEdits(original, modify(original, [\"mcp\", SERVER_NAME], undefined, {\n formattingOptions: { insertSpaces: true, tabSize: 2, eol: \"\\n\" },\n }));\n await backupAndAtomicWrite(filePath, updated, true);\n return { agent: \"opencode\", action: \"removed\" };\n}\n\nexport function defaultOpenCodePath(env: NodeJS.ProcessEnv = process.env): string {\n const base = env.XDG_CONFIG_HOME || (process.platform === \"win32\"\n ? path.join(env.USERPROFILE || os.homedir(), \".config\")\n : path.join(os.homedir(), \".config\"));\n return path.join(base, \"opencode\", \"opencode.json\");\n}\n\nexport function bundledSkillPath(cliEntry: string): string {\n return path.resolve(path.dirname(cliEntry), \"..\", \"skills\", SERVER_NAME);\n}\n\nexport function defaultSkillPath(agent: AgentName, env: NodeJS.ProcessEnv = process.env): string {\n const home = env.USERPROFILE || env.HOME || os.homedir();\n if (agent === \"codex\") return path.join(env.CODEX_HOME || path.join(home, \".codex\"), \"skills\", SERVER_NAME);\n if (agent === \"claude\") return path.join(home, \".claude\", \"skills\", SERVER_NAME);\n return path.join(path.dirname(defaultOpenCodePath(env)), \"skills\", SERVER_NAME);\n}\n\nasync function configureAgentSkill(agent: AgentName, input: ConfigureInput): Promise {\n const source = input.skillSource ?? bundledSkillPath(input.cliEntry);\n const destination = input.skillPaths?.[agent] ?? defaultSkillPath(agent, input.env);\n const sourceFiles = await readSkillDirectory(source, true);\n if (!sourceFiles) throw new Error(`Bundled Skill directory is missing: ${source}`);\n const existingFiles = await readSkillDirectory(destination, false);\n if (existingFiles && skillFilesEqual(existingFiles, sourceFiles)) return \"unchanged\";\n\n if (existingFiles && !input.force && !input.dryRun) {\n const confirm = input.confirm ?? terminalConfirm;\n if (!process.stdin.isTTY && !input.confirm) throw new Error(`${agent} already has a different ${SERVER_NAME} Skill; use --force to replace it`);\n if (!await confirm(`${agent} already has a different ${SERVER_NAME} Skill. Replace it?`)) {\n throw new Error(`${agent} Skill configuration was not changed`);\n }\n }\n\n if (input.dryRun) return existingFiles ? \"would-replace\" : \"would-install\";\n if (existingFiles) await backupSkillDirectory(destination);\n await replaceSkillDirectory(source, destination, Boolean(existingFiles));\n return existingFiles ? \"replaced\" : \"installed\";\n}\n\nasync function unconfigureAgentSkill(agent: AgentName, input: ConfigureInput): Promise {\n const source = input.skillSource ?? bundledSkillPath(input.cliEntry);\n const destination = input.skillPaths?.[agent] ?? defaultSkillPath(agent, input.env);\n const existingFiles = await readSkillDirectory(destination, false);\n if (!existingFiles) return \"absent\";\n const sourceFiles = await readSkillDirectory(source, true);\n if (!sourceFiles) throw new Error(`Bundled Skill directory is missing: ${source}`);\n const managed = skillFilesEqual(existingFiles, sourceFiles);\n if (!managed && !input.force) return input.dryRun ? \"would-preserve\" : \"preserved\";\n if (input.dryRun) return \"would-remove\";\n if (!managed) await backupSkillDirectory(destination);\n await rm(destination, { recursive: true, force: true });\n return \"removed\";\n}\n\nasync function readSkillDirectory(directory: string, required: boolean): Promise | undefined> {\n const files = new Map();\n const walk = async (current: string, relative: string): Promise => {\n const entries = await readdir(current, { withFileTypes: true });\n entries.sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of entries) {\n const entryPath = path.join(current, entry.name);\n const entryRelative = relative ? path.join(relative, entry.name) : entry.name;\n if (entry.isDirectory()) {\n await walk(entryPath, entryRelative);\n } else if (entry.isFile()) {\n files.set(entryRelative, await readFile(entryPath));\n } else {\n throw new Error(`Skill directory contains an unsupported entry: ${entryPath}`);\n }\n }\n };\n try {\n await walk(directory, \"\");\n } catch (error) {\n if (!required && (error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n if (!files.has(\"SKILL.md\")) throw new Error(`Skill directory is missing SKILL.md: ${directory}`);\n return files;\n}\n\nfunction skillFilesEqual(left: Map, right: Map): boolean {\n if (left.size !== right.size) return false;\n return [...left].every(([name, value]) => right.get(name)?.equals(value) === true);\n}\n\nasync function backupSkillDirectory(directory: string): Promise {\n const backup = `${directory}.crafttable-mcp.backup`;\n try {\n await cp(directory, backup, { recursive: true, force: false, errorOnExist: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n }\n return backup;\n}\n\nasync function replaceSkillDirectory(source: string, destination: string, existed: boolean): Promise {\n await mkdir(path.dirname(destination), { recursive: true });\n const temporary = `${destination}.${process.pid}.${randomUUID()}.tmp`;\n await cp(source, temporary, { recursive: true, force: false, errorOnExist: true });\n try {\n if (existed) await rm(destination, { recursive: true, force: true });\n await rename(temporary, destination);\n } catch (error) {\n if (existed && !await pathExists(destination)) {\n const backup = `${destination}.crafttable-mcp.backup`;\n if (await pathExists(backup)) await cp(backup, destination, { recursive: true });\n }\n throw error;\n } finally {\n await rm(temporary, { recursive: true, force: true });\n }\n}\n\nasync function pathExists(filePath: string): Promise {\n try {\n await stat(filePath);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n\nasync function backupAndAtomicWrite(filePath: string, updated: string, existed: boolean): Promise {\n await mkdir(path.dirname(filePath), { recursive: true });\n if (existed) {\n try {\n await copyFile(filePath, `${filePath}.crafttable-mcp.backup`, constants.COPYFILE_EXCL);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n }\n }\n const temporary = `${filePath}.${process.pid}.tmp`;\n await writeFile(temporary, updated, \"utf8\");\n await rename(temporary, filePath);\n}\n\nasync function readOptionalFile(filePath: string): Promise {\n try {\n return await readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nfunction arraysEqual(value: unknown, expected: string[]): boolean {\n return Array.isArray(value) && value.length === expected.length && value.every((item, index) => item === expected[index]);\n}\n\nfunction expandTarget(target: AgentTarget): AgentName[] {\n if (target === \"all\") return [\"codex\", \"claude\", \"opencode\"];\n if ([\"codex\", \"claude\", \"opencode\"].includes(target)) return [target as AgentName];\n throw new Error(\"Agent must be one of: codex, claude, opencode, all\");\n}\n\nasync function terminalConfirm(message: string): Promise {\n const readline = createInterface({ input: process.stdin, output: process.stderr });\n try {\n return /^y(es)?$/i.test((await readline.question(`${message} [y/N] `)).trim());\n } finally {\n readline.close();\n }\n}\n\nasync function requireSuccess(resultPromise: Promise, operation: string): Promise {\n const result = await resultPromise;\n if (result.code !== 0) throw new Error(`${operation} failed: ${safeCommandError(result)}`);\n}\n\nfunction safeCommandError(result: CommandResult): string {\n return (result.stderr || result.stdout || `exit code ${result.code}`).trim();\n}\n\nexport class SpawnCommandRunner implements CommandRunner {\n run(command: string, args: string[]): Promise {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, { shell: false, windowsHide: true, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.setEncoding(\"utf8\").on(\"data\", (chunk) => { stdout += String(chunk); });\n child.stderr?.setEncoding(\"utf8\").on(\"data\", (chunk) => { stderr += String(chunk); });\n child.once(\"error\", (error) => reject(new Error(`Could not run ${command}: ${errorMessage(error)}`)));\n child.once(\"close\", (code) => resolve({ code: code ?? 1, stdout, stderr }));\n });\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { OAuthDiscoveryState } from \"@modelcontextprotocol/sdk/client/auth.js\";\n\nexport const DEFAULT_MCP_URL = \"https://crafttable.crash.work/mcp\";\nexport const DEFAULT_CLIENT_ID = \"crafttable-mcp-cli\";\nexport const DEFAULT_CALLBACK_PORT = 48321;\nexport const OAUTH_SCOPES = \"openid profile email offline_access\";\n\nexport type ClientOptions = {\n url: URL;\n clientId: string;\n callbackPort: number;\n};\n\nexport function resolveClientOptions(input: {\n url?: string;\n clientId?: string;\n callbackPort?: string | number;\n env?: NodeJS.ProcessEnv;\n} = {}): ClientOptions {\n const env = input.env ?? process.env;\n const url = validateMcpUrl(input.url ?? env.CRAFTTABLE_MCP_URL ?? DEFAULT_MCP_URL);\n const clientId = (input.clientId ?? env.CRAFTTABLE_MCP_OAUTH_CLIENT_ID ?? DEFAULT_CLIENT_ID).trim();\n if (!clientId) throw new Error(\"OAuth client ID must not be empty\");\n const callbackPort = Number(input.callbackPort ?? env.CRAFTTABLE_MCP_OAUTH_CALLBACK_PORT ?? DEFAULT_CALLBACK_PORT);\n if (!Number.isInteger(callbackPort) || callbackPort < 1 || callbackPort > 65535) {\n throw new Error(\"OAuth callback port must be an integer between 1 and 65535\");\n }\n return { url, clientId, callbackPort };\n}\n\nexport function validateMcpUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"MCP URL must be an absolute URL\");\n }\n if (url.username || url.password || url.search || url.hash) {\n throw new Error(\"MCP URL must not include credentials, query parameters, or a fragment\");\n }\n const local = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && local)) {\n throw new Error(\"MCP URL must use HTTPS unless it targets localhost\");\n }\n url.pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n return url;\n}\n\nexport function credentialAccount(options: Pick): string {\n return createHash(\"sha256\").update(`${options.url.toString()}\\0${options.clientId}`).digest(\"hex\");\n}\n\nexport function platformConfigDir(env: NodeJS.ProcessEnv = process.env, platform = process.platform): string {\n if (platform === \"win32\") return path.join(env.APPDATA || path.join(os.homedir(), \"AppData\", \"Roaming\"), \"GameCraftTable\", \"mcp-client\");\n if (platform === \"darwin\") return path.join(os.homedir(), \"Library\", \"Application Support\", \"GameCraftTable\", \"mcp-client\");\n return path.join(env.XDG_CONFIG_HOME || path.join(os.homedir(), \".config\"), \"gamecrafttable\", \"mcp-client\");\n}\n\ntype DiscoveryFile = {\n version: 1;\n entries: Record;\n};\n\nexport class DiscoveryStore {\n readonly filePath: string;\n\n constructor(configDir = platformConfigDir()) {\n this.filePath = path.join(configDir, \"discovery.json\");\n }\n\n async get(account: string): Promise {\n return (await this.read()).entries[account];\n }\n\n async set(account: string, state: OAuthDiscoveryState): Promise {\n const document = await this.read();\n document.entries[account] = state;\n await atomicWriteJson(this.filePath, document);\n }\n\n async delete(account: string): Promise {\n const document = await this.read();\n if (!(account in document.entries)) return;\n delete document.entries[account];\n await atomicWriteJson(this.filePath, document);\n }\n\n private async read(): Promise {\n try {\n const value = JSON.parse(await readFile(this.filePath, \"utf8\")) as Partial;\n return { version: 1, entries: value.entries && typeof value.entries === \"object\" ? value.entries : {} };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { version: 1, entries: {} };\n throw new Error(`Could not read OAuth discovery cache: ${errorMessage(error)}`);\n }\n }\n}\n\nexport async function atomicWriteJson(filePath: string, value: unknown): Promise {\n await mkdir(path.dirname(filePath), { recursive: true });\n const temporary = `${filePath}.${process.pid}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, { encoding: \"utf8\", mode: 0o600 });\n await rename(temporary, filePath);\n}\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { DiscoveryStore } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\nimport { connectRemote } from \"./remote.js\";\n\nexport async function serveBridge(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n serviceToken = process.env.CRAFTTABLE_MCP_TOKEN?.trim(),\n): Promise {\n const upstream = await connectRemote(options, tokenStore, discoveryStore, serviceToken);\n if (upstream.authentication === \"service-token\") {\n process.stderr.write(\"CraftTable MCP: using the legacy service-account token path.\\n\");\n }\n const server = createProxyServer(upstream.client);\n const transport = new StdioServerTransport();\n const close = async (): Promise => {\n await server.close().catch(() => undefined);\n await upstream.close().catch(() => undefined);\n };\n process.once(\"SIGINT\", () => void close());\n process.once(\"SIGTERM\", () => void close());\n try {\n await server.connect(transport);\n } catch (error) {\n await close();\n throw error;\n }\n}\n\nexport function createProxyServer(upstream: {\n listTools: (params?: { cursor?: string }) => Promise;\n callTool: (params: { name: string; arguments?: Record }) => Promise;\n listResources: (params?: { cursor?: string }) => Promise;\n listResourceTemplates: (params?: { cursor?: string }) => Promise;\n readResource: (params: { uri: string }) => Promise;\n}): Server {\n const server = new Server({ name: \"crafttable-mcp-stdio-bridge\", version: \"0.1.3\" }, {\n capabilities: {\n tools: {},\n resources: {},\n },\n });\n server.setRequestHandler(ListToolsRequestSchema, (request) => upstream.listTools(request.params) as never);\n server.setRequestHandler(CallToolRequestSchema, (request) => upstream.callTool(request.params) as never);\n server.setRequestHandler(ListResourcesRequestSchema, (request) => upstream.listResources(request.params) as never);\n server.setRequestHandler(ListResourceTemplatesRequestSchema, (request) => upstream.listResourceTemplates(request.params) as never);\n server.setRequestHandler(ReadResourceRequestSchema, (request) => upstream.readResource(request.params) as never);\n return server;\n}\n", "import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport open from \"open\";\nimport { OAuthCallbackServer } from \"./callbackServer.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { credentialAccount, DiscoveryStore, errorMessage } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\nimport { CraftTableOAuthProvider } from \"./oauthProvider.js\";\n\nexport type RemoteConnection = {\n client: Client;\n transport: StreamableHTTPClientTransport;\n authentication: \"oauth\" | \"service-token\";\n close: () => Promise;\n};\n\nexport async function connectRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n serviceToken = process.env.CRAFTTABLE_MCP_TOKEN?.trim(),\n): Promise {\n const tokens = await tokenStore.get(credentialAccount(options));\n if (tokens) {\n const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, () => {\n throw new Error(\"OAuth login is required; run `crafttable-mcp login`\");\n });\n return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, { authProvider: provider }), \"oauth\");\n }\n if (serviceToken) {\n return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, {\n requestInit: { headers: { authorization: `Bearer ${serviceToken}` } },\n }), \"service-token\");\n }\n throw new Error(\"Not logged in; run `crafttable-mcp login` or set CRAFTTABLE_MCP_TOKEN for the legacy service-account path\");\n}\n\nexport async function loginRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n input: { browser: boolean; timeoutMs?: number; writeLine?: (value: string) => void } = { browser: true },\n): Promise<{ alreadyAuthenticated: boolean; toolCount: number }> {\n const writeLine = input.writeLine ?? ((value) => process.stderr.write(`${value}\\n`));\n await requireOAuthProtectedResourceMetadata(options.url);\n let authorizationUrl: URL | undefined;\n const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, async (url) => {\n authorizationUrl = url;\n if (!input.browser) {\n writeLine(`Open this URL to log in:\\n${url.toString()}`);\n return;\n }\n try {\n await open(url.toString(), { wait: false });\n writeLine(\"Opened the system browser for CraftTable login.\");\n } catch (error) {\n writeLine(`Could not open the browser (${errorMessage(error)}). Open this URL manually:\\n${url.toString()}`);\n }\n });\n const callback = new OAuthCallbackServer(options.callbackPort, (state) => provider.validateState(state));\n await callback.listen();\n const firstClient = new Client({ name: \"crafttable-mcp-cli\", version: \"0.1.3\" });\n const firstTransport = new StreamableHTTPClientTransport(options.url, { authProvider: provider });\n try {\n try {\n await firstClient.connect(firstTransport);\n const tools = await firstClient.listTools();\n return { alreadyAuthenticated: true, toolCount: tools.tools.length };\n } catch (error) {\n if (!(error instanceof UnauthorizedError) && !authorizationUrl) throw error;\n const { code } = await callback.wait(input.timeoutMs);\n await firstTransport.finishAuth(code);\n }\n } finally {\n await firstClient.close().catch(() => undefined);\n await callback.close().catch(() => undefined);\n }\n\n const connection = await connectRemote(options, tokenStore, discoveryStore, \"\");\n try {\n const tools = await connection.client.listTools();\n return { alreadyAuthenticated: false, toolCount: tools.tools.length };\n } finally {\n await connection.close();\n }\n}\n\nexport async function logoutRemote(\n options: ClientOptions,\n tokenStore: TokenStore,\n discoveryStore: DiscoveryStore,\n localOnly: boolean,\n fetchFn: typeof fetch = fetch,\n): Promise<{ hadCredential: boolean; revoked: boolean }> {\n const account = credentialAccount(options);\n const tokens = await tokenStore.get(account);\n if (tokens && !localOnly) {\n const endpoint = await discoverRevocationEndpoint(options.url, fetchFn);\n await revokeTokens(endpoint, options.clientId, tokens, fetchFn);\n }\n await tokenStore.delete(account);\n await discoveryStore.delete(account);\n return { hadCredential: Boolean(tokens), revoked: Boolean(tokens && !localOnly) };\n}\n\nasync function connectWithTransport(\n options: ClientOptions,\n transport: StreamableHTTPClientTransport,\n authentication: RemoteConnection[\"authentication\"],\n): Promise {\n const client = new Client({ name: \"crafttable-mcp-cli\", version: \"0.1.3\" });\n try {\n await client.connect(transport);\n } catch (error) {\n await client.close().catch(() => undefined);\n if (error instanceof UnauthorizedError) throw new Error(\"OAuth login is required; run `crafttable-mcp login`\");\n throw error;\n }\n return {\n client,\n transport,\n authentication,\n close: () => client.close(),\n };\n}\n\nasync function discoverRevocationEndpoint(resource: URL, fetchFn: typeof fetch): Promise {\n const protectedMetadata = await requireOAuthProtectedResourceMetadata(resource, fetchFn);\n const issuer = Array.isArray(protectedMetadata.authorization_servers)\n ? protectedMetadata.authorization_servers.find((value): value is string => typeof value === \"string\")\n : undefined;\n if (!issuer) throw new Error(\"OAuth protected-resource metadata has no authorization server\");\n const issuerUrl = new URL(issuer);\n const candidates = [\n new URL(`${issuerUrl.toString().replace(/\\/$/, \"\")}/.well-known/openid-configuration`),\n new URL(`/.well-known/openid-configuration${issuerUrl.pathname === \"/\" ? \"\" : issuerUrl.pathname}`, issuerUrl.origin),\n ];\n for (const candidate of candidates) {\n const response = await fetchFn(candidate, { headers: { accept: \"application/json\" } });\n if (!response.ok) continue;\n try {\n const metadata = await response.json() as { revocation_endpoint?: unknown };\n if (typeof metadata.revocation_endpoint === \"string\") return new URL(metadata.revocation_endpoint);\n } catch {\n // Try the next standards-compatible discovery location.\n }\n }\n throw new Error(\"OAuth authorization server does not advertise a revocation endpoint\");\n}\n\nexport async function requireOAuthProtectedResourceMetadata(\n resource: URL,\n fetchFn: typeof fetch = fetch,\n): Promise<{ authorization_servers?: unknown }> {\n const metadataUrl = new URL(`/.well-known/oauth-protected-resource${resource.pathname === \"/\" ? \"\" : resource.pathname}`, resource.origin);\n let response: Response;\n try {\n response = await fetchFn(metadataUrl, { headers: { accept: \"application/json\" } });\n } catch (error) {\n throw new Error(`Could not reach OAuth protected-resource metadata at ${metadataUrl}: ${errorMessage(error)}`);\n }\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!response.ok) {\n throw new Error(`OAuth is not enabled for ${resource}; protected-resource metadata at ${metadataUrl} returned HTTP ${response.status}`);\n }\n if (!contentType.includes(\"application/json\")) {\n throw new Error(`OAuth is not enabled for ${resource}; protected-resource metadata at ${metadataUrl} returned ${contentType || \"an unknown content type\"} instead of JSON`);\n }\n try {\n return await response.json() as { authorization_servers?: unknown };\n } catch {\n throw new Error(`OAuth protected-resource metadata at ${metadataUrl} is not valid JSON`);\n }\n}\n\nasync function revokeTokens(endpoint: URL, clientId: string, tokens: OAuthTokens, fetchFn: typeof fetch): Promise {\n const candidates = [tokens.refresh_token\n ? { token: tokens.refresh_token, hint: \"refresh_token\" }\n : { token: tokens.access_token, hint: \"access_token\" }];\n for (const value of candidates) {\n const response = await fetchFn(endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({ token: value.token, token_type_hint: value.hint, client_id: clientId }),\n });\n if (!response.ok) throw new Error(`OAuth token revocation returned HTTP ${response.status}; local credentials were retained`);\n }\n}\n", "import { createServer, type Server } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nexport type OAuthCallback = { code: string };\n\nexport class OAuthCallbackServer {\n private server?: Server;\n private resolveResult?: (value: OAuthCallback) => void;\n private rejectResult?: (reason: Error) => void;\n private readonly result = new Promise((resolve, reject) => {\n this.resolveResult = resolve;\n this.rejectResult = reject;\n });\n\n constructor(\n private readonly port: number,\n private readonly validateState: (state: string | null) => boolean,\n ) {\n // A very fast browser callback can arrive before loginRemote starts awaiting it.\n // Keep rejection handled while preserving the original promise for wait().\n void this.result.catch(() => undefined);\n }\n\n async listen(): Promise {\n if (this.server) throw new Error(\"OAuth callback server is already running\");\n this.server = createServer((request, response) => {\n const url = new URL(request.url ?? \"/\", `http://127.0.0.1:${this.port}`);\n if (request.method !== \"GET\" || url.pathname !== \"/oauth/callback\") {\n response.writeHead(404, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"Not found\");\n return;\n }\n const oauthError = url.searchParams.get(\"error\");\n if (oauthError) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth login failed. Return to the terminal.\");\n this.rejectResult?.(new Error(`OAuth authorization failed: ${oauthError}`));\n return;\n }\n if (!this.validateState(url.searchParams.get(\"state\"))) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth state did not match. Return to the terminal.\");\n this.rejectResult?.(new Error(\"OAuth callback state did not match\"));\n return;\n }\n const code = url.searchParams.get(\"code\");\n if (!code) {\n response.writeHead(400, { \"content-type\": \"text/plain; charset=utf-8\" }).end(\"OAuth authorization code is missing.\");\n this.rejectResult?.(new Error(\"OAuth callback did not include an authorization code\"));\n return;\n }\n response.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" }).end(\"CraftTable MCP

Login complete. You can close this window.

\");\n this.resolveResult?.({ code });\n });\n await new Promise((resolve, reject) => {\n const onError = (error: Error) => reject(new Error(`Could not listen on OAuth callback port ${this.port}: ${error.message}`));\n this.server!.once(\"error\", onError);\n this.server!.listen(this.port, \"127.0.0.1\", () => {\n this.server!.off(\"error\", onError);\n resolve();\n });\n });\n const address = this.server.address() as AddressInfo | null;\n if (!address || address.port !== this.port) throw new Error(`OAuth callback server did not bind port ${this.port}`);\n }\n\n async wait(timeoutMs = 10 * 60 * 1000): Promise {\n let timeout: NodeJS.Timeout | undefined;\n try {\n return await Promise.race([\n this.result,\n new Promise((_resolve, reject) => {\n timeout = setTimeout(() => reject(new Error(\"OAuth callback timed out\")), timeoutMs);\n }),\n ]);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n\n async close(): Promise {\n if (!this.server) return;\n const server = this.server;\n this.server = undefined;\n await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));\n }\n}\n", "import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type { OAuthClientProvider, OAuthDiscoveryState } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { ClientOptions } from \"./config.js\";\nimport { credentialAccount, DiscoveryStore, OAUTH_SCOPES } from \"./config.js\";\nimport type { TokenStore } from \"./credentials.js\";\n\nexport class CraftTableOAuthProvider implements OAuthClientProvider {\n readonly redirectUrl: URL;\n readonly clientMetadata: OAuthClientMetadata;\n private readonly account: string;\n private readonly expectedState: string;\n private codeVerifierValue?: string;\n\n constructor(\n private readonly options: ClientOptions,\n private readonly tokenStore: TokenStore,\n private readonly discoveryStore: DiscoveryStore,\n private readonly onRedirect: (url: URL) => void | Promise,\n state = randomBytes(32).toString(\"base64url\"),\n ) {\n this.redirectUrl = new URL(`http://127.0.0.1:${options.callbackPort}/oauth/callback`);\n this.clientMetadata = {\n client_name: \"CraftTable MCP CLI\",\n redirect_uris: [this.redirectUrl.toString()],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: OAUTH_SCOPES,\n };\n this.account = credentialAccount(options);\n this.expectedState = state;\n }\n\n state(): string {\n return this.expectedState;\n }\n\n validateState(value: string | null): boolean {\n if (!value) return false;\n const expected = Buffer.from(this.expectedState);\n const actual = Buffer.from(value);\n return expected.length === actual.length && timingSafeEqual(expected, actual);\n }\n\n clientInformation(): OAuthClientInformationMixed {\n return { client_id: this.options.clientId };\n }\n\n tokens(): Promise {\n return this.tokenStore.get(this.account);\n }\n\n saveTokens(tokens: OAuthTokens): Promise {\n return this.tokenStore.set(this.account, tokens);\n }\n\n redirectToAuthorization(url: URL): void | Promise {\n return this.onRedirect(url);\n }\n\n saveCodeVerifier(codeVerifier: string): void {\n this.codeVerifierValue = codeVerifier;\n }\n\n codeVerifier(): string {\n if (!this.codeVerifierValue) throw new Error(\"OAuth PKCE verifier is missing or expired\");\n return this.codeVerifierValue;\n }\n\n discoveryState(): Promise {\n return this.discoveryStore.get(this.account);\n }\n\n saveDiscoveryState(state: OAuthDiscoveryState): Promise {\n return this.discoveryStore.set(this.account, state);\n }\n\n async invalidateCredentials(scope: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): Promise {\n if (scope === \"all\" || scope === \"tokens\") await this.tokenStore.delete(this.account);\n if (scope === \"all\" || scope === \"discovery\") await this.discoveryStore.delete(this.account);\n if (scope === \"all\" || scope === \"verifier\") this.codeVerifierValue = undefined;\n }\n}\n", "import { randomUUID } from \"node:crypto\";\nimport type { OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nexport const KEYRING_SERVICE = \"CraftTable MCP\";\nconst KEYRING_CHUNK_SIZE = 1000;\n\ntype CredentialEntry = {\n getPassword(): Promise;\n setPassword(password: string): Promise;\n deleteCredential(): Promise;\n};\n\ntype CredentialEntryFactory = (account: string) => Promise;\n\ntype ChunkManifest = {\n version: 2;\n generation: string;\n chunks: number;\n};\n\nexport interface TokenStore {\n get(account: string): Promise;\n set(account: string, tokens: OAuthTokens): Promise;\n delete(account: string): Promise;\n}\n\nexport class KeyringTokenStore implements TokenStore {\n constructor(private readonly entryFactory: CredentialEntryFactory = keyringEntry) {}\n\n async get(account: string): Promise {\n let serialized: string | undefined;\n try {\n serialized = await this.readPassword(account);\n } catch (error) {\n throw keyringError(error);\n }\n if (!serialized) return undefined;\n\n const manifest = parseChunkManifest(serialized);\n if (manifest) {\n try {\n const chunks = await Promise.all(Array.from({ length: manifest.chunks }, (_, index) =>\n this.readPassword(chunkAccount(account, manifest.generation, index))));\n if (chunks.some((chunk) => chunk === undefined)) throw new Error(\"missing credential chunk\");\n serialized = Buffer.from(chunks.join(\"\"), \"base64\").toString(\"utf8\");\n } catch (error) {\n if (error instanceof Error && error.message === \"missing credential chunk\") throw invalidCredentialError();\n throw keyringError(error);\n }\n }\n\n try {\n const value = JSON.parse(serialized) as OAuthTokens;\n if (!value.access_token || !value.token_type) throw new Error(\"missing token fields\");\n return value;\n } catch {\n throw invalidCredentialError();\n }\n }\n\n async set(account: string, tokens: OAuthTokens): Promise {\n const encoded = Buffer.from(JSON.stringify(tokens), \"utf8\").toString(\"base64\");\n const chunks = splitCredential(encoded);\n const generation = randomUUID().replaceAll(\"-\", \"\");\n const manifest: ChunkManifest = { version: 2, generation, chunks: chunks.length };\n let previous: string | undefined;\n const writtenAccounts: string[] = [];\n\n try {\n previous = await this.readPassword(account);\n for (const [index, chunk] of chunks.entries()) {\n const partAccount = chunkAccount(account, generation, index);\n await (await this.entryFactory(partAccount)).setPassword(chunk);\n writtenAccounts.push(partAccount);\n }\n await (await this.entryFactory(account)).setPassword(JSON.stringify(manifest));\n } catch (error) {\n await Promise.allSettled(writtenAccounts.map((partAccount) => this.deletePassword(partAccount)));\n throw keyringError(error);\n }\n\n const previousManifest = previous && parseChunkManifest(previous);\n if (previousManifest) {\n await Promise.allSettled(Array.from({ length: previousManifest.chunks }, (_, index) =>\n this.deletePassword(chunkAccount(account, previousManifest.generation, index))));\n }\n }\n\n async delete(account: string): Promise {\n try {\n const serialized = await this.readPassword(account);\n const manifest = serialized ? parseChunkManifest(serialized) : undefined;\n await this.deletePassword(account);\n if (manifest) {\n await Promise.all(Array.from({ length: manifest.chunks }, (_, index) =>\n this.deletePassword(chunkAccount(account, manifest.generation, index))));\n }\n } catch (error) {\n throw keyringError(error);\n }\n }\n\n private async readPassword(account: string): Promise {\n try {\n return await (await this.entryFactory(account)).getPassword();\n } catch (error) {\n if (isMissingCredential(error)) return undefined;\n throw error;\n }\n }\n\n private async deletePassword(account: string): Promise {\n try {\n await (await this.entryFactory(account)).deleteCredential();\n } catch (error) {\n if (!isMissingCredential(error)) throw error;\n }\n }\n}\n\nfunction splitCredential(value: string): string[] {\n const chunks: string[] = [];\n for (let offset = 0; offset < value.length; offset += KEYRING_CHUNK_SIZE) {\n chunks.push(value.slice(offset, offset + KEYRING_CHUNK_SIZE));\n }\n return chunks.length ? chunks : [\"\"];\n}\n\nfunction chunkAccount(account: string, generation: string, index: number): string {\n return `${account}:v2:${generation}:${index}`;\n}\n\nfunction parseChunkManifest(value: string): ChunkManifest | undefined {\n try {\n const parsed = JSON.parse(value) as Partial;\n if (parsed.version !== 2 || typeof parsed.generation !== \"string\" || !/^[0-9a-f]{32}$/.test(parsed.generation)\n || !Number.isInteger(parsed.chunks) || (parsed.chunks ?? 0) < 1 || (parsed.chunks ?? 0) > 100) return undefined;\n return parsed as ChunkManifest;\n } catch {\n return undefined;\n }\n}\n\nfunction isMissingCredential(error: unknown): boolean {\n const message = String((error as Error)?.message ?? error).toLowerCase();\n return message.includes(\"no entry\") || message.includes(\"not found\");\n}\n\nfunction invalidCredentialError(): Error {\n return new Error(\"The saved CraftTable MCP credential is invalid; run `crafttable-mcp logout --local-only` and log in again\");\n}\n\nasync function keyringEntry(account: string): Promise {\n try {\n const { AsyncEntry } = await import(\"@napi-rs/keyring\");\n return new AsyncEntry(KEYRING_SERVICE, account);\n } catch (error) {\n throw keyringError(error);\n }\n}\n\nfunction keyringError(error: unknown): Error {\n if (error instanceof Error && error.message.startsWith(\"The operating-system credential store is unavailable\")) return error;\n const detail = error instanceof Error ? error.message : String(error);\n return new Error(`The operating-system credential store is unavailable (${detail}). Enable Windows Credential Manager, macOS Keychain, or a Secret Service provider, then retry; plaintext token storage is not supported.`);\n}\n"], + "mappings": "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", "names": ["mkdir", "readFile", "rename", "writeFile", "os", "path", "path", "os", "readFile", "mkdir", "rename", "writeFile", "randomUUID"] } diff --git a/src/oauthProvider.ts b/src/oauthProvider.ts index 684e249..33252f3 100644 --- a/src/oauthProvider.ts +++ b/src/oauthProvider.ts @@ -5,7 +5,7 @@ import type { ClientOptions } from "./config.js"; import { credentialAccount, DiscoveryStore, OAUTH_SCOPES } from "./config.js"; import type { TokenStore } from "./credentials.js"; -export class GameCraftOAuthProvider implements OAuthClientProvider { +export class CraftTableOAuthProvider implements OAuthClientProvider { readonly redirectUrl: URL; readonly clientMetadata: OAuthClientMetadata; private readonly account: string; diff --git a/src/remote.ts b/src/remote.ts index adb86e4..3a97764 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -7,7 +7,7 @@ import { OAuthCallbackServer } from "./callbackServer.js"; import type { ClientOptions } from "./config.js"; import { credentialAccount, DiscoveryStore, errorMessage } from "./config.js"; import type { TokenStore } from "./credentials.js"; -import { GameCraftOAuthProvider } from "./oauthProvider.js"; +import { CraftTableOAuthProvider } from "./oauthProvider.js"; export type RemoteConnection = { client: Client; @@ -24,7 +24,7 @@ export async function connectRemote( ): Promise { const tokens = await tokenStore.get(credentialAccount(options)); if (tokens) { - const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, () => { + const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, () => { throw new Error("OAuth login is required; run `crafttable-mcp login`"); }); return connectWithTransport(options, new StreamableHTTPClientTransport(options.url, { authProvider: provider }), "oauth"); @@ -46,7 +46,7 @@ export async function loginRemote( const writeLine = input.writeLine ?? ((value) => process.stderr.write(`${value}\n`)); await requireOAuthProtectedResourceMetadata(options.url); let authorizationUrl: URL | undefined; - const provider = new GameCraftOAuthProvider(options, tokenStore, discoveryStore, async (url) => { + const provider = new CraftTableOAuthProvider(options, tokenStore, discoveryStore, async (url) => { authorizationUrl = url; if (!input.browser) { writeLine(`Open this URL to log in:\n${url.toString()}`); @@ -54,7 +54,7 @@ export async function loginRemote( } try { await open(url.toString(), { wait: false }); - writeLine("Opened the system browser for Game-CraftTable login."); + writeLine("Opened the system browser for CraftTable login."); } catch (error) { writeLine(`Could not open the browser (${errorMessage(error)}). Open this URL manually:\n${url.toString()}`); } diff --git a/test/configAndOAuth.test.ts b/test/configAndOAuth.test.ts index 2b92dba..ff62e33 100644 --- a/test/configAndOAuth.test.ts +++ b/test/configAndOAuth.test.ts @@ -5,7 +5,7 @@ import type { OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js"; import { OAuthCallbackServer } from "../src/callbackServer.js"; import { credentialAccount, resolveClientOptions, validateMcpUrl } from "../src/config.js"; import type { TokenStore } from "../src/credentials.js"; -import { GameCraftOAuthProvider } from "../src/oauthProvider.js"; +import { CraftTableOAuthProvider } from "../src/oauthProvider.js"; import { logoutRemote, requireOAuthProtectedResourceMetadata } from "../src/remote.js"; class MemoryTokens implements TokenStore { @@ -38,7 +38,7 @@ test("OAuth provider validates state and replaces rotated refresh tokens", async const options = resolveClientOptions({ url: "https://example.test/mcp", clientId: "client", callbackPort: 48321, env: {} }); const tokens = new MemoryTokens(); const discovery = new MemoryDiscovery(); - const provider = new GameCraftOAuthProvider(options, tokens, discovery as never, () => undefined, "expected-state"); + const provider = new CraftTableOAuthProvider(options, tokens, discovery as never, () => undefined, "expected-state"); assert.equal(provider.validateState("expected-state"), true); assert.equal(provider.validateState("wrong-state"), false); provider.saveCodeVerifier("verifier");