Returning rich responses to the Slackbot MCP Client
To check if you have access to this feature, go to App Settings. For any app, look for an MCP Servers label in the left sidebar under Features.
MCP servers can return rich, interactive UI in one way (for now):
MCP Apps (interactive UI)
MCP Apps are rich, interactive UI experiences returned by MCP servers. Instead of returning plain text that Slackbot renders as a conversational response, your tools can return full interactive interfaces (dashboards, forms, approval flows) that render natively in Slack.
When an MCP tool returns a response containing a _meta.ui.resourceUri field, Slack detects this and renders the UI resource as an interactive block:
- A tool is called by Slackbot based on the user's prompt.
- The tool returns data plus a
_meta.ui.resourceUripointing to a UI resource. - Slack fetches the UI resource (HTML/JS) from that URI.
- The content is rendered as an interactive block in the conversation.
Example response
{
"content": [
{
"type": "text",
"text": "You have 4 pending tasks"
}
],
"_meta": {
"ui": {
"resourceUri": "ui://acme/task-dashboard"
}
}
}
The content field provides a text fallback, while _meta.ui.resourceUri tells Slack where to fetch the interactive UI.
Integration types
| Integration type | Tool returns | User experience |
|---|---|---|
| Client-only (e.g., tool search, data lookup) | Plain data/text | Conversational text response |
| Apps-only (e.g., dashboards, analytics) | Data + resourceUri | Rich interactive UI |
| Combined | Either, depending on context | Both conversational and rich UI |
Your app can support any combination; some tools return plain text while others return interactive UI.
MCP server example
This is an example of an MCP server returning a rich response. The MCP server registers a dice roller tool and serves an interactive HTML resource that renders the result inside Slack. The /mcp route verifies the Slack request signature before forwarding the request to the MCP transport.
The tool uses the readOnlyHint annotation to indicate it doesn't modify any state, and returns structuredContent so the UI resource can render the roll visually.
The examples below use Bolt for JavaScript and Bolt for Python.
- JavaScript
- Python
loading...
loading...
UI resource
When Slackbot invokes the roll_dice tool, it renders this HTML inside an iframe. The page connects to the MCP Apps runtime and displays the structured result visually.
loading...
Entry point
Start the server on the configured port. Bolt handles the Slack events route automatically, while the custom /mcp route serves your MCP server.
- JavaScript
- Python
loading...
loading...