11/**
22 * @file Pure adapters from the fleet-canonical Claude `.mcp.json` shape to
3- * project-local Codex/OpenCode configs and Kimi's per-user MCP file.
3+ * project-local Codex/OpenCode/Kimi configs and Kimi's per-user MCP file.
44 * Credentials never belong in the canonical or generated project files; each
55 * client owns OAuth state in its user data directory.
66 */
@@ -62,6 +62,34 @@ function assertNoCredentials(value: unknown, location = '.mcp.json'): void {
6262 }
6363}
6464
65+ function compactKimiArgsArrays (
66+ text : string ,
67+ servers : PortableMcpServers ,
68+ ) : string {
69+ let result = text
70+ const items = Object . values ( servers )
71+ for ( let i = 0 , { length } = items ; i < length ; i += 1 ) {
72+ const server = items [ i ] !
73+ if ( server . kind !== 'stdio' || server . args . length === 0 ) {
74+ continue
75+ }
76+ const compact = ` "args": [${ server . args . map ( value => JSON . stringify ( value ) ) . join ( ', ' ) } ]`
77+ if ( compact . length > 80 ) {
78+ continue
79+ }
80+ const expanded = [
81+ ' "args": [' ,
82+ ...server . args . map (
83+ ( value , index ) =>
84+ ` ${ JSON . stringify ( value ) } ${ index + 1 < server . args . length ? ',' : '' } ` ,
85+ ) ,
86+ ' ]' ,
87+ ] . join ( '\n' )
88+ result = result . replace ( expanded , compact )
89+ }
90+ return result
91+ }
92+
6593function compactOpenCodeCommandArrays (
6694 text : string ,
6795 servers : PortableMcpServers ,
@@ -102,7 +130,9 @@ function main(): void {
102130 )
103131 }
104132 writeMcpClientConfigs ( REPO_ROOT )
105- process . stdout . write ( 'Generated .codex/config.toml and opencode.json.\n' )
133+ process . stdout . write (
134+ 'Generated .codex/config.toml, opencode.json, and .kimi-code/mcp.json.\n' ,
135+ )
106136}
107137
108138function parseStringArray ( value : unknown , field : string ) : string [ ] {
@@ -268,7 +298,28 @@ export function renderOpenCodeMcpConfig(servers: PortableMcpServers): string {
268298}
269299
270300/**
271- * Regenerate the two committed project adapters from `.mcp.json`.
301+ * Render Kimi's project-local `~/.kimi-code/mcp.json` adapter. Kimi resolves
302+ * stdio commands relative to the project root when the file lives at
303+ * `<project>/.kimi-code/mcp.json`, so no `cwd` is needed.
304+ */
305+ export function renderKimiProjectMcpConfig ( servers : PortableMcpServers ) : string {
306+ const mcpServers : Record < string , unknown > = { }
307+ for ( const [ name , server ] of Object . entries ( sortRecord ( servers ) ) ) {
308+ mcpServers [ name ] =
309+ server . kind === 'http'
310+ ? { auth : 'oauth' , type : 'http' , url : server . url }
311+ : { args : server . args , command : server . command }
312+ }
313+ const rendered = JSON . stringify (
314+ { mcpServers : sortRecord ( mcpServers ) } ,
315+ undefined ,
316+ 2 ,
317+ )
318+ return `${ compactKimiArgsArrays ( rendered , servers ) } \n`
319+ }
320+
321+ /**
322+ * Regenerate the three committed project adapters from `.mcp.json`.
272323 */
273324export function writeMcpClientConfigs ( repoRoot : string ) : void {
274325 const templateRoot = path . join ( repoRoot , 'template' , 'base' )
@@ -279,6 +330,7 @@ export function writeMcpClientConfigs(repoRoot: string): void {
279330 readFileSync ( path . join ( configRoot , '.mcp.json' ) , 'utf8' ) ,
280331 )
281332 mkdirSync ( path . join ( configRoot , '.codex' ) , { recursive : true } )
333+ mkdirSync ( path . join ( configRoot , '.kimi-code' ) , { recursive : true } )
282334 writeFileSync (
283335 path . join ( configRoot , '.codex' , 'config.toml' ) ,
284336 renderCodexMcpConfig ( servers ) ,
@@ -287,6 +339,10 @@ export function writeMcpClientConfigs(repoRoot: string): void {
287339 path . join ( configRoot , 'opencode.json' ) ,
288340 renderOpenCodeMcpConfig ( servers ) ,
289341 )
342+ writeFileSync (
343+ path . join ( configRoot , '.kimi-code' , 'mcp.json' ) ,
344+ renderKimiProjectMcpConfig ( servers ) ,
345+ )
290346}
291347
292348if ( isMainModule ( import . meta. url ) ) {
0 commit comments