# `ExMCP.Content.Protocol`
[🔗](https://github.com/azmaveth/ex_mcp/blob/v1.0.0/lib/ex_mcp/content/protocol.ex#L1)

Content 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

1. **Type Safety**: All content has compile-time type checking
2. **Extensibility**: Easy to add new content types
3. **Validation**: Built-in validation for content structure
4. **Performance**: Efficient serialization/deserialization
5. **Developer Experience**: Intuitive constructors and builders

# `annotation`

```elixir
@type annotation() :: %{
  type: :annotation,
  annotation: %{
    type: String.t(),
    confidence: float() | nil,
    text: String.t() | nil
  },
  metadata: map()
}
```

Annotation content for metadata

# `audio`

```elixir
@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

# `content`

```elixir
@type content() :: text() | image() | audio() | resource() | annotation()
```

Base content protocol for all content types

# `image`

```elixir
@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

# `resource`

```elixir
@type resource() :: %{
  type: :resource,
  resource: %{
    uri: String.t(),
    text: String.t() | nil,
    mime_type: String.t() | nil
  },
  metadata: map()
}
```

Resource reference content

# `serialize_opts`

```elixir
@type serialize_opts() :: [
  format: :mcp | :json | :compact,
  validate: boolean(),
  include_metadata: boolean()
]
```

Content serialization options

# `text`

```elixir
@type text() :: %{
  type: :text,
  text: String.t(),
  format: :plain | :markdown | :code | :html,
  language: String.t() | nil,
  metadata: map()
}
```

Text content with optional formatting

# `validation_result`

```elixir
@type validation_result() :: :ok | {:error, String.t()}
```

Content validation result

# `annotation`

```elixir
@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: %{}}

# `audio`

```elixir
@spec audio(String.t(), String.t(), keyword()) :: audio()
```

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: %{}}

# `content_type`

```elixir
@spec content_type(content()) :: atom()
```

Gets the content type for given content.

## Examples

    iex> content = ExMCP.Content.Protocol.text("Hello")
    iex> ExMCP.Content.Protocol.content_type(content)
    :text

# `content_type?`

```elixir
@spec content_type?(content(), atom()) :: boolean()
```

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

# `deserialize`

```elixir
@spec deserialize(map()) :: {:ok, content()} | {:error, String.t()}
```

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: %{}}}

# `image`

```elixir
@spec image(String.t(), String.t(), keyword()) :: image()
```

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: %{}}

# `resource`

```elixir
@spec resource(
  String.t(),
  keyword()
) :: resource()
```

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: %{}}

# `serialize`

```elixir
@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"}

# `text`

```elixir
@spec text(
  String.t(),
  keyword()
) :: text()
```

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: %{}}

# `validate`

```elixir
@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"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
