Current section
Files
Jump to
Current section
Files
lib/phantom/resource_template.ex
defmodule Phantom.ResourceTemplate do
@moduledoc """
The Model Context Protocol (MCP) provides a standardized way for
servers to expose resources to clients. Resources allow servers to
share data that provides context to language models, such as files,
database schemas, or application-specific information. Each resource
is uniquely identified by a URI.
https://modelcontextprotocol.io/specification/2025-03-26/server/resources
"""
import Phantom.Utils
defstruct [
:name,
:description,
:function,
:completion_function,
:handler,
:mime_type,
:path,
:router,
:scheme,
:size,
:uri,
:uri_template
]
@type t :: %__MODULE__{
name: String.t(),
description: String.t(),
function: atom(),
completion_function: atom(),
handler: module(),
mime_type: String.t(),
path: String.t(),
router: module(),
scheme: String.t(),
size: pos_integer(),
uri: URI.t(),
uri_template: String.t()
}
@type json :: %{
required(:uri) => String.t(),
required(:name) => String.t(),
optional(:description) => String.t(),
optional(:mimeType) => String.t(),
optional(:size) => pos_integer()
}
@spec build(map() | Keyword.t()) :: t()
def build(attrs) do
attrs = Map.new(attrs)
uri_template = "#{attrs.scheme}://#{to_uri_6570(attrs.path)}"
struct!(__MODULE__, Map.put(attrs, :uri_template, uri_template))
end
@spec to_json(t()) :: json()
def to_json(%__MODULE__{} = resource) do
remove_nils(%{
uriTemplate: resource.uri_template,
name: resource.name,
size: resource.size,
description: resource.description,
mimeType: resource.mime_type
})
end
defp to_uri_6570(str) do
String.replace(str, ~r/:\w*/, fn ":" <> var -> "{#{var}}" end)
end
@doc false
# TODO: not ready
def updated(uri), do: %{uri: uri}
@doc "Formats the response from an MCP Router to the MCP specification"
def response(results, resource_template, uri) do
%{
contents:
results
|> List.wrap()
|> Enum.map(fn result ->
encode(%{
blob: result[:blob],
text: result[:text],
mimeType: result[:mime_type] || resource_template.mime_type,
uri: uri
})
end)
}
end
end