<div align="center">
<img src="image.png" alt="pumble-mcp — Full Pumble Platform Access for AI Agents" width="100%"/>
<br/>
     
A standalone MCP server that gives AI agents complete access to the Pumble messaging platform.<br/> Built on the official Pumble SDK and the Model Context Protocol.
Getting Started · Tools · Real-Time Events · Architecture · Configuration · Development
</div>
---
Why pumble-mcp?
The existing Pumble MCP server wraps ~8 API endpoints with API-key auth. It can't touch files, receive events, manage channels, search messages, or schedule anything.
pumble-mcp exposes the entire platform — 33 tools across messaging, files, channels, users, search, scheduling, and real-time events — using OAuth2 and the full Pumble SDK for capabilities the REST API alone cannot provide.
| Capability | Existing MCP | pumble-mcp | |---|:---:|:---:| | Messages (send, read, edit, delete, threads) | Partial | Full | | File operations (upload, download, list) | — | SDK-exclusive | | Real-time events (subscribe, poll) | — | WebSocket | | Channel management (create, add/remove members) | — | Full | | Search with text/channel/user/date filters | — | Full | | Scheduled messages (create, edit, cancel) | — | Full | | User status and groups | — | Full | | HTTP transport for N8N / webhooks | — | Streamable HTTP | | Auth model | API key | OAuth2 | | Total tools | ~8 | 33 |
---
Getting Started
Prerequisites
- Node.js 22+ (LTS)
- A Pumble workspace where you have admin access
1. Clone and install
git clone https://github.com/nitindermohan/pumble-mcp.git
cd pumble-mcp
npm install
2. Register a Pumble app
npx pumble-cli login # Authenticate with your Pumble account
npx pumble-cli create # Register a new bot app
This creates .pumbleapprc with your app credentials (APP_ID, APP_KEY, CLIENT_SECRET, SIGNING_SECRET).
3. Configure environment
cp .env.example .env
Fill in the credentials from .pumbleapprc:
PUMBLE_APP_ID=your_app_id
PUMBLE_APP_KEY=your_app_key
PUMBLE_APP_CLIENT_SECRET=your_client_secret
PUMBLE_APP_SIGNING_SECRET=your_signing_secret
4. Authorize and register events
Run once via pumble-cli to authorize the bot in your workspace and push event subscriptions to Pumble's platform:
npx pumble-cli
Wait for Websocket connected and App is updated, then Ctrl+C.
5. Build and run
npm run build
node dist/index.js
6. Connect to your AI client
<details> <summary><strong>Claude Code</strong></summary>
Add to .mcp.json in your project root:
{
"mcpServers": {
"pumble": {
"command": "node",
"args": ["dist/index.js"],
"cwd": "/path/to/pumble-mcp"
}
}
}
</details>
<details> <summary><strong>Claude Desktop</strong></summary>
Add to claude_desktop_config.json:
{
"mcpServers": {
"pumble": {
"command": "node",
"args": ["/absolute/path/to/pumble-mcp/dist/index.js"],
"cwd": "/absolute/path/to/pumble-mcp"
}
}
}
</details>
<details> <summary><strong>N8N (HTTP transport)</strong></summary>
Set MCP_TRANSPORT=http (or both) in .env, optionally set MCP_BEARER_TOKEN, then point N8N's HTTP Request node at:
POST http://localhost:3456/mcp
Authorization: Bearer YOUR_TOKEN
</details>
---
🔧 Tools
Messaging — Read, write, and manage messages across channels and threads
| Tool | Description | |------|-------------| | pumble_send_message | Send a message to a channel. Accepts #channel-name or channel ID. | | pumble_reply_message | Reply to a specific message in a thread. | | pumble_list_messages | List recent messages in a channel with cursor-based pagination. | | pumble_get_message | Fetch a single message by its timestamp ID. | | pumble_get_thread_replies | Fetch all replies in a message thread. | | pumble_edit_message | Edit a message the bot previously sent. | | pumble_delete_message | Delete a message the bot previously sent. |
Direct Messages — Private conversations with individuals or groups
| Tool | Description | |------|-------------| | pumble_send_dm | Send a direct message to a user. Accepts email address or user ID. | | pumble_send_group_dm | Send a group DM to multiple users at once. |
Channels — Create and manage workspace channels
| Tool | Description | |------|-------------| | pumble_list_channels | List all channels the bot belongs to, with pagination. | | pumble_get_channel | Get channel details by #name or ID. | | pumble_create_channel | Create a new PUBLIC or PRIVATE channel. | | pumble_add_channel_members | Add one or more users to a channel. | | pumble_remove_channel_member | Remove a user from a channel. |
Users — Workspace user information and bot identity
| Tool | Description | |------|-------------| | pumble_list_users | List all users in the workspace with roles and status. | | pumble_get_bot_identity | Get the bot's own user ID, display name, and workspace info. | | pumble_list_user_groups | List user groups and their members. | | pumble_set_status | Set the bot's custom status with emoji, text, and optional expiration. |
Reactions — Emoji reactions on messages
| Tool | Description | |------|-------------| | pumble_add_reaction | Add an emoji reaction (e.g. :thumbsup:) to any message. | | pumble_remove_reaction | Remove a previously added emoji reaction. |
Files — Upload, download, and browse files (SDK-exclusive)
| Tool | Description | |------|-------------| | pumble_upload_file | Upload a file (base64-encoded) to a channel with an optional message. | | pumble_download_file | Download a file by URL and return its base64 content. | | pumble_list_files | List files shared in a channel. |
Note: File operations are only available through the Pumble SDK with OAuth2 auth. The REST API alone does not expose file endpoints.
Search — Find messages across the workspace
| Tool | Description | |------|-------------| | pumble_search_messages | Full-text search with filters for channel, user, date range, and pagination. |
Scheduled Messages — Send messages at a future time
| Tool | Description | |------|-------------| | pumble_create_scheduled_message | Schedule a message for future delivery to any channel. | | pumble_list_scheduled_messages | List all pending scheduled messages. | | pumble_edit_scheduled_message | Edit the content or timing of a pending scheduled message. | | pumble_delete_scheduled_message | Cancel a scheduled message before it sends. |
Real-Time Events — Subscribe and poll for live workspace activity
| Tool | Description | |------|-------------| | pumble_subscribe_events | Subscribe to one or more event types. Returns a subscription ID for polling. | | pumble_poll_events | Poll for events buffered since the last poll for a given subscription. | | pumble_list_subscriptions | List all active event subscriptions with their types and cursor positions. | | pumble_unsubscribe_events | Remove a subscription and stop buffering its events. |
System
| Tool | Description | |------|-------------| | pumble_health_check | Check server version, auth status, workspace name, and connection health. |
---
📡 Real-Time Events
pumble-mcp connects to Pumble via socket mode WebSocket and buffers incoming events in an in-memory ring buffer (1000 events, oldest evicted first). AI agents subscribe to event types and poll for new events at their own pace — no push endpoint or public URL required.
AI Agent pumble-mcp Pumble
│ │ │
│── subscribe(NEW_MESSAGE) ─▶│ │
│◀── subscription_id ───────│ │
│ │◀── WebSocket: NEW_MESSAGE ──│
│ │ (buffered in EventStore) │
│── poll(subscription_id) ──▶│ │
│◀── [event1, event2] ──────│ │
Supported event types:
| Event | Triggered when... | |-------|-------------------| | NEW_MESSAGE | A message is posted in any channel the bot belongs to | | UPDATED_MESSAGE | A message is edited | | REACTION_ADDED | Someone adds an emoji reaction to a message | | CHANNEL_CREATED | A new channel is created in the workspace | | APP_UNINSTALLED | The bot app is uninstalled from the workspace | | APP_UNAUTHORIZED | A user revokes the bot's authorization | | WORKSPACE_USER_JOINED | A new user joins the workspace |
Example flow:
// 1. Subscribe to events
pumble_subscribe_events({ event_types: ["NEW_MESSAGE", "REACTION_ADDED"] })
// → { subscription_id: "sub_a1b2c3d4", event_types: [...] }
// 2. Poll periodically
pumble_poll_events({ subscription_id: "sub_a1b2c3d4" })
// → { events: [{ eventType: "NEW_MESSAGE", payload: {...}, ... }], count: 3 }
// 3. Unsubscribe when done
pumble_unsubscribe_events({ subscription_id: "sub_a1b2c3d4" })
// → { unsubscribed: true }
---
Architecture
┌──────────────────────────────────────────────┐
│ pumble-mcp │
│ │
Claude/CLI ──stdio──▶ McpServer ──▶ 33 Tools ──▶ PumbleClient ──▶── Pumble API
│ │ │ │
N8N/HTTP ───http──▶ McpServer EventStore ◀── SDK WebSocket ◀─── Pumble Events
│ (ring buffer) │
└──────────────────────────────────────────────┘
Key design decisions:
- Dual transport — stdio for Claude Desktop/Code, Streamable HTTP for N8N and remote consumers. Same 33 tools on both.
- EventStore singleton — One ring buffer shared across all transports. Subscribe on stdio, poll from HTTP — it just works.
- Socket mode — The Pumble SDK handles WebSocket connection, ping/pong keepalive, message ack, and automatic reconnection. No public URL or tunnel needed.
- stderr-only logging — stdout is reserved exclusively for MCP JSON-RPC. The Pumble SDK's internal
console.logcalls are redirected to stderr at process start. - OAuth2 with token mutex — Concurrent API calls serialize through a mutex to prevent race conditions on single-use refresh tokens.
---
Customizing the Bot Identity
Edit manifest.json to change how the bot appears in your Pumble workspace:
{
"name": "my-custom-bot",
"displayName": "My Custom Bot",
"botTitle": "Team Assistant"
}
Then sync to Pumble:
npx pumble-cli # Pushes manifest changes to Pumble
# Wait for "App is updated", then Ctrl+C
---
Configuration
Environment Variables
| Variable | Required | Default | Description | |----------|:--------:|---------|-------------| | PUMBLE_APP_ID | Yes | — | App ID from .pumbleapprc | | PUMBLE_APP_KEY | Yes | — | App key for WebSocket authentication | | PUMBLE_APP_CLIENT_SECRET | Yes | — | OAuth2 client secret | | PUMBLE_APP_SIGNING_SECRET | Yes | — | Request signature verification secret | | PUMBLE_TOKEN_STORE_PATH | No | .pumble-tokens.json | Path to OAuth2 token storage | | MCP_TRANSPORT | No | stdio | Transport mode: stdio, http, or both | | MCP_HTTP_PORT | No | 3456 | Port for HTTP transport | | MCP_BEARER_TOKEN | No | — | Bearer token for HTTP transport auth (strongly recommended) | | LOG_LEVEL | No | info | Logging verbosity: error, info, debug |
Required Bot Scopes
These scopes are configured in manifest.json and registered during app creation:
messages:read messages:write messages:edit messages:delete
channels:list channels:read channels:write
users:list user:read
reaction:read reaction:write
workspace:read files:write attachments:write status:write
---
Development
npm run dev # Run with tsx (hot reload)
npm run build # Compile TypeScript
npm test # Run all 175 tests
npm run test:watch # Watch mode
npm run test:coverage # Code coverage report
npm run typecheck # Type check without emitting
Testing
| Suite | Tests | Coverage | |-------|------:|----------| | Unit | 39 | EventStore, event listeners, auth, config, logger | | Integration | 128 | All 33 tools via in-process MCP server + InMemoryTransport | | Live | 8 | End-to-end against a real Pumble workspace |
npm test # Unit + integration (no network)
npx tsx tests/live/run-live-tests.ts # Live tests (requires credentials)
Project Structure
src/
index.ts Entry point — boot sequence, console.log redirect
server.ts MCP server setup (stdio + Streamable HTTP transports)
config.ts Environment validation with Zod schemas
logger.ts stderr-only logger (stdout reserved for MCP JSON-RPC)
main.ts pumble-cli entry point for event registration
pumble/
auth.ts OAuth2 setup, token mutex, SDK event handler wiring
client.ts PumbleClient — unified wrapper for all SDK operations
resolvers.ts Smart resolution: #channel-name → ID, email → user ID
events/
event-store.ts Ring buffer (1000 capacity) with subscription-cursor polling
event-listeners.ts Bridges SDK event callbacks → EventStore.push()
tools/
index.ts Tool registration hub (routes to all modules below)
health.ts pumble_health_check
channels.ts 5 channel management tools
users.ts 4 user and bot identity tools
messages.ts 5 message read tools
messages-mutate.ts 2 message write tools (edit, delete)
reactions.ts 2 reaction tools
dms.ts 2 direct message tools
files.ts 3 file operation tools (SDK-exclusive)
search.ts 1 search tool with multi-filter support
scheduled.ts 4 scheduled message tools
events.ts 4 real-time event subscription tools
tests/
setup.ts Mock PumbleClient and EventStore factories
unit/ Pure logic tests — no network, no SDK
integration/ Full MCP pipeline tests via InMemoryTransport
live/ Real Pumble workspace end-to-end tests
---
Tech Stack
| Component | Technology | Version | |-----------|------------|---------| | Runtime | Node.js | 22 LTS | | Language | TypeScript | 5.9 | | MCP Protocol | @modelcontextprotocol/sdk | 1.29.x | | Pumble Platform | pumble-sdk | 1.1.x | | HTTP Transport | Express + @modelcontextprotocol/express | 4.x | | Schema Validation | Zod | 4.x | | Testing | Vitest | 4.x | | Auth | OAuth2 via pumble-cli | — |
---
Disclaimer
This project was largely vibe-coded with Claude Code (Anthropic's AI coding agent). The entire development lifecycle — architecture, implementation, testing, debugging, and documentation — was driven through conversational AI-assisted development. All code was reviewed, tested (175 automated tests), and validated against a live Pumble workspace.
---






