Skip to content

Commit 8c2195b

Browse files
authored
Merge pull request lightspeed-core#796 from tisnik/lcore-946-updated-utils-doc
LCORE-946: updated utils doc
2 parents 41e89f6 + 6ba4935 commit 8c2195b

1 file changed

Lines changed: 50 additions & 3 deletions

File tree

src/utils/common.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,25 @@
1515
async def register_mcp_servers_async(
1616
logger: Logger, configuration: Configuration
1717
) -> None:
18-
"""Register Model Context Protocol (MCP) servers with the LlamaStack client (async)."""
18+
"""Register Model Context Protocol (MCP) servers with the LlamaStack client (async).
19+
20+
If no MCP servers are present in the provided configuration this function returns immediately.
21+
Selects between a library client (initializes it) and a service client based on
22+
configuration.llama_stack.use_as_library_client, then registers any MCP servers not already
23+
present in the client's toolgroups.
24+
25+
Parameters:
26+
logger: Logger instance.
27+
configuration: Configuration containing the `mcp_servers` list and
28+
`llama_stack` client mode.
29+
30+
Notes:
31+
- The `logger` parameter is used for debug/info logging and is
32+
intentionally undocumented as a common service.
33+
- Exceptions from the LlamaStack client (network/errors during
34+
initialization or registration) are not caught here and will
35+
propagate to the caller.
36+
"""
1937
# Skip MCP registration if no MCP servers are configured
2038
if not configuration.mcp_servers:
2139
logger.debug("No MCP servers configured, skipping registration")
@@ -39,7 +57,19 @@ async def _register_mcp_toolgroups_async(
3957
mcp_servers: List[ModelContextProtocolServer],
4058
logger: Logger,
4159
) -> None:
42-
"""Async logic for registering MCP toolgroups."""
60+
"""
61+
Register MCP (Model Context Protocol) toolgroups with a LlamaStack async client.
62+
63+
Checks the client's existing toolgroups and registers any servers from `mcp_servers`
64+
whose `name` is not present in the client's `provider_resource_id` list. For each
65+
new server it calls the client's toolgroups.register with parameters:
66+
`toolgroup_id`=`mcp.name`, `provider_id`=`mcp.provider_id`, and
67+
`mcp_endpoint` containing the server `url`.
68+
69+
This function performs network calls against the provided async client and does not
70+
catch exceptions raised by those calls — any exceptions from the client (e.g., RPC
71+
or HTTP errors) will propagate to the caller.
72+
"""
4373
# Get registered tools
4474
registered_toolgroups = await client.toolgroups.list()
4575
registered_toolgroups_ids = [
@@ -63,11 +93,28 @@ async def _register_mcp_toolgroups_async(
6393

6494

6595
def run_once_async(func: Callable) -> Callable:
66-
"""Decorate an async function to run only once."""
96+
"""
97+
Ensure that an async function is executed only once.
98+
99+
On the first invocation the wrapped coroutine is scheduled as an
100+
asyncio.Task on the current running event loop and its Task is cached.
101+
Later invocations return/await the same Task, receiving the same result or
102+
propagated exception. Requires an active running event loop when the
103+
wrapped function is first called.
104+
"""
67105
task = None
68106

69107
@wraps(func)
70108
async def wrapper(*args: Any, **kwargs: Any) -> Any:
109+
"""
110+
Run the wrapped async function exactly once and return its (awaited) result on every call.
111+
112+
On the first invocation this schedules the underlying coroutine as an
113+
asyncio.Task on the current running event loop and caches that task.
114+
Subsequent calls return the same awaited task result. Exceptions raised
115+
by the task propagate to callers. Requires an active running event loop
116+
when first called.
117+
"""
71118
nonlocal task
72119
if task is None:
73120
loop = asyncio.get_running_loop()

0 commit comments

Comments
 (0)