Imports the tools of authorized MCP servers as ordinary Imp.Tool values.
connect/2 dials each server, lists its tools and returns them with their
source provenance and one cleanup function. Imported tools validate required
fields and basic JSON-schema-style property constraints. Tool schemas follow
the MCP specification dialect: the input contract is the camelCase
"inputSchema" key (MCP spec, Tool definition) and "description" is
optional.
Imported tools default to result_mode: :text, matching DSPy's MCP tool
boundary: one text block becomes a string, multiple text blocks become a
list, and non-text blocks are returned when no text is present. Set
result_mode: :structured to return structuredContent exactly when the
server includes it—even when its value is nil, false, 0, or empty—and
fall back to the text conversion only when that field is absent. MCP error
results become {:error, {:mcp_tool_error, original_envelope}} before either
conversion. The original structured failure and content remain available;
uncertainty about an effect must not be collapsed into a retryable refusal.
A call that got no answer from its tool returns
{:error, %Imp.MCP.CallFailure{}}, whose outcome says whether it was
refused, never sent, or sent with no trustworthy answer.
Summary
Functions
Connects authorized MCP servers; returns tools with source metadata and cleanup.
The words a model reads for a failed MCP tool call.
Functions
@spec connect([Imp.MCP.Connections.descriptor()], keyword()) :: {:ok, Imp.MCP.Import.t()} | {:error, term()}
Connects authorized MCP servers; returns tools with source metadata and cleanup.
servers is a list of descriptor maps, local ("command") or remote
("url"); see Imp.MCP.Connections for their shape and every option.
server = %{"name" => "files", "command" => "my-mcp-server", "args" => ["--stdio"]}
{:ok, import} = Imp.MCP.connect([server], trusted_servers: [server])
agent = Imp.react("question -> answer", import.tools, lm: lm)
The words a model reads for a failed MCP tool call.
An error result ({:mcp_tool_error, envelope}) is the text its tool wrote:
MCP spec, CallToolResult, puts what went wrong in the content, for the model
to read. Its text items are joined; its structured content stands in as plain
data when there is no text. For an Imp.MCP.CallFailure, a JSON-RPC error is
the server's message, and otherwise the sentence follows its outcome: a
refused call says the server refused it, a call whose credential was
refused says so, a call that was not sent says so,
and a call whose outcome is unknown says it got no answer, why, and that it
may have been carried out, because a timeout, a closed or failed connection,
a broken stream, or a server that stopped waiting for its tool does not say
whether the tool ran, and a write that did run must not read as one that did
not.
This is only what is read. The error term itself, which the loop records, keeps the whole envelope or reason.
iex> failure = %Imp.MCP.CallFailure{
...> outcome: :unknown,
...> index: 0,
...> server_name: "kite",
...> tool_name: "reply",
...> reason: :timeout
...> }
iex> Imp.MCP.failure_text(failure)
"no answer came back; it timed out, so it may have been carried out."