# Tools return proper content types (text, image, resource)

- **Pattern:** `ab-001830` (`mcp-server.tool-definitions.return-content-types`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001830
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001830)

## Why it matters

The MCP content type system (`text`, `image`, `resource`) tells clients how to render tool results. Returning a raw string instead of a `content` array means clients receive output they cannot reliably parse or display. Image tools that omit `mimeType` from `data` content leave clients unable to decode the bytes. These are protocol conformance failures — a client following the MCP spec will reject or misrender non-conformant responses, turning working tool calls into user-visible errors.

## Severity rationale

Low because malformed return structures cause display or parse failures in clients but do not expose data or enable attacks; the impact is limited to incorrect rendering.

## Remediation

Return a `content` array with the correct `type` field from every tool handler. Never return a raw string.

```ts
// src/tools/screenshot.ts
server.tool('screenshot', ..., async () => ({
  content: [{
    type: 'image',
    data: base64ImageData,   // required for image
    mimeType: 'image/png',  // required for image
  }]
}))

// Text result
server.tool('read_file', ..., async ({ path }) => ({
  content: [{ type: 'text', text: await fs.readFile(path, 'utf-8') }]
}))
```

For tools returning multiple items, include them as separate entries in the `content` array — not as a concatenated string.

## Detection

- **ID:** `return-content-types`
- **Severity:** `low`
- **What to look for:** Count all tool return statements. Enumerate which specify content types (text, image, resource) vs. which return untyped content. Examine the return values of all tool handlers. Check that handlers return `content` arrays with proper `type` fields (`text`, `image`, or `resource`). For text content, verify the `text` field is a string. For image content, verify `data` (base64) and `mimeType` are set. For resource content, verify `uri` and `mimeType` are set. Check that tools don't return raw objects or non-content structures.
- **Pass criteria:** All tool handlers return properly structured content arrays with correct type fields. Image and resource content types include required metadata (mimeType, data/uri). 100% of tool returns must specify a valid MCP content type.
- **Fail criteria:** Tool handlers return raw strings instead of content arrays, or content objects have incorrect/missing type fields, or image/resource content lacks required metadata.
- **Skip (N/A) when:** The server registers no tools. All checks skip when no MCP server is detected.

- **Cross-reference:** For resource URI definitions, see `resource-uris`.
- **Detail on fail:** `"Tool 'screenshot' returns image content but mimeType is missing — clients cannot render the image correctly"` or `"Tool 'read_file' returns a raw string instead of a content array with type: 'text'"`
- **Remediation:** Content types tell clients how to render tool results. Use the correct structure:

  ```ts
  // src/tools/search.ts — typed return content
  return { content: [{ type: "text", text: JSON.stringify(results) }] }
  ```

  ```ts
  // Text content
  server.tool('read_file', ..., async ({ path }) => ({
    content: [{ type: 'text', text: await fs.readFile(path, 'utf-8') }]
  }))

  // Image content
  server.tool('screenshot', ..., async () => ({
    content: [{
      type: 'image',
      data: base64Data,
      mimeType: 'image/png',
    }]
  }))

  // Multiple content items
  server.tool('analyze', ..., async ({ path }) => ({
    content: [
      { type: 'text', text: 'Analysis results:' },
      { type: 'text', text: JSON.stringify(results, null, 2) },
    ]
  }))
  ```

## External references

- external mcp-spec-content-types — https://modelcontextprotocol.io/docs/concepts/tools#tool-results

Taxons: inference-contract

HTML version: https://auditbuffet.com/patterns/ab-001830
