1+ #!/usr/bin/env -S deno run --allow-net --allow-env --allow-read
12// SPDX-License-Identifier: MPL-2.0
23// Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3- #!/usr/bin/env -S deno run --allow-net --allow-env --allow-read
44//
55// BoJ Server — MCP transport bridge (stdio + HTTP per ADR-0013)
66//
1717
1818import { env , stdout } from "./lib/runtime.js" ;
1919import { sanitizeErrorMessage } from "./lib/security.js" ;
20- import { dispatchMcpMessage } from "./lib/dispatcher.js" ;
2120import { info , error as logError } from "./lib/logger.js" ;
2221import * as otel from "./lib/otel.js" ;
23- import { startHttpTransport } from "./lib/http-transport.js" ;
2422
2523const TRANSPORT = ( env . get ( "BOJ_TRANSPORT" ) ?? "stdio" ) . toLowerCase ( ) ;
2624
@@ -43,6 +41,15 @@ function sendError(id, code, message) {
4341 send ( { jsonrpc : "2.0" , id, error : { code, message : sanitizeErrorMessage ( message ) } } ) ;
4442}
4543
44+ let dispatchMcpMessagePromise ;
45+
46+ async function getDispatchMcpMessage ( ) {
47+ if ( ! dispatchMcpMessagePromise ) {
48+ dispatchMcpMessagePromise = import ( "./lib/dispatcher.js" ) . then ( ( m ) => m . dispatchMcpMessage ) ;
49+ }
50+ return dispatchMcpMessagePromise ;
51+ }
52+
4653async function handleStdioLine ( line ) {
4754 let msg ;
4855 try {
@@ -51,6 +58,7 @@ async function handleStdioLine(line) {
5158 sendError ( null , - 32700 , "Parse error" ) ;
5259 return ;
5360 }
61+ const dispatchMcpMessage = await getDispatchMcpMessage ( ) ;
5462 const response = await dispatchMcpMessage ( msg , { transport : "stdio" } ) ;
5563 if ( response !== null ) send ( response ) ;
5664}
@@ -77,8 +85,16 @@ async function runStdio() {
7785 if ( typeof Deno !== "undefined" ) {
7886 for await ( const chunk of Deno . stdin . readable ) processChunk ( chunk ) ;
7987 } else {
80- // @ts -ignore: process is global in Node
81- for await ( const chunk of process . stdin ) processChunk ( chunk ) ;
88+ await new Promise ( ( resolve , reject ) => {
89+ // @ts -ignore: process is global in Node/Bun
90+ process . stdin . on ( "data" , processChunk ) ;
91+ // @ts -ignore: process is global in Node/Bun
92+ process . stdin . once ( "end" , resolve ) ;
93+ // @ts -ignore: process is global in Node/Bun
94+ process . stdin . once ( "error" , reject ) ;
95+ // @ts -ignore: process is global in Node/Bun
96+ process . stdin . resume ( ) ;
97+ } ) ;
8298 }
8399 await Promise . allSettled ( pendingMessages ) ;
84100}
@@ -88,6 +104,7 @@ async function runStdio() {
88104// ===================================================================
89105
90106async function runHttp ( ) {
107+ const { startHttpTransport } = await import ( "./lib/http-transport.js" ) ;
91108 const handle = await startHttpTransport ( ) ;
92109 await new Promise ( ( resolve ) => {
93110 const stop = async ( ) => {
0 commit comments