Route tool calls to the appropriate handler.
(name: str, arguments: dict[str, Any])
| 358 | "required": ["repo_path"], |
| 359 | }, |
| 360 | ), |
| 361 | ] |
| 362 | |
| 363 | |
| 364 | # =================================================================== |
| 365 | # Tool dispatch |
| 366 | # =================================================================== |
| 367 | |
| 368 | @server.list_tools() |
| 369 | async def list_tools() -> list[Tool]: |
| 370 | """List all available CodeWiki MCP tools.""" |
| 371 | return _fine_grained_tools() + _legacy_tools() |
| 372 | |
| 373 | |
| 374 | @server.call_tool() |
| 375 | async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]: |
| 376 | """Route tool calls to the appropriate handler.""" |
| 377 | try: |
| 378 | # --- Fine-grained tools (no LLM config needed) --- |
| 379 | # Synchronous handlers run via asyncio.to_thread() so they never |
| 380 | # block the event loop (which would hang the MCP stdio server). |
| 381 | if name == "analyze_repo": |
| 382 | from codewiki.mcp.tools.analysis import handle_analyze_repo |
| 383 | # NOTE: Tree-sitter C extensions are not thread-safe, so this |
| 384 | # must run on the main thread (blocking the event loop is |
| 385 | # acceptable for this one-time heavy operation). |
| 386 | return [_text(handle_analyze_repo(arguments, _store))] |
| 387 | |
| 388 | elif name == "read_code_components": |
| 389 | from codewiki.mcp.tools.code_reader import handle_read_code_components |
| 390 | return [_text(await asyncio.to_thread(handle_read_code_components, arguments, _store))] |
| 391 | |
| 392 | elif name == "write_doc_file": |
| 393 | from codewiki.mcp.tools.doc_writer import handle_write_doc_file |
| 394 | result = await handle_write_doc_file(arguments, _store) |
| 395 | return [_text(result)] |
| 396 | |
| 397 | elif name == "edit_doc_file": |
| 398 | from codewiki.mcp.tools.doc_writer import handle_edit_doc_file |
| 399 | result = await handle_edit_doc_file(arguments, _store) |
| 400 | return [_text(result)] |
| 401 | |
| 402 | elif name == "save_module_tree": |
| 403 | from codewiki.mcp.tools.module_tree import handle_save_module_tree |
| 404 | return [_text(await asyncio.to_thread(handle_save_module_tree, arguments, _store))] |
| 405 | |
| 406 | elif name == "get_processing_order": |
| 407 | from codewiki.mcp.tools.module_tree import handle_get_processing_order |
| 408 | return [_text(await asyncio.to_thread(handle_get_processing_order, arguments, _store))] |
| 409 | |
| 410 | elif name == "get_prompt": |
| 411 | from codewiki.mcp.tools.prompt_server import handle_get_prompt |
| 412 | return [_text(await asyncio.to_thread(handle_get_prompt, arguments, _store))] |
| 413 | |
| 414 | elif name == "close_session": |
| 415 | sid = arguments["session_id"] |
| 416 | session = _store.get(sid) |
| 417 | if session: |
nothing calls this directly
no test coverage detected