# `PhoenixKit.API.MCP.Names`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.64.1/lib/phoenix_kit/api/mcp/names.ex#L1)

Tool names on MCP.

Some model APIs accept only `[a-zA-Z0-9_-]` in tool names, so MCP shows
every tool with `_` where the name has a `.` (`catalogue.set_prices` is
`catalogue_set_prices`). REST and OpenAPI keep the dotted name, and
`tools/call` accepts both.

Two tools of one audience can map to the same MCP name (`a.b_c` and
`a_b.c`). `PhoenixKit.API.ToolLint.check_tools/1` reports that in a
module's tests; at run time the first one in registry order wins, in
`dedupe/1` and in `resolve/2`. `dedupe/1` works on the list the caller may
see and `resolve/2` ignores scopes, so when the two tools need different
scopes a key that holds only the second one sees the second tool in
`tools/list`, while `tools/call` with the underscore name reaches the first
and is refused. The dotted name always reaches its own tool.

# `dedupe`

```elixir
@spec dedupe([PhoenixKit.API.Tool.t()]) :: [PhoenixKit.API.Tool.t()]
```

Drops every tool whose MCP name an earlier tool of the list already has.

# `resolve`

```elixir
@spec resolve(String.t(), PhoenixKit.API.Tool.audience()) :: String.t()
```

The dotted name for `name`, which may be given in either form.

A name that has a `.` is returned as it is. An underscore name is mapped to
the dotted name of a tool **of `audience`**: a live one, or one whose module
is switched off (so that `PhoenixKit.API.Executor` can say `module_disabled`
instead of `not_found`). That is decided by `PhoenixKit.API.Registry.find/2`,
which looks at the audience, so the answer for a tool of the other audience,
a tool hidden by `api_disabled_tools`, a tool of a module switched off in
`api_disabled_modules` and a name nobody has is the same: the name comes
back unchanged. An anonymous caller of the public endpoint can
therefore not learn the dotted name of an admin tool, or that it exists.

Whether the tool is visible to the caller, permitted or enabled is the
executor's answer.

# `to_mcp`

```elixir
@spec to_mcp(String.t()) :: String.t()
```

The MCP form of a tool name.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
