list_mcp_tools
Python · package toolnexus · SPEC §2 · python/src/toolnexus/mcp_source.py
async def list_mcp_tools( input: str | dict[str, Any], *, cancel: asyncio.Event | None = None,) -> McpInventoryConnects to every enabled server, lists its tool definitions, and disconnects before
returning — no Tool.execute, no toolkit, nothing left running. The returned tool defs use each
server’s original, unprefixed names, and are the unfiltered set (ignoring any per-server
tools allowlist in config) — this is the call that exists to author and validate those
allowlists, so it needs to show you everything a server has, not the narrowed view.
When to use it
Section titled “When to use it”- Building a config UI or a
mcp.jsonvalidator: show what a server would expose, without committing to running it. - Deciding a per-server
toolsallowlist — you need the full, unfiltered tool list to write it against. - A one-shot inventory (a CLI
--list-toolsflag, a CI check) where holding connections open past the listing would be pure waste.
Why this and not the alternative
Section titled “Why this and not the alternative”Examples
Section titled “Examples”1. Disabled servers report status, and nothing else
Section titled “1. Disabled servers report status, and nothing else”import asynciofrom toolnexus import list_mcp_tools, parse_mcp_config
config = parse_mcp_config("examples/mcp.json")for cfg in config.values(): cfg["enabled"] = False
async def main(): inventory = await list_mcp_tools(config)
assert inventory.tools == {} assert inventory.status == {"everything": "disabled", "example-remote": "disabled"}
print("ok:", inventory.status)
asyncio.run(main())2. A failed server has no entry in tools
Section titled “2. A failed server has no entry in tools”inventory.tools only gets a key for a server that actually listed successfully — a failed
connect shows up in status, not as an empty list.
import asynciofrom toolnexus import list_mcp_tools
config = { "broken": { "type": "local", "command": ["/no/such/binary-toolnexus-docs-example"], },}
async def main(): inventory = await list_mcp_tools(config)
assert inventory.status["broken"] == "failed" # No key at all for a server that never listed anything — not `[]`. assert "broken" not in inventory.tools
print("ok:", inventory.status, "| tools:", inventory.tools)
asyncio.run(main())3. Parse first, decide what to inventory, run it, confirm nothing lingers
Section titled “3. Parse first, decide what to inventory, run it, confirm nothing lingers”The realistic shape: use parse_mcp_config to see what a config
declares, then call list_mcp_tools on the part you actually want inventoried. Here every server
is disabled, so the call has nothing to connect to — proving the “disconnect before returning”
contract trivially, since there is nothing left to disconnect.
import asynciofrom toolnexus import list_mcp_tools, parse_mcp_config
config = parse_mcp_config("examples/mcp.json")assert sorted(config.keys()) == ["everything", "example-remote"]for cfg in config.values(): cfg["enabled"] = False
async def main(): inventory = await list_mcp_tools(config, cancel=asyncio.Event())
assert inventory.tools == {} assert set(inventory.status) == {"everything", "example-remote"} assert all(v == "disabled" for v in inventory.status.values())
print("ok:", sorted(inventory.status))
asyncio.run(main())Options
Section titled “Options”| Parameter | Type | What it does |
|---|---|---|
input |
str | dict |
Same accepted shapes as load_mcp — see parse_mcp_config. |
cancel |
asyncio.Event | None |
Same whole-call abort semantics as load_mcp_with_context. |
Returns — McpInventory
Section titled “Returns — McpInventory”| Member | Type | What it is |
|---|---|---|
tools |
dict[str, list[ToolInfo]] |
Server name → its listed, unfiltered tool defs (original names). Only present for a server that listed successfully. |
status |
dict[str, McpStatus] |
Per-server "connected", "disabled", or "failed" — same vocabulary as load_mcp. |
ToolInfo carries name, description, input_schema — no execute.
See also
Section titled “See also”load_mcp— Read an mcp.json, connect every local stdio and remote streamable-HTTP server, expose each server tool as a Tool.load_mcp_with_context— The ctx-aware load: bound connection time and cancel a slow or hung server without leaking a child process.parse_mcp_config— Parse and validate config without connecting — the fast fail for a malformed or misspelled server block.elicitation_to_request— Map an MCP server’s elicitation request onto the §10 suspension contract, and map the answer back.