@onyxsecurity/mcp-gateway 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onyxsecurity/mcp-gateway",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "prebuild": "npx tsx scripts/generate-config.ts",
@@ -1,2 +0,0 @@
1
- import{randomUUID as e}from"crypto";import{join as t}from"node:path";import{homedir as n}from"node:os";import r from"env-var";import"dotenv/config";const i={APP_VERSION:`1.0.0`,NODE_ENV:`development`,SENTRY_DSN:null,SENTRY_ENABLED:!1},a=r.get,o=i.APP_VERSION,s=e=>{let t={};if(e){let n=e.split(`,`);for(let e of n){let[n,...r]=e.split(`:`);n&&r.length>0&&(t[n.trim()]=r.join(`:`).trim())}}return t},c=e(),l=a(`NODE_ENV`).default(i.NODE_ENV||`development`).asEnum([`development`,`production`,`staging`,`test`]),u=a(`MCP_GATEWAY_SENTRY_DSN`).default(i.SENTRY_DSN||``).asString()||null,d=a(`MCP_GATEWAY_SENTRY_ENABLED`).default(String(i.SENTRY_ENABLED??!1)).asBool(),f=a(`DEBUG`).default(`false`).asBool()||a(`MCP_GATEWAY_DEBUG`).default(`false`).asBool(),p=a(`MCP_GATEWAY_MIRROR_URL`).default(``).asString()||null,m=a(`MCP_GATEWAY_MIRROR_API_KEY`).default(``).asString()||null,h=(()=>{let e=a(`MCP_GATEWAY_MIRROR_HEADERS`).required(!1).asString();return e?s(e):{}})(),g=a(`MCP_GATEWAY_SCANNER_URL`).default(``).asString()||null,_=a(`MCP_GATEWAY_SCANNER_API_KEY`).default(``).asString()||void 0,v=(()=>{let e=a(`MCP_GATEWAY_SCANNER_HEADERS`).required(!1).asString();return e?s(e):{}})(),y=a(`MCP_GATEWAY_SCANNER_TIMEOUT_MS`).default(`20000`).asIntPositive(),b=a(`MCP_GATEWAY_SCANNER_FAIL_OPEN`).default(`true`).asBool(),x=a(`MCP_GATEWAY_COMMAND`).default(`mcp-gateway`).asString(),S=a(`CLIENT_APP_NAME`).default(``).asString(),C=a(`MCP_GATEWAY_LOG_DIR`).default(t(n(),`.onyx`,`mcp-gateway`,`logs`)).asString(),w={appVersion:o,clientAppName:S,debug:f,environment:l,logDir:C,mirror:{apiKey:m,enabled:!!p,headers:h,url:p},proxyCommand:x,scanner:{apiKey:_,enabled:!!g,failOpen:b,headers:v,timeoutMs:y,url:g},sentry:{debug:f&&l===`development`,dsn:u||void 0,enabled:d,environment:l,release:`mcp-gateway@${o}`,tracesSampleRate:l===`production`?1:0}};f&&console.debug(`[mcp-gateway] Configuration:`,{debug:w.debug,environment:w.environment,sentryEnabled:w.sentry.enabled,version:w.appVersion});export{o as APP_VERSION,S as CLIENT_APP_NAME,c as SESSION_ID,w as config};
2
- //# sourceMappingURL=env-B4Y1X0NP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"env-B4Y1X0NP.js","names":["BUILD_TIME_CONFIG: BuildTimeConfig","headers: Record<string, string>"],"sources":["../src/config/config.generated.ts","../src/config/env.ts"],"sourcesContent":["// THIS FILE IS AUTO-GENERATED - DO NOT EDIT MANUALLY\n// Generated at build time from environment variables\n\nimport type { BuildTimeConfig } from \"./config.js\";\n\nexport const BUILD_TIME_CONFIG: BuildTimeConfig = {\n \"APP_VERSION\": \"1.0.0\",\n \"NODE_ENV\": \"development\",\n \"SENTRY_DSN\": null,\n \"SENTRY_ENABLED\": false\n};\n","import { randomUUID } from \"crypto\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport envVar from \"env-var\";\nimport \"dotenv/config\";\n\nconst env = envVar.get;\n\nimport { BUILD_TIME_CONFIG } from \"./config.generated.js\";\n\nexport const APP_VERSION = BUILD_TIME_CONFIG.APP_VERSION;\n\n// Helper function to parse headers from environment variable\nconst parseHeaders = (headerString: string): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (headerString) {\n const headerPairs = headerString.split(\",\");\n for (const pair of headerPairs) {\n const [key, ...valueParts] = pair.split(\":\");\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join(\":\").trim();\n }\n }\n }\n return headers;\n};\n\nexport const SESSION_ID = randomUUID();\n\n// Environment configuration - runtime env vars take precedence over build-time config\nexport const NODE_ENV = env(\"NODE_ENV\")\n .default(BUILD_TIME_CONFIG.NODE_ENV || \"development\")\n .asEnum([\"development\", \"production\", \"staging\", \"test\"]);\n\nexport const SENTRY_DSN =\n env(\"MCP_GATEWAY_SENTRY_DSN\")\n .default(BUILD_TIME_CONFIG.SENTRY_DSN || \"\")\n .asString() || null;\n\nexport const SENTRY_ENABLED = env(\"MCP_GATEWAY_SENTRY_ENABLED\")\n .default(String(BUILD_TIME_CONFIG.SENTRY_ENABLED ?? false))\n .asBool();\nexport const DEBUG_MODE = env(\"DEBUG\").default(\"false\").asBool() || env(\"MCP_GATEWAY_DEBUG\").default(\"false\").asBool();\n\nexport const MIRROR_URL = env(\"MCP_GATEWAY_MIRROR_URL\").default(\"\").asString() || null;\n\nexport const MIRROR_API_KEY = env(\"MCP_GATEWAY_MIRROR_API_KEY\").default(\"\").asString() || null;\n\nexport const MIRROR_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_MIRROR_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const SCANNER_URL = env(\"MCP_GATEWAY_SCANNER_URL\").default(\"\").asString() || null;\n\nexport const SCANNER_API_KEY = env(\"MCP_GATEWAY_SCANNER_API_KEY\").default(\"\").asString() || undefined;\n\nexport const SCANNER_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_SCANNER_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const SCANNER_TIMEOUT_MS = env(\"MCP_GATEWAY_SCANNER_TIMEOUT_MS\").default(\"20000\").asIntPositive();\n\nexport const SCANNER_FAIL_OPEN = env(\"MCP_GATEWAY_SCANNER_FAIL_OPEN\").default(\"true\").asBool();\n\nexport const PROXY_COMMAND = env(\"MCP_GATEWAY_COMMAND\").default(\"mcp-gateway\").asString();\n\nexport const CLIENT_APP_NAME = env(\"CLIENT_APP_NAME\").default(\"\").asString();\n\nexport const LOG_DIR = env(\"MCP_GATEWAY_LOG_DIR\").default(join(homedir(), \".onyx\", \"mcp-gateway\", \"logs\")).asString();\n\nexport const config = {\n appVersion: APP_VERSION,\n clientAppName: CLIENT_APP_NAME,\n debug: DEBUG_MODE,\n environment: NODE_ENV,\n logDir: LOG_DIR,\n mirror: {\n apiKey: MIRROR_API_KEY,\n enabled: Boolean(MIRROR_URL),\n headers: MIRROR_HEADERS,\n url: MIRROR_URL,\n },\n proxyCommand: PROXY_COMMAND,\n scanner: {\n apiKey: SCANNER_API_KEY,\n enabled: Boolean(SCANNER_URL),\n failOpen: SCANNER_FAIL_OPEN,\n headers: SCANNER_HEADERS,\n timeoutMs: SCANNER_TIMEOUT_MS,\n url: SCANNER_URL,\n },\n sentry: {\n debug: DEBUG_MODE && NODE_ENV === \"development\",\n dsn: SENTRY_DSN || undefined,\n enabled: SENTRY_ENABLED,\n environment: NODE_ENV,\n release: `mcp-gateway@${APP_VERSION}`,\n // Only enable tracing in production\n tracesSampleRate: NODE_ENV === \"production\" ? 1.0 : 0,\n },\n} as const;\n\n// Note: Don't use the logger here to avoid circular dependency issues\n// The logger hasn't been initialized yet when this config file is imported\n// Log configuration in debug mode\nif (DEBUG_MODE) {\n console.debug(\"[mcp-gateway] Configuration:\", {\n debug: config.debug,\n environment: config.environment,\n sentryEnabled: config.sentry.enabled,\n version: config.appVersion,\n });\n}\n"],"mappings":"oJAKA,MAAaA,EAAqC,CAChD,YAAe,QACf,SAAY,cACZ,WAAc,KACd,eAAkB,GACnB,CCJK,EAAM,EAAO,IAIN,EAAc,EAAkB,YAGvC,EAAgB,GAAiD,CACrE,IAAMC,EAAkC,EAAE,CAC1C,GAAI,EAAc,CAChB,IAAM,EAAc,EAAa,MAAM,IAAI,CAC3C,IAAK,IAAM,KAAQ,EAAa,CAC9B,GAAM,CAAC,EAAK,GAAG,GAAc,EAAK,MAAM,IAAI,CACxC,GAAO,EAAW,OAAS,IAC7B,EAAQ,EAAI,MAAM,EAAI,EAAW,KAAK,IAAI,CAAC,MAAM,GAIvD,OAAO,GAGI,EAAa,GAAY,CAGzB,EAAW,EAAI,WAAW,CACpC,QAAQ,EAAkB,UAAY,cAAc,CACpD,OAAO,CAAC,cAAe,aAAc,UAAW,OAAO,CAAC,CAE9C,EACX,EAAI,yBAAyB,CAC1B,QAAQ,EAAkB,YAAc,GAAG,CAC3C,UAAU,EAAI,KAEN,EAAiB,EAAI,6BAA6B,CAC5D,QAAQ,OAAO,EAAkB,gBAAkB,GAAM,CAAC,CAC1D,QAAQ,CACE,EAAa,EAAI,QAAQ,CAAC,QAAQ,QAAQ,CAAC,QAAQ,EAAI,EAAI,oBAAoB,CAAC,QAAQ,QAAQ,CAAC,QAAQ,CAEzG,EAAa,EAAI,yBAAyB,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAI,KAErE,EAAiB,EAAI,6BAA6B,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAI,KAE7E,OAAwB,CACnC,IAAM,EAAiB,EAAI,6BAA6B,CAAC,SAAS,GAAM,CAAC,UAAU,CAInF,OAHI,EACK,EAAa,EAAe,CAE9B,EAAE,IACP,CAES,EAAc,EAAI,0BAA0B,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAI,KAEvE,EAAkB,EAAI,8BAA8B,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAI,IAAA,GAE/E,OAAyB,CACpC,IAAM,EAAiB,EAAI,8BAA8B,CAAC,SAAS,GAAM,CAAC,UAAU,CAIpF,OAHI,EACK,EAAa,EAAe,CAE9B,EAAE,IACP,CAES,EAAqB,EAAI,iCAAiC,CAAC,QAAQ,QAAQ,CAAC,eAAe,CAE3F,EAAoB,EAAI,gCAAgC,CAAC,QAAQ,OAAO,CAAC,QAAQ,CAEjF,EAAgB,EAAI,sBAAsB,CAAC,QAAQ,cAAc,CAAC,UAAU,CAE5E,EAAkB,EAAI,kBAAkB,CAAC,QAAQ,GAAG,CAAC,UAAU,CAE/D,EAAU,EAAI,sBAAsB,CAAC,QAAQ,EAAK,GAAS,CAAE,QAAS,cAAe,OAAO,CAAC,CAAC,UAAU,CAExG,EAAS,CACpB,WAAY,EACZ,cAAe,EACf,MAAO,EACP,YAAa,EACb,OAAQ,EACR,OAAQ,CACN,OAAQ,EACR,QAAS,EAAQ,EACjB,QAAS,EACT,IAAK,EACN,CACD,aAAc,EACd,QAAS,CACP,OAAQ,EACR,QAAS,EAAQ,EACjB,SAAU,EACV,QAAS,EACT,UAAW,EACX,IAAK,EACN,CACD,OAAQ,CACN,MAAO,GAAc,IAAa,cAClC,IAAK,GAAc,IAAA,GACnB,QAAS,EACT,YAAa,EACb,QAAS,eAAe,IAExB,iBAAkB,IAAa,aAAe,EAAM,EACrD,CACF,CAKG,GACF,QAAQ,MAAM,+BAAgC,CAC5C,MAAO,EAAO,MACd,YAAa,EAAO,YACpB,cAAe,EAAO,OAAO,QAC7B,QAAS,EAAO,WACjB,CAAC"}
@@ -1,16 +0,0 @@
1
- import{config as e}from"./env-B4Y1X0NP.js";import{accessSync as t,constants as n,copyFileSync as r,existsSync as i,readFileSync as a,unlinkSync as o,writeFileSync as s}from"node:fs";import{join as c,resolve as l}from"node:path";import{homedir as u}from"node:os";const d=[c(u(),`.claude.json`),c(u(),`.claude`,`settings.json`),c(u(),`.claude`,`settings.local.json`),c(u(),`.config`,`claude`,`settings.json`),c(u(),`.config`,`claude`,`settings.local.json`),c(process.cwd(),`.claude.json`),c(process.cwd(),`.claude`,`settings.json`),c(process.cwd(),`.claude`,`settings.local.json`),c(process.cwd(),`.mcp.json`),c(process.cwd(),`mcp-config.json`),c(process.cwd(),`.claude-mcp.json`)];function f(e){let t=`${e}.mcp-gateway-backup`;try{return r(e,t),t}catch(t){throw Error(`Failed to create backup of ${e}: ${t}`)}}function p(e){let t=`${e}.mcp-gateway-backup`;if(i(t))try{o(t)}catch(e){throw Error(`Failed to delete backup ${t}: ${e}`)}}function m(){let e=[];for(let t of d)_(t)&&e.push(t);return e}async function h(){let e=[],t=new Set;for(let n of d)try{i(n)&&!t.has(n)&&(t.add(n),e.push({isWritable:O(n),path:n,type:D(n)}))}catch{}return e}function g(e,t=[]){let n=[];if(!e||typeof e!=`object`)return n;for(let[r,i]of Object.entries(e))r===`mcpServers`&&typeof i==`object`&&!Array.isArray(i)?n.push({path:[...t,r],servers:i}):typeof i==`object`&&i&&!Array.isArray(i)&&n.push(...g(i,[...t,r]));return n}function _(e){let t=`${e}.mcp-gateway-backup`;return i(t)}async function v(e={}){await T(e),console.log(`šŸ” Scanning for Claude Code MCP configurations...
2
- `);let t=await h();if(t.length===0){console.log(`āŒ No MCP configuration files found.`),console.log(` Expected locations include:`),console.log(` • ~/.claude.json`),console.log(` • ~/.claude/settings.json`),console.log(` • ~/.claude/settings.local.json`),console.log(` • ./.claude/settings.json (project)`),console.log(` • ./.claude/settings.local.json (project)`),console.log(` • ./.mcp.json (project)`);return}let n=0,r=0,i=0;for(let a of t){if(console.log(`šŸ“ ${a.path}`),!a.isWritable){console.log(` āš ļø Skipping (read-only/enterprise)
3
- `);continue}try{let t=y(a.path),o=!1,s=g(t);if(s.length===0){console.log(` • No MCP servers configured
4
- `);continue}for(let a of s){let s=a.path.join(`.`);console.log(` šŸ“ Processing mcpServers at: ${s}`);let c=!1,l={...a.servers};for(let[t,o]of Object.entries(a.servers)){n++;let a=w(o);if(!a){console.log(` āœ“ ${t}: Already using mcp-gateway`),i++;continue}e.dryRun||(l[t]=a);let s=o.type?`remote ${o.type}`:`stdio`;console.log(` ↻ ${t}: Wrapped ${s} server`),r++,c=!0}c&&!e.dryRun?(t=C(t,a.path,l),o=!0):c&&(o=!0)}if(o&&!e.dryRun){let n=f(a.path);console.log(` šŸ’¾ Created backup: ${n}`),E(a.path,t,{dryRun:e.dryRun})}console.log()}catch(e){console.log(` āŒ Error processing config: ${e}\n`)}}e.dryRun?console.log(`šŸ” Dry run summary:`):console.log(`šŸ“Š Installation summary:`),console.log(` • ${n} total servers found`),console.log(` • ${r} servers ${e.dryRun?`would be`:``} wrapped with mcp-gateway`),console.log(` • ${i} servers already configured`),r>0&&!e.dryRun?console.log(`
5
- āœ… Installation complete! Restart Claude Code to apply changes.`):r>0&&e.dryRun?console.log(`
6
- šŸ’” Run without --dry-run to apply these changes.`):console.log(`
7
- āœ… All servers are already configured.`)}function y(e){try{let t=a(e,`utf-8`);return JSON.parse(t)}catch(t){throw Error(`Failed to read config ${e}: ${t}`)}}async function b(e={}){console.log(`šŸ” Scanning for backup files...
8
- `);let t=m();if(t.length===0){console.log(`āŒ No backup files found.`),console.log(` Backup files should have .mcp-gateway-backup extension`);return}console.log(`šŸ“ Found ${t.length} backup file${t.length===1?``:`s`}:`);for(let n of t){let t=`${n}.mcp-gateway-backup`;if(console.log(` šŸ’¾ ${t} → ${n}`),!e.dryRun)try{x(n),console.log(` āœ… Restored successfully`);try{p(n)}catch(e){console.log(` āš ļø Warning: Could not delete backup for ${n}: ${e}`)}}catch(e){console.log(` āŒ Restore failed: ${e}`)}}e.dryRun||console.log(`
9
- āœ… Restore complete! Restart Claude Code to apply changes.`)}function x(e){let t=`${e}.mcp-gateway-backup`;if(!i(t))throw Error(`No backup found for ${e}`);try{r(t,e)}catch(t){throw Error(`Failed to restore ${e} from backup: ${t}`)}}function S(t){let n=e.proxyCommand;if(t._mcp_gateway_original){let e={...t._mcp_gateway_original};return delete e._mcp_gateway_original,e}if(t.command!==n&&t.command!==`mcp-gateway`)return null;let r=t.args||[];if(r[0]===`stdio`&&r.length>1)return{command:r[1],...r.length>2&&{args:r.slice(2)},...t.env&&{env:t.env}};if(r[0]===`remote`){let e=r.indexOf(`--url`),n=r.indexOf(`--remote-transport`);if(e===-1)return null;let i=r[e+1],a=(n===-1?`sse`:r[n+1])===`stream`?`http`:`sse`,o={},s=r.indexOf(`--headers`);for(;s!==-1&&s<r.length-1;){let e=r[s+1],t=e.indexOf(`:`);if(t!==-1){let n=e.slice(0,t);o[n]=e.slice(t+1)}s=r.indexOf(`--headers`,s+2)}return{type:a,url:i,...Object.keys(o).length>0&&{headers:o},...t.env&&{env:t.env}}}return null}function C(e,t,n){if(t.length===0)return n;let[r,...i]=t;return{...e,[r]:i.length===0?n:C(e[r]||{},i,n)}}function w(t){let n=e.proxyCommand;if(t.command===n||t._mcp_gateway_original)return null;if(t.type&&t.url){let e=t.type===`sse`?`sse`:`stream`,r=[];if(t.headers)for(let[e,n]of Object.entries(t.headers))r.push(`--headers`,`${e}:${n}`);return{args:[n,`remote`,`--url`,t.url,`--remote-transport`,e,...r],command:`npx`,...t.env&&{env:t.env},_mcp_gateway_original:{type:t.type,url:t.url,...t.headers&&{headers:t.headers},...t.env&&{env:t.env}}}}return t.command?{args:[n,`--`,t.command,...t.args||[]],command:`npx`,...t.env&&{env:t.env},_mcp_gateway_original:{command:t.command,...t.args&&{args:t.args},...t.env&&{env:t.env}}}:null}async function T(e={}){console.log(`šŸ” Scanning for Claude Code MCP configurations...
10
- `);let t=await h();if(t.length===0){console.log(`āŒ No MCP configuration files found.`);return}let n=0,r=0,i=0;for(let a of t){if(console.log(`šŸ“ ${a.path}`),!a.isWritable){console.log(` āš ļø Skipping (read-only/enterprise)
11
- `);continue}try{let t=y(a.path),o=!1,s=g(t);if(s.length===0){console.log(` • No MCP servers configured
12
- `);continue}for(let a of s){let s=a.path.join(`.`);console.log(` šŸ“ Processing mcpServers at: ${s}`);let c=!1,l={...a.servers};for(let[t,o]of Object.entries(a.servers)){n++;let a=S(o);if(!a){console.log(` - ${t}: Not using mcp-gateway`),i++;continue}e.dryRun||(l[t]=a),console.log(` ↩ ${t}: Reverted to original configuration`),r++,c=!0}c&&!e.dryRun?(t=C(t,a.path,l),o=!0):c&&(o=!0)}o&&!e.dryRun&&E(a.path,t,{dryRun:e.dryRun}),console.log()}catch(e){console.log(` āŒ Error processing config: ${e}\n`)}}e.dryRun?console.log(`šŸ” Dry run summary:`):console.log(`šŸ“Š Uninstall summary:`),console.log(` • ${n} total servers found`),console.log(` • ${r} servers ${e.dryRun?`would be`:``} reverted`),console.log(` • ${i} servers not using mcp-gateway`),r>0&&!e.dryRun?console.log(`
13
- āœ… Uninstall complete! Restart Claude Code to apply changes.`):r>0&&e.dryRun?console.log(`
14
- šŸ’” Run without --dry-run to apply these changes.`):console.log(`
15
- āœ… No servers needed reverting.`)}function E(e,t,n={}){if(!n.dryRun)try{let n=JSON.stringify(t,null,2);s(e,n,`utf-8`)}catch(t){throw Error(`Failed to write config ${e}: ${t}`)}}function D(e){return e.endsWith(`.claude.json`)?`claude-json`:e.endsWith(`.mcp.json`)||e.endsWith(`mcp-config.json`)?`mcp-json`:`settings`}function O(e){try{t(e,n.W_OK);let r=[`/Library/Application Support/ClaudeCode/managed-settings.json`,`/etc/claude-code/managed-settings.json`,`C:\\ProgramData\\ClaudeCode\\managed-settings.json`],i=l(e);return r.some(e=>i===l(e))?!1:![`/opt/`,`/usr/`,`C:\\Program Files`].some(e=>i.startsWith(l(e)))}catch{return!1}}export{v as installCommand,b as restoreCommand,T as uninstallCommand};
16
- //# sourceMappingURL=install-CC7hksDO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install-CC7hksDO.js","names":["backups: string[]","configs: ConfigFile[]","locations: McpServerLocation[]","config","headers: Record<string, string>","headerArgs: string[]"],"sources":["../src/commands/install.ts"],"sourcesContent":["import { accessSync, constants, copyFileSync, existsSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nimport { config } from \"../config/env.js\";\n\nexport interface ClaudeConfig {\n [key: string]: unknown; // Other config properties\n}\n\nexport interface ConfigFile {\n isWritable: boolean;\n path: string;\n type: \"claude-json\" | \"mcp-json\" | \"settings\";\n}\n\nexport interface InstallOptions {\n dryRun?: boolean;\n}\n\n// Types for MCP server configurations\nexport interface MCPServerConfig {\n // Our metadata for clean reversal\n _mcp_gateway_original?: unknown;\n args?: string[];\n // Stdio format\n command?: string;\n\n env?: Record<string, string>;\n headers?: Record<string, string>;\n // Remote format (SSE/HTTP)\n type?: \"http\" | \"sse\" | \"stdio\";\n\n url?: string;\n}\n\nexport interface McpServerLocation {\n path: string[]; // JSON path to mcpServers (e.g., ['projects', '/path', 'mcpServers'])\n servers: Record<string, MCPServerConfig>;\n}\n\nexport interface RestoreOptions {\n dryRun?: boolean;\n}\n\n// Known Claude MCP configuration file locations\nconst KNOWN_CONFIG_LOCATIONS = [\n // User-level configurations\n join(homedir(), \".claude.json\"),\n join(homedir(), \".claude\", \"settings.json\"),\n join(homedir(), \".claude\", \"settings.local.json\"),\n join(homedir(), \".config\", \"claude\", \"settings.json\"),\n join(homedir(), \".config\", \"claude\", \"settings.local.json\"),\n\n // Project-level configurations (current working directory)\n join(process.cwd(), \".claude.json\"),\n join(process.cwd(), \".claude\", \"settings.json\"),\n join(process.cwd(), \".claude\", \"settings.local.json\"),\n join(process.cwd(), \".mcp.json\"),\n join(process.cwd(), \"mcp-config.json\"),\n join(process.cwd(), \".claude-mcp.json\"),\n];\n\n/**\n * Create a backup copy of a configuration file\n */\nexport function createBackup(configPath: string): string {\n const backupPath = `${configPath}.mcp-gateway-backup`;\n try {\n copyFileSync(configPath, backupPath);\n return backupPath;\n } catch (error) {\n throw new Error(`Failed to create backup of ${configPath}: ${error}`);\n }\n}\n\n/**\n * Delete a backup file\n */\nexport function deleteBackup(configPath: string): void {\n const backupPath = `${configPath}.mcp-gateway-backup`;\n if (existsSync(backupPath)) {\n try {\n unlinkSync(backupPath);\n } catch (error) {\n throw new Error(`Failed to delete backup ${backupPath}: ${error}`);\n }\n }\n}\n\n/**\n * Find all backup files in known configuration locations\n */\nexport function findAllBackups(): string[] {\n const backups: string[] = [];\n\n for (const configPath of KNOWN_CONFIG_LOCATIONS) {\n if (hasBackup(configPath)) {\n backups.push(configPath);\n }\n }\n\n return backups;\n}\n\n/**\n * Safe file discovery using targeted file checking\n */\nexport async function findAllConfigs(): Promise<ConfigFile[]> {\n const configs: ConfigFile[] = [];\n const seen = new Set<string>(); // Avoid duplicates\n\n // Check all known config locations\n for (const configPath of KNOWN_CONFIG_LOCATIONS) {\n try {\n if (existsSync(configPath) && !seen.has(configPath)) {\n seen.add(configPath);\n configs.push({\n isWritable: isConfigWritable(configPath),\n path: configPath,\n type: determineConfigType(configPath),\n });\n }\n } catch {\n // Skip files we can't access\n }\n }\n\n return configs;\n}\n\n/**\n * Recursively find all mcpServers in JSON structure\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function findAllMcpServers(obj: any, currentPath: string[] = []): McpServerLocation[] {\n const locations: McpServerLocation[] = [];\n\n if (!obj || typeof obj !== \"object\") return locations;\n\n for (const [key, value] of Object.entries(obj)) {\n if (key === \"mcpServers\" && typeof value === \"object\" && !Array.isArray(value)) {\n locations.push({\n path: [...currentPath, key],\n servers: value as Record<string, MCPServerConfig>,\n });\n } else if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n // Recurse into nested objects (but not arrays)\n locations.push(...findAllMcpServers(value, [...currentPath, key]));\n }\n }\n\n return locations;\n}\n\n/**\n * Get value at JSON path\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getAtPath(obj: any, path: string[]): any {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return path.reduce((current: any, key) => current?.[key], obj);\n}\n\n/**\n * Check if a backup exists for a configuration file\n */\nexport function hasBackup(configPath: string): boolean {\n const backupPath = `${configPath}.mcp-gateway-backup`;\n return existsSync(backupPath);\n}\n\n/**\n * Install mcp-gateway for all MCP configurations\n */\nexport async function installCommand(options: InstallOptions = {}): Promise<void> {\n await uninstallCommand(options);\n console.log(\"šŸ” Scanning for Claude Code MCP configurations...\\n\");\n\n const configs = await findAllConfigs();\n\n if (configs.length === 0) {\n console.log(\"āŒ No MCP configuration files found.\");\n console.log(\" Expected locations include:\");\n console.log(\" • ~/.claude.json\");\n console.log(\" • ~/.claude/settings.json\");\n console.log(\" • ~/.claude/settings.local.json\");\n console.log(\" • ./.claude/settings.json (project)\");\n console.log(\" • ./.claude/settings.local.json (project)\");\n console.log(\" • ./.mcp.json (project)\");\n return;\n }\n\n let totalServers = 0;\n let modifiedServers = 0;\n let skippedServers = 0;\n\n for (const configFile of configs) {\n console.log(`šŸ“ ${configFile.path}`);\n\n if (!configFile.isWritable) {\n console.log(\" āš ļø Skipping (read-only/enterprise)\\n\");\n continue;\n }\n\n try {\n let config = readConfig(configFile.path);\n let fileModified = false;\n\n // Find all mcpServers at any nesting level\n const mcpServerLocations = findAllMcpServers(config);\n\n if (mcpServerLocations.length === 0) {\n console.log(\" • No MCP servers configured\\n\");\n continue;\n }\n\n // Process each mcpServers location\n for (const location of mcpServerLocations) {\n const pathStr = location.path.join(\".\");\n console.log(` šŸ“ Processing mcpServers at: ${pathStr}`);\n\n let locationModified = false;\n const updatedServers = { ...location.servers };\n\n for (const [name, server] of Object.entries(location.servers)) {\n totalServers++;\n const transformed = transformServer(server);\n\n if (!transformed) {\n console.log(` āœ“ ${name}: Already using mcp-gateway`);\n skippedServers++;\n continue;\n }\n\n if (!options.dryRun) {\n updatedServers[name] = transformed;\n }\n\n const serverType = server.type ? `remote ${server.type}` : \"stdio\";\n console.log(` ↻ ${name}: Wrapped ${serverType} server`);\n modifiedServers++;\n locationModified = true;\n }\n\n // Update the config at the specific path if modified\n if (locationModified && !options.dryRun) {\n config = setAtPath(config, location.path, updatedServers);\n fileModified = true;\n } else if (locationModified) {\n fileModified = true; // Mark as would be modified for dry run\n }\n }\n\n if (fileModified && !options.dryRun) {\n // Create backup before modifying\n const backupPath = createBackup(configFile.path);\n console.log(` šŸ’¾ Created backup: ${backupPath}`);\n\n writeConfig(configFile.path, config, { dryRun: options.dryRun });\n }\n\n console.log();\n } catch (error) {\n console.log(` āŒ Error processing config: ${error}\\n`);\n }\n }\n\n // Summary\n if (options.dryRun) {\n console.log(\"šŸ” Dry run summary:\");\n } else {\n console.log(\"šŸ“Š Installation summary:\");\n }\n console.log(` • ${totalServers} total servers found`);\n console.log(` • ${modifiedServers} servers ${options.dryRun ? \"would be\" : \"\"} wrapped with mcp-gateway`);\n console.log(` • ${skippedServers} servers already configured`);\n\n if (modifiedServers > 0 && !options.dryRun) {\n console.log(\"\\nāœ… Installation complete! Restart Claude Code to apply changes.\");\n } else if (modifiedServers > 0 && options.dryRun) {\n console.log(\"\\nšŸ’” Run without --dry-run to apply these changes.\");\n } else {\n console.log(\"\\nāœ… All servers are already configured.\");\n }\n}\n\n/**\n * Read and parse a configuration file\n */\nexport function readConfig(configPath: string): ClaudeConfig {\n try {\n const content = readFileSync(configPath, \"utf-8\");\n return JSON.parse(content);\n } catch (error) {\n throw new Error(`Failed to read config ${configPath}: ${error}`);\n }\n}\n\n/**\n * Restore all configuration files from their backups\n */\nexport async function restoreCommand(options: RestoreOptions = {}): Promise<void> {\n console.log(\"šŸ” Scanning for backup files...\\n\");\n\n const backupConfigs = findAllBackups();\n\n if (backupConfigs.length === 0) {\n console.log(\"āŒ No backup files found.\");\n console.log(\" Backup files should have .mcp-gateway-backup extension\");\n return;\n }\n\n console.log(`šŸ“ Found ${backupConfigs.length} backup file${backupConfigs.length === 1 ? \"\" : \"s\"}:`);\n\n for (const configPath of backupConfigs) {\n const backupPath = `${configPath}.mcp-gateway-backup`;\n console.log(` šŸ’¾ ${backupPath} → ${configPath}`);\n\n if (!options.dryRun) {\n try {\n restoreFromBackup(configPath);\n console.log(` āœ… Restored successfully`);\n\n try {\n deleteBackup(configPath);\n } catch (error) {\n console.log(` āš ļø Warning: Could not delete backup for ${configPath}: ${error}`);\n }\n } catch (error) {\n console.log(` āŒ Restore failed: ${error}`);\n }\n }\n }\n\n if (!options.dryRun) {\n console.log(\"\\nāœ… Restore complete! Restart Claude Code to apply changes.\");\n }\n}\n\n/**\n * Restore a configuration file from its backup\n */\nexport function restoreFromBackup(configPath: string): void {\n const backupPath = `${configPath}.mcp-gateway-backup`;\n if (!existsSync(backupPath)) {\n throw new Error(`No backup found for ${configPath}`);\n }\n try {\n copyFileSync(backupPath, configPath);\n } catch (error) {\n throw new Error(`Failed to restore ${configPath} from backup: ${error}`);\n }\n}\n\n/**\n * Revert a server configuration from mcp-gateway back to original\n */\nexport function revertServer(server: MCPServerConfig): MCPServerConfig | null {\n const proxyCommand = config.proxyCommand;\n\n // Use stored original if available (safest)\n if (server._mcp_gateway_original) {\n const original = { ...server._mcp_gateway_original } as MCPServerConfig;\n // Remove our internal metadata\n delete original._mcp_gateway_original;\n return original;\n }\n\n // Only revert if it's our proxy wrapper (check both current and legacy commands)\n if (server.command !== proxyCommand && server.command !== \"mcp-gateway\") {\n return null;\n }\n\n // Fallback: Parse from args (for configs without metadata)\n const args = server.args || [];\n\n if (args[0] === \"stdio\" && args.length > 1) {\n // Stdio format reversal\n return {\n command: args[1],\n ...(args.length > 2 && { args: args.slice(2) }),\n ...(server.env && { env: server.env }),\n };\n }\n\n if (args[0] === \"remote\") {\n // Remote format reversal\n const urlIndex = args.indexOf(\"--url\");\n const transportIndex = args.indexOf(\"--remote-transport\");\n\n if (urlIndex === -1) return null;\n\n const url = args[urlIndex + 1];\n const transport = transportIndex !== -1 ? args[transportIndex + 1] : \"sse\";\n const type = transport === \"stream\" ? \"http\" : \"sse\";\n\n // Parse headers\n const headers: Record<string, string> = {};\n let i = args.indexOf(\"--headers\");\n while (i !== -1 && i < args.length - 1) {\n const header = args[i + 1];\n const colonIndex = header.indexOf(\":\");\n if (colonIndex !== -1) {\n const key = header.slice(0, colonIndex);\n const value = header.slice(colonIndex + 1);\n headers[key] = value;\n }\n i = args.indexOf(\"--headers\", i + 2);\n }\n\n return {\n type,\n url,\n ...(Object.keys(headers).length > 0 && { headers }),\n ...(server.env && { env: server.env }),\n };\n }\n\n return null;\n}\n\n/**\n * Set value at JSON path (immutable)\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function setAtPath(obj: any, path: string[], value: any): any {\n if (path.length === 0) return value;\n\n const [head, ...tail] = path;\n return {\n ...obj,\n [head]: tail.length === 0 ? value : setAtPath(obj[head] || {}, tail, value),\n };\n}\n\n/**\n * Transform a server configuration to use mcp-gateway\n */\nexport function transformServer(server: MCPServerConfig): MCPServerConfig | null {\n const proxyCommand = config.proxyCommand;\n\n // Skip if already proxied\n if (server.command === proxyCommand || server._mcp_gateway_original) {\n return null;\n }\n\n // Handle remote servers (type + url format)\n if (server.type && server.url) {\n const transport = server.type === \"sse\" ? \"sse\" : \"stream\";\n const headerArgs: string[] = [];\n\n // Convert headers to command line arguments\n if (server.headers) {\n for (const [key, value] of Object.entries(server.headers)) {\n headerArgs.push(\"--headers\", `${key}:${value}`);\n }\n }\n\n return {\n args: [proxyCommand, \"remote\", \"--url\", server.url, \"--remote-transport\", transport, ...headerArgs],\n command: \"npx\",\n ...(server.env && { env: server.env }),\n _mcp_gateway_original: {\n type: server.type,\n url: server.url,\n ...(server.headers && { headers: server.headers }),\n ...(server.env && { env: server.env }),\n },\n };\n }\n\n // Handle stdio servers (command + args format)\n if (server.command) {\n return {\n args: [proxyCommand, \"--\", server.command, ...(server.args || [])],\n command: \"npx\",\n ...(server.env && { env: server.env }),\n _mcp_gateway_original: {\n command: server.command,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n },\n };\n }\n\n return null;\n}\n\n/**\n * Uninstall mcp-gateway from all MCP configurations\n */\nexport async function uninstallCommand(options: InstallOptions = {}): Promise<void> {\n console.log(\"šŸ” Scanning for Claude Code MCP configurations...\\n\");\n\n const configs = await findAllConfigs();\n\n if (configs.length === 0) {\n console.log(\"āŒ No MCP configuration files found.\");\n return;\n }\n\n let totalServers = 0;\n let revertedServers = 0;\n let skippedServers = 0;\n\n for (const configFile of configs) {\n console.log(`šŸ“ ${configFile.path}`);\n\n if (!configFile.isWritable) {\n console.log(\" āš ļø Skipping (read-only/enterprise)\\n\");\n continue;\n }\n\n try {\n let config = readConfig(configFile.path);\n let fileModified = false;\n\n // Find all mcpServers at any nesting level\n const mcpServerLocations = findAllMcpServers(config);\n\n if (mcpServerLocations.length === 0) {\n console.log(\" • No MCP servers configured\\n\");\n continue;\n }\n\n // Process each mcpServers location\n for (const location of mcpServerLocations) {\n const pathStr = location.path.join(\".\");\n console.log(` šŸ“ Processing mcpServers at: ${pathStr}`);\n\n let locationModified = false;\n const updatedServers = { ...location.servers };\n\n for (const [name, server] of Object.entries(location.servers)) {\n totalServers++;\n const reverted = revertServer(server);\n\n if (!reverted) {\n console.log(` - ${name}: Not using mcp-gateway`);\n skippedServers++;\n continue;\n }\n\n if (!options.dryRun) {\n updatedServers[name] = reverted;\n }\n\n console.log(` ↩ ${name}: Reverted to original configuration`);\n revertedServers++;\n locationModified = true;\n }\n\n // Update the config at the specific path if modified\n if (locationModified && !options.dryRun) {\n config = setAtPath(config, location.path, updatedServers);\n fileModified = true;\n } else if (locationModified) {\n fileModified = true; // Mark as would be modified for dry run\n }\n }\n\n if (fileModified && !options.dryRun) {\n writeConfig(configFile.path, config, { dryRun: options.dryRun });\n }\n\n console.log();\n } catch (error) {\n console.log(` āŒ Error processing config: ${error}\\n`);\n }\n }\n\n // Summary\n if (options.dryRun) {\n console.log(\"šŸ” Dry run summary:\");\n } else {\n console.log(\"šŸ“Š Uninstall summary:\");\n }\n console.log(` • ${totalServers} total servers found`);\n console.log(` • ${revertedServers} servers ${options.dryRun ? \"would be\" : \"\"} reverted`);\n console.log(` • ${skippedServers} servers not using mcp-gateway`);\n\n if (revertedServers > 0 && !options.dryRun) {\n console.log(\"\\nāœ… Uninstall complete! Restart Claude Code to apply changes.\");\n } else if (revertedServers > 0 && options.dryRun) {\n console.log(\"\\nšŸ’” Run without --dry-run to apply these changes.\");\n } else {\n console.log(\"\\nāœ… No servers needed reverting.\");\n }\n}\n\n/**\n * Write a configuration file\n */\nexport function writeConfig(configPath: string, config: ClaudeConfig, options: { dryRun?: boolean } = {}): void {\n if (options.dryRun) {\n return; // Don't actually write in dry run mode\n }\n\n try {\n const content = JSON.stringify(config, null, 2);\n writeFileSync(configPath, content, \"utf-8\");\n } catch (error) {\n throw new Error(`Failed to write config ${configPath}: ${error}`);\n }\n}\n\n/**\n * Determine config file type from path\n */\nfunction determineConfigType(filePath: string): \"claude-json\" | \"mcp-json\" | \"settings\" {\n if (filePath.endsWith(\".claude.json\")) return \"claude-json\";\n if (filePath.endsWith(\".mcp.json\") || filePath.endsWith(\"mcp-config.json\")) return \"mcp-json\";\n return \"settings\";\n}\n\n/**\n * Check if a file is writable and not in a managed/enterprise location\n */\nfunction isConfigWritable(configPath: string): boolean {\n try {\n accessSync(configPath, constants.W_OK);\n\n // Check for enterprise/managed paths (read-only)\n const enterprisePaths = [\n \"/Library/Application Support/ClaudeCode/managed-settings.json\",\n \"/etc/claude-code/managed-settings.json\",\n \"C:\\\\ProgramData\\\\ClaudeCode\\\\managed-settings.json\",\n ];\n\n const normalizedPath = resolve(configPath);\n if (enterprisePaths.some((p) => normalizedPath === resolve(p))) {\n return false;\n }\n\n // Check if in system directories\n const systemPaths = [\"/opt/\", \"/usr/\", \"C:\\\\Program Files\"];\n return !systemPaths.some((p) => normalizedPath.startsWith(resolve(p)));\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}