# Run as: iex --dot-iex path/to/notebook.exs
# Title: 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:
alias Toolbox.MCP.ConnectionManager
ConnectionManager.list_connections()
# ── Discover Available Tools ──
# Each connected server exposes tools. Let's list them:
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:
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:
# 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`:
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"
# }
# }
# }
# ```