# MCP Servers — Tool Discovery & Execution
## What is MCP?
The [Model Context Protocol](https://modelcontextprotocol.io) lets LLMs call
external tools through a standard interface. Skynet can both **connect to**
MCP servers (as a client) and **expose actions as** an MCP server.
## Connected Servers
See which MCP servers are configured and connected:
```elixir
alias Toolbox.MCP.ConnectionManager
ConnectionManager.list_connections()
```
## Discover Available Tools
Each connected server exposes tools. Let's list them:
```elixir
alias Toolbox.MCP.ToolRegistry
tools = ToolRegistry.list_all_tools()
tools
|> Enum.group_by(& &1["_server"])
|> Enum.each(fn {server, tool_list} ->
IO.puts("\n--- #{server} ---")
for tool <- tool_list do
IO.puts(" #{tool["name"]}: #{tool["description"] |> String.slice(0..80)}")
end
end)
:ok
```
## Call an MCP Tool
Use the `MCPCall` action to invoke a tool on a connected server:
```elixir
alias Toolbox.Actions.MCPCall
# Example: list files using the filesystem MCP server
{:ok, result} =
MCPCall.run(
%{
server: :filesystem,
tool: "list_directory",
arguments: %{"path" => "/tmp"}
},
%{}
)
result
```
## Add a Server at Runtime
You can connect to additional MCP servers without restarting:
```elixir
# Example: connect to a local MCP server
ConnectionManager.add_server(:my_server, %{
transport: :stdio,
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home"]
})
```
## Skynet as MCP Server
Skynet also exposes its own actions as MCP tools. External agents
(Claude Code, Cursor, etc.) can connect to Skynet's MCP server.
The exposed actions are configured in `config/runtime.exs`:
```elixir
Application.get_env(:toolbox, :mcp_server)
```
To connect from Claude Code, add to your `.claude/settings.json`:
```json
{
"mcpServers": {
"skynet": {
"type": "streamable-http",
"url": "http://your-server:4288/mcp"
}
}
}
```