ExMCP.Content.Protocol (ex_mcp v0.7.4)
View SourceContent protocol for ExMCP - type-safe content handling system.
This module defines the core protocol and types for handling different content types in MCP messages, providing a unified interface for text, images, audio, and embedded resources.
Content Types
- Text: Plain text, markdown, code, etc.
- Image: Base64-encoded images with metadata
- Audio: Base64-encoded audio with metadata
- Resource: Embedded resource references
- Annotation: Metadata annotations for content
Design Principles
- Type Safety: All content has compile-time type checking
- Extensibility: Easy to add new content types
- Validation: Built-in validation for content structure
- Performance: Efficient serialization/deserialization
- Developer Experience: Intuitive constructors and builders
Summary
Types
Annotation content for metadata
Audio content with base64 data and metadata
Base content protocol for all content types
Image content with base64 data and metadata
Resource reference content
Content serialization options
Text content with optional formatting
Content validation result
Functions
Creates new annotation content.
Creates new audio content from base64 data.
Gets the content type for given content.
Checks if content is of a specific type.
Deserializes content from MCP protocol format.
Creates new image content from base64 data.
Creates new resource reference content.
Serializes content to MCP protocol format.
Creates new text content.
Validates content structure and data integrity.
Types
@type annotation() :: %{ type: :annotation, annotation: %{ type: String.t(), confidence: float() | nil, text: String.t() | nil }, metadata: map() }
Annotation content for metadata
@type audio() :: %{ type: :audio, data: String.t(), mime_type: String.t(), duration: float() | nil, transcript: String.t() | nil, metadata: map() }
Audio content with base64 data and metadata
@type content() :: text() | image() | audio() | resource() | annotation()
Base content protocol for all content types
@type image() :: %{ type: :image, data: String.t(), mime_type: String.t(), width: pos_integer() | nil, height: pos_integer() | nil, alt_text: String.t() | nil, metadata: map() }
Image content with base64 data and metadata
@type resource() :: %{ type: :resource, resource: %{ uri: String.t(), text: String.t() | nil, mime_type: String.t() | nil }, metadata: map() }
Resource reference content
@type serialize_opts() :: [ format: :mcp | :json | :compact, validate: boolean(), include_metadata: boolean() ]
Content serialization options
@type text() :: %{ type: :text, text: String.t(), format: :plain | :markdown | :code | :html, language: String.t() | nil, metadata: map() }
Text content with optional formatting
@type validation_result() :: :ok | {:error, String.t()}
Content validation result
Functions
@spec annotation( String.t(), keyword() ) :: annotation()
Creates new annotation content.
Examples
iex> ExMCP.Content.Protocol.annotation("sentiment", confidence: 0.95, text: "positive")
%{type: :annotation, annotation: %{type: "sentiment", confidence: 0.95, text: "positive"}, metadata: %{}}
Creates new audio content from base64 data.
Examples
iex> data = Base.encode64("fake audio data")
iex> ExMCP.Content.Protocol.audio(data, "audio/wav")
%{type: :audio, data: data, mime_type: "audio/wav", duration: nil, transcript: nil, metadata: %{}}
Gets the content type for given content.
Examples
iex> content = ExMCP.Content.Protocol.text("Hello")
iex> ExMCP.Content.Protocol.content_type(content)
:text
Checks if content is of a specific type.
Examples
iex> content = ExMCP.Content.Protocol.text("Hello")
iex> ExMCP.Content.Protocol.content_type?(content, :text)
true
iex> ExMCP.Content.Protocol.content_type?(content, :image)
false
Deserializes content from MCP protocol format.
Examples
iex> data = %{"type" => "text", "text" => "Hello"}
iex> ExMCP.Content.Protocol.deserialize(data)
{:ok, %{type: :text, text: "Hello", format: :plain, language: nil, metadata: %{}}}
Creates new image content from base64 data.
Examples
iex> data = Base.encode64("fake image data")
iex> ExMCP.Content.Protocol.image(data, "image/png")
%{type: :image, data: data, mime_type: "image/png", width: nil, height: nil, alt_text: nil, metadata: %{}}
Creates new resource reference content.
Examples
iex> ExMCP.Content.Protocol.resource("file://data.txt")
%{type: :resource, resource: %{uri: "file://data.txt", text: nil, mime_type: nil}, metadata: %{}}
iex> ExMCP.Content.Protocol.resource("file://doc.pdf", text: "Important document", mime_type: "application/pdf")
%{type: :resource, resource: %{uri: "file://doc.pdf", text: "Important document", mime_type: "application/pdf"}, metadata: %{}}
@spec serialize(content(), serialize_opts()) :: map()
Serializes content to MCP protocol format.
Examples
iex> content = ExMCP.Content.Protocol.text("Hello")
iex> ExMCP.Content.Protocol.serialize(content)
%{"type" => "text", "text" => "Hello"}
iex> content2 = ExMCP.Content.Protocol.text("Hello")
iex> ExMCP.Content.Protocol.serialize(content2, format: :compact)
%{"type" => "text", "text" => "Hello"}
Creates new text content.
Examples
iex> ExMCP.Content.Protocol.text("Hello, world!")
%{type: :text, text: "Hello, world!", format: :plain, language: nil, metadata: %{}}
iex> ExMCP.Content.Protocol.text("# Header", format: :markdown)
%{type: :text, text: "# Header", format: :markdown, language: nil, metadata: %{}}
iex> ExMCP.Content.Protocol.text("console.log('hi')", format: :code, language: "javascript")
%{type: :text, text: "console.log('hi')", format: :code, language: "javascript", metadata: %{}}
@spec validate(content()) :: validation_result()
Validates content structure and data integrity.
Examples
iex> content = ExMCP.Content.Protocol.text("Hello")
iex> ExMCP.Content.Protocol.validate(content)
:ok
iex> invalid = %{type: :text, text: nil}
iex> ExMCP.Content.Protocol.validate(invalid)
{:error, "Text content must have non-nil text field"}