Coverage for mcp_chatkit_widget / server.py: 100%

9 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 06:37 +0000

1"""Tools for UI components.""" 

2 

3from pathlib import Path 

4from fastmcp import FastMCP 

5from mcp_chatkit_widget.tooling import ( 

6 _create_widget_tool_function, 

7 _sanitize_tool_name, 

8 _to_camel_case, 

9 generate_widget_tools, 

10) 

11from mcp_chatkit_widget.widget_loader import load_widgets 

12 

13 

14server = FastMCP("mcp-chatkit-widget") 

15 

16 

17def register_widget_tools(widgets_dir: Path) -> None: 

18 """Discover widget definitions and register FastMCP tools.""" 

19 widget_defs = load_widgets(widgets_dir) 

20 generate_widget_tools(server, widget_defs) 

21 

22 

23__all__ = [ 

24 "generate_widget_tools", 

25 "_create_widget_tool_function", 

26 "_sanitize_tool_name", 

27 "_to_camel_case", 

28 "register_widget_tools", 

29 "server", 

30] 

31 

32 

33if __name__ == "__main__": # pragma: no cover 

34 import asyncio 

35 

36 def _examples_widgets_path() -> Path: 

37 """Return the curated examples/widgets directory for manual testing.""" 

38 return Path(__file__).resolve().parents[1] / "examples" / "widgets" 

39 

40 async def list_tools() -> None: 

41 """List all registered tools.""" 

42 print("Registered tools:") 

43 tools = await server.get_tools() 

44 for tool_name in sorted(tools): 

45 print(f" - {tool_name}") 

46 tool = await server.get_tool(tool_name) 

47 if tool and tool.description: 

48 print(f" {tool.description.strip().split(chr(10))[0]}") 

49 

50 widgets_dir = _examples_widgets_path() 

51 register_widget_tools(widgets_dir) 

52 asyncio.run(list_tools())