| 115 | } |
| 116 | |
| 117 | async function readMcpConfigFile(userDataHome: string): Promise<{ enabled: boolean; port?: number }> { |
| 118 | const filePath = resolve(userDataHome, 'data', 'config', 'mcp.json') |
| 119 | let raw: string |
| 120 | try { |
| 121 | raw = await readFile(filePath, 'utf8') |
| 122 | } catch { |
| 123 | return { enabled: false } |
| 124 | } |
| 125 | let parsed: unknown |
| 126 | try { |
| 127 | parsed = JSON.parse(raw) |
| 128 | } catch (err) { |
| 129 | throw new Error(`[guardian] ${filePath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`) |
| 130 | } |
| 131 | if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) { |
| 132 | throw new Error(`[guardian] ${filePath} must be a JSON object like {"enabled":false,"port":47332}`) |
| 133 | } |
| 134 | const rec = parsed as Record<string, unknown> |
| 135 | return { |
| 136 | enabled: rec['enabled'] === true, |
| 137 | ...(rec['port'] !== undefined ? { port: parsePort(rec['port'], `${filePath} ("port")`) } : {}), |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | function parseEnabledEnv(raw: string | undefined): boolean | null { |
| 142 | if (raw === undefined || raw === '') return null |