@maheidem/pi-slack

Pi extension: Slack with a consistent, scriptable control-panel UX.

Packages

Package details

extensionskillprompt

Install @maheidem/pi-slack from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@maheidem/pi-slack
Package
@maheidem/pi-slack
Version
0.2.1
Published
Sep 11, 2026
Downloads
290/mo · 290/wk
Author
marcos-heidemann
License
MIT
Types
extension, skill, prompt
Size
319.1 KB
Dependencies
0 dependencies · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/index.ts"
  ],
  "skills": [
    "./skills"
  ],
  "prompts": [
    "./prompts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-slack

Pi extension for Slack, backed by the official Slack MCP server. After a one-time browser login it registers the server's 27 tools verbatim as slack_* Pi tools, plus five extension-owned companion tools backed by the Slack Web API (same token) for what the MCP catalog lacks: unread state, mark-read, message edit/delete, and name→ID resolution. A scriptable control panel (/slack) covers status, settings, and session management.

Two surfaces, one login

  1. MCP surface (27 tools)https://mcp.slack.com/mcp, registered verbatim from the server's tools/list (names, descriptions, schemas).
  2. Web API surface (5 companion tools) — direct https://slack.com/api/* calls with the same user token, added by the extension itself (v0.2.1): Slack's hosted MCP catalog has no read-state, message-edit, or message-delete tool, and the granted OAuth scopes already cover those Web API methods. All companion calls go through the same queue/refresh/retry discipline as MCP calls.

Install

pi install npm:@maheidem/pi-slack@0.2.1
# then /reload in any running session

Requires a Pi settings entry (packages) pointing at the installed package — pi install handles that.

Login

/slack login

Opens the Slack browser OAuth flow (PKCE, user token). A localhost callback on port 3118 (configurable) completes it; no code is pasted by hand. When the browser can't open, /slack login prints the authorize URL for manual use.

Tokens are user tokens (xoxe.xoxp-…) with a lifetime of roughly 12 hours; the extension refreshes them proactively before expiry and reactively (single refresh + retry) if the server rejects one mid-session. When the refresh itself fails, the state becomes degraded and tools stop with a clear "run /slack login again" message.

/slack logout [--yes] drops the local tokens and clears the cached tool catalog (the confirmation is required in non-TUI mode via --yes).

Config

Everything lives in ~/.pi/agent/slack.json (created on first load, mode 0600 — it holds OAuth tokens). Override the location with the PI_SLACK_CONFIG environment variable.

  • serverUrl — default https://mcp.slack.com/mcp
  • clientId — shipped default; change only if you register your own Slack app
  • redirectPort — localhost OAuth callback port (default 3118)
  • loginTimeoutMs, requestTimeoutMs, maxResultChars, queueLimit
  • enabledTools — empty = all 27 catalog tools; a comma list restricts registration (the 5 companion tools are never gated by it)

Inspect with /slack config get (values via /slack config set <field> <value>), or /slack doctor for full diagnostics.

Usage

/slack                    control panel (TUI) / status (print mode)
/slack status             connection + queue + catalog status
/slack login              browser OAuth flow
/slack logout [--yes]     drop tokens (confirm in TUI)
/slack test               initialize handshake + tools/list probe
/slack doctor             diagnostics incl. quarantine + version
/slack tools list         cached catalog tool names
/slack tools refresh      re-fetch tools/list now
/slack unread             unread summary (Web API scan)
/slack config get|set|reset
/slack paths              config file location
/slack help

The 27 tools

slack_add_list_record, slack_add_reaction, slack_complete_file_upload, slack_create_canvas, slack_create_conversation, slack_create_list, slack_get_file_upload_url, slack_get_reactions, slack_list_channel_members, slack_list_user_channels, slack_read_canvas, slack_read_channel, slack_read_file, slack_read_list, slack_read_thread, slack_read_user_profile, slack_schedule_message, slack_search_channels, slack_search_emojis, slack_search_public, slack_search_public_and_private, slack_search_users, slack_send_message, slack_send_message_draft, slack_update_canvas, slack_update_list, slack_update_list_record

Names are registered verbatim as the server reports them; a stale cached catalog is refreshed in the background at session start.

The 5 companion tools (extension-provided, Slack Web API)

slack_unread_summary — unread counts per conversation (DMs, group DMs, public/private channels), excluding your own messages; bounded scan (20 s deadline, 300 conversations). slack_mark_read — move a conversation's read position (ts defaults to its latest message). slack_edit_message / slack_delete_message — edit/delete your own messages (Slack enforces this for user tokens). slack_resolve_channel — resolve a channel name or query to channel IDs (top 5 ranked matches) before sending.

Companion tools register/unregister with the same lifecycle as catalog tools: logged-out sessions expose zero slack_* tools total.

Sending messages

slack_send_message requires a channel_id (e.g. C0123456789), not a channel name. Resolve names first:

  • slack_search_channels (public) / slack_search_public_and_private
  • slack_list_user_channels for the channels you're already in

Attachments use the slack_get_file_upload_url → upload → slack_complete_file_upload pair.

Development

npm test          # offline: fake MCP server on 127.0.0.1
npm run typecheck

Source of truth: extensions/ (adapter index.ts, application.ts, config.ts, domain/, vendored ui/). Tests in tests/ include the frozen 27-name parity set and a tarball-integrity gate for the files allowlist.