| 1 | /** Raw DSH MCP rows submit definitions to the existing Rust MCP owner. */ |
| 2 | import type { Context } from '@deepseek-ai/cordis' |
| 3 | import { normalizeMcp, type McpDefinition } from '../shims/mcp.ts' |
| 4 | export interface ReviewedMcpContext extends Context { mcp:{registerServer(definition:McpDefinition):()=>void} } |
| 5 | export function reviewedMcpModule() { |
| 6 | return { name:'codewhale-reviewed-mcp',inject:['mcp'], |
| 7 | apply(ctx:ReviewedMcpContext,config:Record<string,unknown>) { |
| 8 | if(!config||Array.isArray(config)||Object.keys(config).some(k=>!['transport','serverName','command','args','env','cwd','url','headers','toolCallTimeoutMs','failOnStartupError'].includes(k)))throw new Error('MCP row uses unsupported configuration; Core owns reconnect and instruction bounds') |
| 9 | if(typeof config.serverName!=='string')throw new Error('MCP serverName must be literal') |
| 10 | const options:Record<string,unknown>={} |
| 11 | if(config.toolCallTimeoutMs!==undefined) { const timeout=config.toolCallTimeoutMs;if(typeof timeout!=='number'||!Number.isInteger(timeout)||timeout<1000||timeout>86_400_000||timeout%1000!==0)throw new Error('MCP timeout must be whole seconds within Core bounds');options.execute_timeout=timeout/1000 } |
| 12 | // Core connects lazily and reports connection failures through /mcp. |
| 13 | // Loader activation cannot stand in for an MCP handshake receipt. |
| 14 | if(config.failOnStartupError===true)throw new Error('failOnStartupError requires explicit Core MCP connection qualification before activation') |
| 15 | if(config.failOnStartupError!==undefined&&config.failOnStartupError!==false)throw new Error('MCP startup gate must be a boolean') |
| 16 | let server:Record<string,unknown> |
| 17 | if(config.transport==='stdio') { |
| 18 | const cwd=config.cwd??'' |
| 19 | if(typeof cwd!=='string'||(cwd!==''&&cwd!=='.'&&(!cwd||/[\\:\u0000-\u001f]/u.test(cwd)||cwd.split('/').some(p=>!p||p==='.'||p==='..'))))throw new Error('MCP cwd must be a reviewed bundle-relative directory') |
| 20 | server={type:'stdio',command:config.command,args:config.args??[],env:config.env??{},cwd:cwd===''||cwd==='.'?'source':`source/${cwd}`} |
| 21 | }else if(config.transport==='streamable-http'||config.transport==='sse')server={type:config.transport,url:config.url,headers:config.headers??{}} |
| 22 | else throw new Error('MCP transport must be stdio, streamable-http or sse') |
| 23 | if(Object.keys(options).length)server.extensions={'net.codewhale':options} |
| 24 | ctx.mcp.registerServer(normalizeMcp({serverName:config.serverName,server})) |
| 25 | }, |
| 26 | } |
| 27 | } |
| 28 |