Interaction Plugins
Add MCP server and Slack bot surfaces to Atlas via plugins.
Interaction plugins add new surfaces for users to communicate with Atlas beyond the web UI and API.
MCP Server
The MCP interaction plugin wraps the @atlas/mcp server package as an Atlas plugin, managing its lifecycle (initialization, health checks, teardown). It supports two transports: stdio for local tools like Claude Desktop and Cursor, and SSE (Streamable HTTP) for browser-based or remote MCP clients.
Tool bridging and resource registration are handled internally by @atlas/mcp -- this plugin is a thin lifecycle wrapper that makes it configurable via atlas.config.ts.
Prerequisites
@atlas/plugin-mcp-interaction-- the plugin package (workspace dependency)@atlas/mcp-- the underlying MCP server (pulled in automatically via dynamic import)@modelcontextprotocol/sdk-- MCP protocol SDK (required for stdio transport)
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
transport | "stdio" | "sse" | "stdio" | Transport type. stdio communicates via stdin/stdout (JSON-RPC). sse starts a Streamable HTTP server. |
port | number | 8080 | Port for the SSE transport server. Ignored when transport is stdio. |
Usage
import { defineConfig } from "@atlas/api/lib/config";
import { mcpPlugin } from "@atlas/plugin-mcp-interaction";
export default defineConfig({
plugins: [
mcpPlugin({ transport: "stdio" }),
],
});For SSE transport with a custom port:
export default defineConfig({
plugins: [
mcpPlugin({ transport: "sse", port: 9090 }),
],
});Transport modes
stdio -- The default. The MCP server communicates over stdin/stdout using JSON-RPC. Use this when connecting from local tools (Claude Desktop, Cursor, etc.) that launch Atlas as a subprocess. The plugin creates a single StdioServerTransport and connects it during initialize().
SSE -- Starts a standalone HTTP server that accepts Streamable HTTP connections. Use this for browser-based MCP clients or remote access. Each SSE session gets its own MCP server instance, managed internally by @atlas/mcp. The plugin tracks the HTTP server handle for graceful shutdown.
Both transports use dynamic imports to avoid pulling in @atlas/mcp and its transitive dependencies at module evaluation time. The MCP server is only created when initialize() is called.
Slack Bot
The Slack interaction plugin integrates Slack as a full interaction surface for Atlas. Users can ask questions via slash commands (/atlas), continue conversations in threads, approve or deny actions via Block Kit buttons, and install the bot across multiple workspaces via OAuth.
This plugin uses the routes() interface to mount Hono routes directly into the Atlas API server, and receives runtime dependencies (agent execution, conversation persistence, action approval) via config callbacks rather than importing from @atlas/api.
Prerequisites
@atlas/plugin-slack-interaction-- the plugin package (workspace dependency)- A Slack app configured with slash commands and Events API subscriptions
- Either a bot token (single-workspace) or OAuth credentials (multi-workspace)
Configuration
| Option | Type | Required | Description |
|---|---|---|---|
signingSecret | string | Yes | Slack signing secret for request verification. Found in your Slack app's Basic Information page. |
botToken | string | Conditional | Bot token for single-workspace mode (xoxb-...). Required if clientId/clientSecret are not set. |
clientId | string | Conditional | Client ID for multi-workspace OAuth. Required (with clientSecret) if botToken is not set. |
clientSecret | string | Conditional | Client secret for multi-workspace OAuth. Required (with clientId) if botToken is not set. |
executeQuery | function | Yes | Callback that runs the Atlas agent on a question and returns structured results. Signature: (question, options?) => Promise<SlackQueryResult>. |
checkRateLimit | function | No | Optional rate limiting callback. Signature: (key) => { allowed: boolean }. |
conversations | ConversationCallbacks | No | Optional conversation persistence callbacks (create, addMessage, get, generateTitle). |
actions | ActionCallbacks | No | Optional action framework callbacks (approve, deny, get). |
scrubError | function | No | Optional error scrubbing callback to strip sensitive information from error messages. |
Either botToken (single-workspace) or both clientId and clientSecret (multi-workspace OAuth) must be provided. The config schema validates this constraint at factory call time.
Usage
import { defineConfig } from "@atlas/api/lib/config";
import { executeAgentQuery } from "@atlas/api/lib/agent-query";
import { slackPlugin } from "@atlas/plugin-slack-interaction";
export default defineConfig({
plugins: [
slackPlugin({
signingSecret: process.env.SLACK_SIGNING_SECRET!,
botToken: process.env.SLACK_BOT_TOKEN,
executeQuery: executeAgentQuery,
}),
],
});For multi-workspace OAuth with conversation persistence and action approval:
import { defineConfig } from "@atlas/api/lib/config";
import { executeAgentQuery } from "@atlas/api/lib/agent-query";
import { slackPlugin } from "@atlas/plugin-slack-interaction";
export default defineConfig({
plugins: [
slackPlugin({
signingSecret: process.env.SLACK_SIGNING_SECRET!,
clientId: process.env.SLACK_CLIENT_ID!,
clientSecret: process.env.SLACK_CLIENT_SECRET!,
executeQuery: executeAgentQuery,
conversations: myConversationCallbacks,
actions: myActionCallbacks,
}),
],
});Mounted routes
The plugin mounts the following Hono routes under the plugin's base path:
| Method | Path | Description |
|---|---|---|
POST | /commands | Slash command handler (/atlas) |
POST | /events | Slack Events API (thread follow-ups, url_verification) |
POST | /interactions | Block Kit action buttons (approve/deny actions) |
GET | /install | OAuth install redirect (multi-workspace mode) |
GET | /callback | OAuth callback (multi-workspace mode) |
Database schema
The Slack plugin declares two tables that are auto-migrated to the Atlas internal database at boot:
slack_installations-- Stores OAuth installations for multi-workspace mode (team_id,bot_token,installed_at)slack_threads-- Maps Slack threads to Atlas conversations (channel_id,thread_ts,conversation_id)
The executeQuery callback is the bridge between the Slack plugin and the Atlas agent. It receives the user's question and optional prior messages (for threaded conversations), runs the agent, and returns structured results that the plugin formats into Block Kit messages. The host application is responsible for providing this callback -- see executeAgentQuery in @atlas/api/lib/agent-query for the reference implementation.