Tool naming
Every tool in the ScaiMCP catalog has a stable, predictable name. Once you know the conventions you can read the catalog at a glance, and you can route an agent to the right tool without listing first.
The three sources#
A name in the catalog comes from one of three places:
- Core tools — registered by ScaiMCP itself, covering ScaiGrid's own API surface (inference, models, sessions, rooms, accounting, IAM, webhooks, modules admin, platform admin).
- Module-contributed tools — registered by other ScaiGrid modules through their
get_mcp_tools()hook. ScaiBunker, ScaiMatrix, ScaiQueue, and others contribute tools this way. - Cloud MCP servers — registered by users through ScaiLink's cloud MCP registry. ScaiMCP aggregates them under the
remote.prefix.
The naming convention differs by source.
Core tools: domain_action#
Core tools follow domain_action with an underscore separator. The domain is the resource family; the action is the verb.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
The domain matches the underlying REST resource (/v1/inference, /v1/models, /v1/sessions, etc.). If you know the REST endpoint, the tool name is almost always derivable.
Module-contributed tools: module_action or module_domain_action#
Modules pick their own prefix; convention is to use the module id as the leading token. ScaiBunker's tools are bunker_create, bunker_exec, bunker_terminate; ScaiMatrix's are matrix_search, matrix_ingest_document. Verify a module's exact names by listing the catalog with the module enabled, or by looking at the module's docs.
A tool's module_id decides whether it appears at all — if the module is not enabled for the caller's tenant, the tool is filtered out of list_tools and call_tool returns MODULE_NOT_ENABLED.
Cloud MCP tools: remote.{scope}.{slug}.{tool}#
When a user (or tenant admin) registers a cloud MCP server through ScaiLink, the server's tools appear in the catalog under a four-segment name:
1 | |
remote.— fixed prefix. Reserved; no core or module tool may start with it.{user_id|tenant}— the registration scope. A personal registration uses the registrar'suser_id; a tenant-shared registration uses the literal stringtenant.{slug}— the registry slug assigned to the cloud server (e.g.notion-prod,slack-acme). Unique within the scope.{tool}— the tool name as advertised by the upstream MCP server.
Examples:
1 2 3 | |
The prefix is unambiguous, so the call_tool handler routes by it: anything starting with remote. goes through ScaiLink's outbound MCP client; everything else stays local.
Why personal vs tenant matters#
A personal registration is visible to one user only — their user_id is baked into the name. A tenant registration is visible to every user in the tenant who holds scailink:remote.use. The scope is enforced at list_tools time; an agent acting as a different user simply does not see the other user's personal tools.
This split lets each user wire up their own personal MCP servers (their Notion, their email, their bookmark store) without polluting the tenant catalog, while still allowing the tenant to share a curated set of operational tools.
Naming for module authors#
If you're writing a ScaiGrid module that contributes MCP tools, follow two rules:
- Prefix with your module id.
mymodule_action,mymodule_resource_action. Keeps the catalog readable and prevents collisions. - Never start with
remote.— that prefix is reserved for the cloud MCP aggregator. The server actively rejects ambiguity here.
For tools where the underlying capability has multiple verbs (create / list / get / update / delete), use _ to separate them: mymodule_resource_create, not mymodule-resource-create or mymodule.resource.create. Underscores are the catalog convention.
Naming and discoverability#
LLMs choose tools by reading names and descriptions. A good name is a hint, but the description is what carries semantic weight. If you can't tell from a tool's name what it does, the description should fill the gap — keep names short and descriptions informative. ScaiMCP's core tools are tuned for this; mirror that style in module contributions.
Stability guarantees#
Core tool names are stable within a major version. Renaming a core tool is a breaking change and follows the same deprecation policy as the underlying REST endpoint. New tools may be added at any time; agents should tolerate previously-unseen names.
Module-contributed tools follow each module's own versioning. A module's docs are authoritative for which names it ships in which version.
Remote tool names are at the mercy of the upstream registration. A slug rename or upstream rename will change the catalog name; treat remote names as runtime-discovered, not hardcoded.
Reading a name#
When you see inference_chat in a catalog, you know:
- No prefix and no module gate (the tool registers without a
module_id) — it's part of ScaiGrid's core surface. - Underscore-separated domain and action —
inferenceresource,chatverb. - Maps to
/v1/inference/chaton REST.
When you see bunker_exec:
bunker_prefix → contributed by the ScaiBunker module.- Only appears when ScaiBunker is enabled for your tenant.
- Maps to ScaiBunker's exec endpoint.
When you see remote.tenant.notion-prod.search_pages:
remote.prefix → cloud MCP server registered through ScaiLink.tenantscope → registered tenant-wide; visible to anyone in the tenant withscailink:remote.use.notion-prod→ the registration's slug.search_pages→ the tool name advertised by the upstream Notion MCP server.
That fourth segment can contain underscores; everything after the third dot is the upstream name verbatim. So remote.tenant.github-internal.list_pull_requests is a single tool, not nested namespaces.
What changes when a permission is revoked#
A tool disappearing from list_tools because its permission was revoked is observably the same as it never existing. Agents that cache the catalog need to re-fetch on a meaningful interval or re-fetch on TOOL_NOT_FOUND / PERMISSION_DENIED errors. ScaiMCP itself never caches — every list_tools call goes through the full filter pipeline against the current CurrentUser.