name is what the API calls the endpoint, and Charter never changes
it. Qualification belongs to whoever assembles tools into one namespace; these
are the functions that do it, so every assembler uses one convention.
Two APIs really do declare the same tool name — products_list exists in both
Stripe and Shopify — so a surface holding both has to disambiguate them.
See Tool names across packs for why the library does not
qualify its own names, and why pack is not provider.
qualified_names
Every tool under <pack>__<tool>, keyed by the qualified name. This is what the
three shipped adapters call, so a pack is named the same way inline, through
LangChain, and over MCP.
Qualified whatever else is loaded. A name is a property of the tool, not of its
neighbours: qualifying only once a second pack appeared would rename every tool
in the first the day someone added one, breaking saved prompts, allow-lists and
logged traces in silence. MCP servers publish the same names whatever else is
installed, and a host composes mcp__<server>__<tool> on top — charter-mcp
names its server charter, so the result reads
mcp__charter__gcalendar__events_list.
stripe__products_list sits beside a bare balance_retrieve makes the pack a
substring of some names and not others, so any filter over it silently misses
the unqualified half.
Raises DeclarationError if a tool
declares no pack, or if two tools qualify to the same name.
qualified_name
One tool’s qualified name.
DeclarationError if the tool
declares no pack. Falling back to the bare name would produce the
half-qualified surface above, silently.
Routing a tool call back
MCP and LangChain resolve a tool call by name for you. The OpenAI APIs hand it back to you to execute, so you need the same mapping you published with —qualified_names is it.
Tool directly in Python never involves a name at all — tool.name
stays events_list, and await gcalendar.events_list.ainvoke(...) is a Python
reference. Qualification exists only where tools are published to a model.