---
title: 'Feedback MCP Server'
description: 'Give your own AI agent a submit_feedback tool'
slug: api/feedback/mcp-server
---

The feedback MCP server at `https://mcp.modem.dev/feedback` lets an AI agent inside your product send feedback to your Modem [feedback channel](/docs/integrations/in-app-feedback#feedback-channels). It has one tool, `submit_feedback`, and no state. Use it when your app has its own assistant and you want that assistant to report the tools that fail it and the requests it cannot meet.

:::info
This is not the [Modem MCP Server](/docs/api/modem-mcp-server) at `https://mcp.modem.dev/mcp`. That server is for people and agents working
with your Modem workspace, and it authorizes with OAuth. The feedback server is for your product's end users, and it authorizes with a
feedback token that is safe to ship.
:::

## Connecting

Add the server to your agent's MCP configuration with the channel's feedback token as a bearer header. The server speaks Streamable HTTP and accepts only `POST`.

```json
{
    "url": "https://mcp.modem.dev/feedback",
    "headers": {
        "Authorization": "Bearer <feedback token>",
        "X-Modem-App-User": "{\"id\":\"usr_8213\",\"name\":\"Ada Lovelace\",\"email\":\"ada@example.com\"}",
        "X-Modem-App-Context": "{\"session_id\":\"sess_41\",\"client\":\"acme-assistant\",\"client_version\":\"2.14.0\",\"release\":\"2.14.0\",\"environment\":\"production\"}"
    }
}
```

The server checks only the token's shape when a connection opens. Whether the token is live is decided when a report is submitted, so a revoked token shows up as a failed `submit_feedback` call, not a failed connection.

Both extra headers belong to the connection, not to a tool call. Open one MCP client per user session, with both headers set for that session, rather than sharing one client across users.

## Headers

### X-Modem-App-User

Names the signed-in user so the agent never asks for a name or email. With this header set, `submit_feedback` has no `name` or `email` inputs, and Modem records the reporter as a claimed identity keyed by your user ID.

| Field   | Type   | Required | Description                                      |
| ------- | ------ | -------- | ------------------------------------------------ |
| `id`    | string | Yes      | Your app's ID for the user, 1 to 128 characters. |
| `name`  | string | No       | Up to 256 characters.                            |
| `email` | string | No       | Up to 320 characters.                            |

### X-Modem-App-Context

What your runtime knows about the session. Every field is optional. Modem attaches it to every report from the connection, and the agent cannot change it.

| Field            | Type   | Description                                                                                                                                                                   |
| ---------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `session_id`     | string | 1 to 128 characters.                                                                                                                                                          |
| `client`         | string | Your agent's name, 1 to 100 characters.                                                                                                                                       |
| `client_version` | string | 1 to 50 characters.                                                                                                                                                           |
| `release`        | string | Your app's version, 1 to 200 characters.                                                                                                                                      |
| `environment`    | string | 1 to 64 characters.                                                                                                                                                           |
| `tags`           | object | Up to 10 labels. Keys 1 to 32 characters, values 1 to 200. The keys `category`, `session_id`, `client`, `client_version`, `mcp_protocol_version`, and `country` are reserved. |

### Encoding

Send each header as a JSON string. When a value contains characters outside ASCII, percent-encode the whole JSON with `encodeURIComponent`; the server tries raw JSON first, then decodes. A header that fails to parse gets `400` with the reason, before any MCP handling.

## The submit_feedback tool

The tool's description tells the agent when to offer a report and when to send one. It offers when one of your app's tools fails, returns something the agent cannot act on, needs a capability the app lacks, or gives an unclear error, and when the user voices feedback or frustration or asks for something the app cannot do. It sends only when the user asks to or agrees, and tells them what it sent.

### Parameters

| Parameter  | Type   | Required | Description                                                                                                                          |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `message`  | string | Yes      | What the agent tried, what happened, and what it expected. 1 to 4,096 characters.                                                    |
| `category` | string | No       | `agent_friction` for the agent's own report of a failing tool, or `user_feedback` for the user's words. Defaults to `user_feedback`. |
| `name`     | string | No       | The reporter's name, up to 256 characters. Absent when `X-Modem-App-User` is set.                                                    |
| `email`    | string | No       | The reporter's email, up to 320 characters. Absent when `X-Modem-App-User` is set.                                                   |
| `url`      | string | No       | The page the report is about. `http` or `https`, up to 2,048 characters.                                                             |
| `trace_id` | string | No       | A trace ID, 1 to 128 characters.                                                                                                     |
| `release`  | string | No       | Your app's version, 1 to 200 characters.                                                                                             |
| `tags`     | object | No       | Up to 20 labels. For a failing tool, send `tool_name` and `error`.                                                                   |
| `context`  | object | No       | What the agent was attempting. At most 8,192 characters when serialized.                                                             |

Modem adds tags of its own to every report: `session_id`, `client`, and `client_version` from your context header, the MCP protocol version, and the connection's country. It also records the user agent. Values the server attaches win over the agent's input, and the total stays within the 20-tag limit.

### Result

On success the tool returns `Feedback sent (id …)` with the feedback event's ID in `structuredContent.id`. On failure it returns an MCP tool error rather than throwing. For a rejected submission the text is the endpoint's own error, such as `Invalid or inactive feedback token`. Otherwise it is `Feedback could not be sent. Please try again later.`

The tool takes no `submission_id`, so every call creates a new submission. Let the agent call it once per report.

### Example call

```json
{
    "message": "create_export failed with a 504 while exporting the Northwind workspace to CSV. Expected a download link.",
    "category": "agent_friction",
    "tags": { "tool_name": "create_export", "error": "504 upstream timeout" },
    "context": { "attempting": "exporting 12,400 topics to CSV" },
    "release": "2.14.0"
}
```

## Related

**[In-app Feedback](/docs/integrations/in-app-feedback)**

Channels, tokens, and what happens to a submission.

**[Feedback endpoint](/docs/api/feedback/endpoint)**

The HTTP endpoint the tool calls, with its limits and responses.

**[Modem MCP Server](/docs/api/modem-mcp-server)**

The OAuth server for working with your Modem workspace.
