Packages

Official-style Elixir SDK for the Model Context Protocol (MCP) — client and server with stdio and Streamable HTTP transports.

Current section

Files

Jump to
mcp_elixir_sdk lib mcp protocol messages tools.ex
Raw

lib/mcp/protocol/messages/tools.ex

defmodule MCP.Protocol.Messages.Tools do
@moduledoc """
Message types for `tools/list` and `tools/call`.
"""
defmodule ListParams do
@moduledoc """
Parameters for `tools/list`.
"""
@derive Jason.Encoder
defstruct [:cursor, :meta]
@type t :: %__MODULE__{
cursor: String.t() | nil,
meta: map() | nil
}
@spec from_map(map()) :: t()
def from_map(map) when is_map(map) do
%__MODULE__{
cursor: Map.get(map, "cursor"),
meta: Map.get(map, "_meta")
}
end
@spec to_map(t()) :: map()
def to_map(%__MODULE__{} = params) do
%{}
|> maybe_put("cursor", params.cursor)
|> maybe_put("_meta", params.meta)
end
defp maybe_put(map, _key, nil), do: map
defp maybe_put(map, key, val), do: Map.put(map, key, val)
end
defmodule ListResult do
@moduledoc """
Result of `tools/list`.
"""
alias MCP.Protocol.Types.Tool
@derive Jason.Encoder
defstruct [:tools, :next_cursor, :meta]
@type t :: %__MODULE__{
tools: [Tool.t()],
next_cursor: String.t() | nil,
meta: map() | nil
}
@spec from_map(map()) :: t()
def from_map(map) when is_map(map) do
%__MODULE__{
tools: map |> Map.fetch!("tools") |> Enum.map(&Tool.from_map/1),
next_cursor: Map.get(map, "nextCursor"),
meta: Map.get(map, "_meta")
}
end
defimpl Jason.Encoder, for: __MODULE__ do
def encode(struct, opts) do
map = %{tools: struct.tools}
map = if struct.next_cursor, do: Map.put(map, :nextCursor, struct.next_cursor), else: map
map = if struct.meta, do: Map.put(map, :_meta, struct.meta), else: map
Jason.Encode.map(map, opts)
end
end
end
defmodule CallParams do
@moduledoc """
Parameters for `tools/call`.
"""
@derive Jason.Encoder
defstruct [:name, :arguments, :meta]
@type t :: %__MODULE__{
name: String.t(),
arguments: map() | nil,
meta: map() | nil
}
@spec from_map(map()) :: t()
def from_map(map) when is_map(map) do
%__MODULE__{
name: Map.fetch!(map, "name"),
arguments: Map.get(map, "arguments"),
meta: Map.get(map, "_meta")
}
end
@spec to_map(t()) :: map()
def to_map(%__MODULE__{} = params) do
%{"name" => params.name}
|> maybe_put("arguments", params.arguments)
|> maybe_put("_meta", params.meta)
end
defp maybe_put(map, _key, nil), do: map
defp maybe_put(map, key, val), do: Map.put(map, key, val)
end
defmodule CallResult do
@moduledoc """
Result of `tools/call`.
"""
alias MCP.Protocol.Types.Content
@derive Jason.Encoder
defstruct [:content, :structured_content, :is_error, :meta]
@type t :: %__MODULE__{
content: [Content.content_block()],
structured_content: map() | nil,
is_error: boolean() | nil,
meta: map() | nil
}
@spec from_map(map()) :: t()
def from_map(map) when is_map(map) do
%__MODULE__{
content: map |> Map.fetch!("content") |> Enum.map(&Content.from_map/1),
structured_content: Map.get(map, "structuredContent"),
is_error: Map.get(map, "isError"),
meta: Map.get(map, "_meta")
}
end
defimpl Jason.Encoder, for: __MODULE__ do
def encode(struct, opts) do
map = %{content: struct.content}
map =
if struct.structured_content,
do: Map.put(map, :structuredContent, struct.structured_content),
else: map
map = if struct.is_error, do: Map.put(map, :isError, struct.is_error), else: map
map = if struct.meta, do: Map.put(map, :_meta, struct.meta), else: map
Jason.Encode.map(map, opts)
end
end
end
end