The MCP Handbook

Chapter 9: Return Values - From Text to Structured Data

In the early days of MCP, tools returned almost exclusively text. But the protocol has evolved. Today, MCP servers can deliver data in a form that the LLM understands directly as a "data object". In this chapter we take a closer look at this difference.

The Classic Method: TextContent

In the past (and in simple servers still today), the return value of a tool was a plain string. The LLM had to read this text and extract the information by itself.

Example of a classic response:

{
  "content": [
    {
      "type": "text",
      "text": "User Max (ID: 42) has a credit balance of EUR 150.50."
    }
  ]
}

Downside: The model has to "parse" the text. If the text is worded in a complicated way, there is a risk that it extracts the ID or the amount incorrectly.


The Modern Method: StructuredContent

Modern MCP servers use the structuredContent field. Here the data is transmitted as a real JSON object. The LLM receives the information "pure", without distracting prose around it.

Example of a structured response:

{
  "content": [
    { "type": "text", "text": "Here are the user details:" }
  ],
  "structuredContent": {
    "user_id": 42,
    "name": "Max",
    "balance": 150.50,
    "currency": "EUR"
  }
}

Advantage: The model accesses the fields directly. The error rate in further processing of the data (e.g. for a calculation in the next step) drops towards zero.


Implementation in the Go SDK

The official Go SDK supports both worlds. If you use a ToolHandlerFor and return a Go struct, the SDK automatically fills the structuredContent for you.

type UserResponse struct {
    ID      int     `json:"user_id"`
    Name    string  `json:"name"`
    Balance float64 `json:"balance"`
}

// In the handler:
return nil, UserResponse{ID: 42, Name: "Max", Balance: 150.50}, nil

Validation with `mcp-tester`

Our mcp-tester was specifically built to display both formats. When calling a tool via the call command, you see a clear separation:

./bin/mcp-tester call get_user --profile local

The output shows you:

  • Content 0 (Text): The part intended for humans.
  • StructuredContent: The data object intended for the AI.

Through this distinction, as a developer, you can make sure that your server delivers not only "pretty text" for the chat, but also "clean data" for the model's logic.

← Chapter 8: The Tool Trap | Table of Contents | Next Chapter: Binary Data →


Copyright Michael Lechner - 2026-02-28

Licence: CC BY-NC 4.0