55
66import argparse
77import asyncio
8- import os
8+ import tempfile
99from contextlib import AsyncExitStack
1010from pathlib import Path
1111
3333
3434async def check_language (language : str ) -> None :
3535 workspace , source_file = CASES [language ]
36+ source_path = str ((workspace / source_file ).resolve ())
3637 connection = MCPLanguageConfigService ().get_language_server_config (
3738 language ,
3839 str (workspace ),
@@ -44,38 +45,53 @@ async def check_language(language: str) -> None:
4445 env = connection .get ("env" ),
4546 )
4647
47- async with AsyncExitStack () as stack :
48- errlog = stack .enter_context (open (os .devnull , "w" , encoding = "utf-8" ))
49- read_stream , write_stream = await stack .enter_async_context (
50- stdio_client (parameters , errlog = errlog )
51- )
52- session = await stack .enter_async_context (
53- ClientSession (read_stream , write_stream )
54- )
55- await session .initialize ()
56- tools = {tool .name for tool in (await session .list_tools ()).tools }
57- required = {"definition" , "references" , "diagnostics" , "hover" }
58- missing = required - tools
59- if missing :
60- raise RuntimeError (
61- f"{ language } : bridge is missing tools: { ', ' .join (sorted (missing ))} "
62- )
63- result = await session .call_tool (
64- "diagnostics" ,
65- {"filePath" : source_file },
66- )
67- if result .isError :
68- detail = " " .join (
69- getattr (item , "text" , str (item )) for item in result .content
70- )
71- raise RuntimeError (f"{ language } : diagnostics failed: { detail } " )
48+ stage = "starting MCP bridge"
49+ print (f"[check] { language } : { stage } " , flush = True )
50+ with tempfile .TemporaryFile (mode = "w+" , encoding = "utf-8" ) as errlog :
51+ try :
52+ async with AsyncExitStack () as stack :
53+ read_stream , write_stream = await stack .enter_async_context (
54+ stdio_client (parameters , errlog = errlog )
55+ )
56+ session = await stack .enter_async_context (
57+ ClientSession (read_stream , write_stream )
58+ )
59+ stage = "initializing MCP session"
60+ async with asyncio .timeout (30 ):
61+ await session .initialize ()
62+ stage = "listing MCP tools"
63+ async with asyncio .timeout (15 ):
64+ tools = {tool .name for tool in (await session .list_tools ()).tools }
65+ required = {"definition" , "references" , "diagnostics" , "hover" }
66+ missing = required - tools
67+ if missing :
68+ raise RuntimeError (
69+ f"{ language } : bridge is missing tools: "
70+ f"{ ', ' .join (sorted (missing ))} "
71+ )
72+ stage = f"requesting diagnostics for { source_path } "
73+ async with asyncio .timeout (30 ):
74+ result = await session .call_tool (
75+ "diagnostics" ,
76+ {"filePath" : source_path },
77+ )
78+ if result .isError :
79+ detail = " " .join (
80+ getattr (item , "text" , str (item )) for item in result .content
81+ )
82+ raise RuntimeError (f"{ language } : diagnostics failed: { detail } " )
83+ except Exception as exc :
84+ errlog .seek (0 )
85+ server_log = errlog .read ().strip ()
86+ detail = f"\n Bridge stderr:\n { server_log } " if server_log else ""
87+ raise RuntimeError (f"{ language } : failed while { stage } : { exc } { detail } " ) from exc
7288
7389 print (f"[ok] { language } : MCP handshake and diagnostics call succeeded" )
7490
7591
7692async def async_main (languages : list [str ]) -> None :
7793 for language in languages :
78- await asyncio . wait_for ( check_language (language ), timeout = 90 )
94+ await check_language (language )
7995
8096
8197def main () -> None :
0 commit comments