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

Smart constructors and builder patterns for ExMCP content creation.

This module provides an intuitive, chainable API for building complex content
structures with validation, type safety, and helpful defaults.

## Features

- **Chainable API**: Fluent interface for building content
- **Type Safety**: Compile-time type checking and validation
- **Smart Defaults**: Sensible defaults for common use cases
- **File Integration**: Direct file loading with automatic type detection
- **Batch Operations**: Efficient creation of multiple content items
- **Template System**: Reusable content templates

## Usage

    use ExMCP.Content.Builders

    # Simple text content
    content = text("Hello, world!")

    # Chainable building
    content = text("# Header")
    |> as_markdown()
    |> with_metadata(%{author: "user"})

    # File-based content
    content = from_file("image.png")
    |> with_alt_text("Product screenshot")
    |> resize(800, 600)

    # Batch creation
    contents = batch([
      text("First message"),
      image_from_file("diagram.png"),
      text("Summary", format: :markdown)
    ])

# `builder`

```elixir
@type builder() :: %{
  content: ExMCP.Content.Protocol.content() | nil,
  errors: [String.t()],
  metadata: map()
}
```

Content builder state

# `file_opts`

```elixir
@type file_opts() :: [
  max_size: pos_integer(),
  mime_types: [String.t()],
  auto_resize: {pos_integer(), pos_integer()},
  quality: float()
]
```

File processing options

# `annotation`

```elixir
@spec annotation(
  String.t(),
  keyword()
) :: ExMCP.Content.Protocol.annotation()
```

Creates a new annotation builder.

# `as_code`

```elixir
@spec as_code(ExMCP.Content.Protocol.text(), String.t() | nil) ::
  ExMCP.Content.Protocol.text()
```

Sets content as code format with optional language.

## Examples

    content = text("console.log()") |> as_code("javascript")
    content = text("SELECT * FROM users") |> as_code("sql")

# `as_html`

```elixir
@spec as_html(ExMCP.Content.Protocol.text()) :: ExMCP.Content.Protocol.text()
```

Sets content as HTML format.

# `as_markdown`

```elixir
@spec as_markdown(ExMCP.Content.Protocol.text()) :: ExMCP.Content.Protocol.text()
```

Sets content as markdown format.

## Examples

    content = text("# Header") |> as_markdown()

# `audio`

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

Creates a new audio content builder from base64 data.

# `audio_from_file`

```elixir
@spec audio_from_file(
  String.t(),
  keyword()
) :: ExMCP.Content.Protocol.audio() | {:error, String.t()}
```

Creates audio content from a file.

# `batch`

```elixir
@spec batch([
  (-&gt; ExMCP.Content.Protocol.content()) | ExMCP.Content.Protocol.content()
]) :: [
  ExMCP.Content.Protocol.content()
]
```

Creates multiple content items efficiently.

## Examples

    contents = batch([
      text("First message"),
      image_from_file("chart.png"),
      text("Summary", format: :markdown)
    ])

# `collection`

```elixir
@spec collection([ExMCP.Content.Protocol.content()], map()) :: [
  ExMCP.Content.Protocol.content()
]
```

Creates a content collection with shared metadata.

## Examples

    contents = collection([
      text("Message 1"),
      text("Message 2")
    ], %{conversation_id: "abc123", timestamp: DateTime.utc_now()})

# `compress`

> This function is deprecated. Not an MCP/ACP API; never implemented. Planned for removal in 2.0.0..

```elixir
@spec compress(
  ExMCP.Content.Protocol.image(),
  keyword()
) :: ExMCP.Content.Protocol.image() | {:error, String.t()}
```

Compresses image content.

Deprecated stub — not an MCP requirement.

# `extract_text`

```elixir
@spec extract_text(ExMCP.Content.Protocol.content()) :: String.t() | nil
```

Extracts text content from various content types.

## Examples

    text_content = extract_text(image_content)  # Uses alt_text
    text_content = extract_text(audio_content)  # Uses transcript

# `filter_by_type`

```elixir
@spec filter_by_type([ExMCP.Content.Protocol.content()], atom() | [atom()]) :: [
  ExMCP.Content.Protocol.content()
]
```

Filters content by type.

## Examples

    text_only = filter_by_type(contents, :text)
    media_content = filter_by_type(contents, [:image, :audio])

# `from_file`

```elixir
@spec from_file(String.t(), file_opts()) ::
  ExMCP.Content.Protocol.content() | {:error, String.t()}
```

Creates content from a file with automatic type detection.

## Examples

    # Image file
    content = from_file("screenshot.png")

    # Text file
    content = from_file("README.md")

    # With options
    content = from_file("large_image.jpg", max_size: 1_000_000, auto_resize: {800, 600})

