Files
mosaic/packages/mosaic/src/runtime/mcp-config.ts
2026-03-07 00:40:29 +00:00

113 lines
2.7 KiB
TypeScript

import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { homedir } from 'node:os';
import type { RuntimeName } from '../types.js';
const MCP_ENTRY = {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-sequential-thinking'],
};
export function configureMcpForRuntime(runtime: RuntimeName): void {
switch (runtime) {
case 'claude':
return configureClaudeMcp();
case 'codex':
return configureCodexMcp();
case 'opencode':
return configureOpenCodeMcp();
}
}
function ensureDir(filePath: string): void {
mkdirSync(dirname(filePath), { recursive: true });
}
function configureClaudeMcp(): void {
const settingsPath = join(homedir(), '.claude', 'settings.json');
ensureDir(settingsPath);
let data: Record<string, unknown> = {};
if (existsSync(settingsPath)) {
try {
data = JSON.parse(readFileSync(settingsPath, 'utf-8'));
} catch {
// Start fresh if corrupt
}
}
if (
!data.mcpServers ||
typeof data.mcpServers !== 'object' ||
Array.isArray(data.mcpServers)
) {
data.mcpServers = {};
}
(data.mcpServers as Record<string, unknown>)['sequential-thinking'] =
MCP_ENTRY;
writeFileSync(
settingsPath,
JSON.stringify(data, null, 2) + '\n',
'utf-8',
);
}
function configureCodexMcp(): void {
const configPath = join(homedir(), '.codex', 'config.toml');
ensureDir(configPath);
let content = '';
if (existsSync(configPath)) {
content = readFileSync(configPath, 'utf-8');
// Remove existing sequential-thinking section
content = content
.replace(
/\[mcp_servers\.(sequential-thinking|sequential_thinking)\][\s\S]*?(?=\n\[|$)/g,
'',
)
.trim();
}
content +=
'\n\n[mcp_servers.sequential-thinking]\n' +
'command = "npx"\n' +
'args = ["-y", "@modelcontextprotocol/server-sequential-thinking"]\n';
writeFileSync(configPath, content, 'utf-8');
}
function configureOpenCodeMcp(): void {
const configPath = join(
homedir(),
'.config',
'opencode',
'config.json',
);
ensureDir(configPath);
let data: Record<string, unknown> = {};
if (existsSync(configPath)) {
try {
data = JSON.parse(readFileSync(configPath, 'utf-8'));
} catch {
// Start fresh
}
}
if (!data.mcp || typeof data.mcp !== 'object' || Array.isArray(data.mcp)) {
data.mcp = {};
}
(data.mcp as Record<string, unknown>)['sequential-thinking'] = {
type: 'local',
command: ['npx', '-y', '@modelcontextprotocol/server-sequential-thinking'],
enabled: true,
};
writeFileSync(
configPath,
JSON.stringify(data, null, 2) + '\n',
'utf-8',
);
}