@@ -928,6 +928,50 @@ describe("session MCP runtime", () => {
928928 }
929929 } ) ;
930930
931+ it ( "does not split a surrogate pair at the MCP metadata text limit" , async ( ) => {
932+ const tempDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "bundle-mcp-utf16-metadata-" ) ) ;
933+ const serverPath = path . join ( tempDir , "utf16-metadata.mjs" ) ;
934+ const logPath = path . join ( tempDir , "server.log" ) ;
935+ const safePrefix = "x" . repeat ( 1_199 ) ;
936+ await writeListToolsMcpServer ( {
937+ filePath : serverPath ,
938+ logPath,
939+ tools : [
940+ {
941+ name : "utf16_tool" ,
942+ description : `${ safePrefix } 🚀tail` ,
943+ inputSchema : { type : "object" , properties : { } } ,
944+ } ,
945+ ] ,
946+ } ) ;
947+
948+ const runtime = await getOrCreateSessionMcpRuntime ( {
949+ sessionId : "session-utf16-metadata" ,
950+ sessionKey : "agent:test:session-utf16-metadata" ,
951+ workspaceDir : "/workspace" ,
952+ cfg : {
953+ mcp : {
954+ servers : {
955+ metadata : {
956+ command : process . execPath ,
957+ args : [ serverPath ] ,
958+ } ,
959+ } ,
960+ } ,
961+ } ,
962+ } ) ;
963+
964+ try {
965+ const catalog = await runtime . getCatalog ( ) ;
966+
967+ expect ( catalog . tools ) . toHaveLength ( 1 ) ;
968+ expect ( catalog . tools [ 0 ] ?. description ) . toBe ( `${ safePrefix } ...` ) ;
969+ } finally {
970+ await runtime . dispose ( ) ;
971+ await fs . rm ( tempDir , { recursive : true , force : true } ) ;
972+ }
973+ } ) ;
974+
931975 it ( "rejects adversarial MCP tool filters without regex backtracking" , async ( ) => {
932976 const tempDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "bundle-mcp-linear-filter-" ) ) ;
933977 const serverPath = path . join ( tempDir , "linear-filter.mjs" ) ;
0 commit comments