# `from_template`

```elixir
@spec from_template(ExMCP.Content.Protocol.text(), map()) ::
  ExMCP.Content.Protocol.text()
```

Creates content from a template with substitutions.

## Examples

    template = text("Hello, {{name}}! Your score is {{score}}")
    content = from_template(template, %{name: "Alice", score: 95})
    # Results in: text("Hello, Alice! Your score is 95")

# `image`

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

Creates a new image content builder from base64 data.

## Examples

    iex> image("iVBORw0K...", "image/png")
    %{type: :image, data: "iVBORw0K...", mime_type: "image/png", ...}

# `image_from_file`

```elixir
@spec image_from_file(
  String.t(),
  keyword()
) :: ExMCP.Content.Protocol.image() | {:error, String.t()}
```

Creates image content from a file.

## Examples

    content = image_from_file("photo.jpg")
    content = image_from_file("diagram.png", alt_text: "System architecture", auto_resize: {800, 600})

# `resize`

> This function is deprecated. Not an MCP/ACP API; never implemented. Planned for removal in 2.0.0..

```elixir
@spec resize(ExMCP.Content.Protocol.image(), pos_integer(), pos_integer()) ::
  ExMCP.Content.Protocol.image() | {:error, String.t()}
```

Resizes image content data.

Deprecated stub — not an MCP requirement. MCP image content is base64 + MIME only.

# `resource`

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

Creates a new resource reference builder.

# `text`

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

Creates a new text content builder.

## Examples

    iex> text("Hello")
    %{type: :text, text: "Hello", format: :plain, language: nil, metadata: %{}}

    iex> text("console.log('hi')", format: :code, language: "javascript")
    %{type: :text, text: "console.log('hi')", format: :code, language: "javascript", metadata: %{}}

# `text_from_file`

```elixir
@spec text_from_file(
  String.t(),
  keyword()
) :: ExMCP.Content.Protocol.text() | {:error, String.t()}
```

Creates text content from a file with format detection.

## Examples

    content = text_from_file("README.md")  # Auto-detects markdown
    content = text_from_file("script.js")  # Auto-detects code with language

# `transform`

```elixir
@spec transform(ExMCP.Content.Protocol.content(), (ExMCP.Content.Protocol.content() -&gt;
                                               ExMCP.Content.Protocol.content()
                                               | {:error, String.t()})) ::
  ExMCP.Content.Protocol.content() | {:error, String.t()}
```

Transforms content with a function, handling errors gracefully.

## Examples

    result = transform(content, fn c -> with_metadata(c, %{processed: true}) end)

# `validate_all`

```elixir
@spec validate_all([ExMCP.Content.Protocol.content()]) :: :ok | {:error, [String.t()]}
```

Validates a list of content items.

## Examples

    contents = [text("Hello"), image(data, "image/png")]
    case validate_all(contents) do
      :ok -> contents
      {:error, errors} -> handle_errors(errors)
    end

# `with_alt_text`

```elixir
@spec with_alt_text(ExMCP.Content.Protocol.image(), String.t()) ::
  ExMCP.Content.Protocol.image()
```

Adds alt text to image content.

## Examples

    content = image(data, "image/png") |> with_alt_text("Product screenshot")

# `with_confidence`

```elixir
@spec with_confidence(ExMCP.Content.Protocol.annotation(), float()) ::
  ExMCP.Content.Protocol.annotation()
```

Adds confidence to annotation content.

## Examples

    content = annotation("sentiment") |> with_confidence(0.95)

# `with_dimensions`

```elixir
@spec with_dimensions(ExMCP.Content.Protocol.image(), pos_integer(), pos_integer()) ::
  ExMCP.Content.Protocol.image()
```

Sets dimensions for image content.

## Examples

    content = image(data, "image/png") |> with_dimensions(800, 600)

# `with_duration`

```elixir
@spec with_duration(ExMCP.Content.Protocol.audio(), float()) ::
  ExMCP.Content.Protocol.audio()
```

Sets duration for audio content.

## Examples

    content = audio(data, "audio/wav") |> with_duration(45.5)

# `with_metadata`

```elixir
@spec with_metadata(ExMCP.Content.Protocol.content(), map()) ::
  ExMCP.Content.Protocol.content()
```

Adds metadata to any content type.

## Examples

    content = text("Hello") |> with_metadata(%{author: "user", timestamp: DateTime.utc_now()})

# `with_transcript`

```elixir
@spec with_transcript(ExMCP.Content.Protocol.audio(), String.t()) ::
  ExMCP.Content.Protocol.audio()
```

Adds transcript to audio content.

## Examples

    content = audio(data, "audio/wav") |> with_transcript("Hello, this is a recording")

---

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