Plugin

Slack Plugin

Manage your Linux and Windows servers from Slack. Get real-time alerts for everything that happens in ManageLM, and run tasks, scans and fleet searches without leaving your workspace.

Overview

The ManageLM Slack plugin connects your infrastructure to Slack through the same portal API used by the n8n and VS Code integrations, which covers the same features ManageLM gives Claude through MCP. It provides two-way communication:

Features

Real-time Alerts

Agents, tasks, scan reports, monitors, backups, certificates, credentials, keystore, pentests and admin sessions, posted the moment they happen.

Slash Commands

/managelm status, run, task, answer, scan, search. Work on your fleet without opening the portal.

Answer from Slack

When a task needs input, answer it with /managelm answer. Replies stay private, so a password never reaches the channel.

Channel Routing

Route warnings and critical events to #ops-alerts and informational events to #ops-general.

HMAC Verification

Every webhook delivery is signed with HMAC-SHA256 and verified before processing.

Socket Mode

Develop locally with Socket Mode (no public URL required), deploy to production with HTTP.

Architecture

ManageLM Portal ── webhook (HMAC) ──> Slack Plugin ──> Slack API :3100/webhook (notifications) Slack Users ── /managelm ──> Slack Plugin ──> ManageLM Portal API :3100/slack/events (status, run, scan, search)

The plugin serves everything on a single HTTP port (PORT, default 3100):

PathPurpose
/slack/eventsSlack Bolt app: slash commands, interactive buttons, Slack request verification
/webhookManageLM webhook receiver: event notifications from the portal
/healthHealth check

Prerequisites

1. Create a Slack App

Quick method: use the manifest

  1. Go to api.slack.com/apps and click Create New App > From an app manifest

  2. Select your workspace

  3. Paste the manifest below (YAML tab), replacing <YOUR_HOST> with your plugin's public URL

  4. Click Create

manifest.yaml
display_information:
  name: ManageLM
  description: Manage your servers from Slack.

features:
  bot_user:
    display_name: ManageLM
    always_online: true
  slash_commands:
    - command: /managelm
      description: Manage your servers with ManageLM
      usage_hint: status | run <host> <skill> <task> | task <id> | answer <id> <text> | scan <host> <type> | search <kind> [text]

oauth_config:
  scopes:
    bot:
      - chat:write
      - commands
      - views:write

settings:
  interactivity:
    is_enabled: true
    request_url: https://<YOUR_HOST>/slack/events

Manual method

  1. Go to api.slack.com/apps > Create New App > From scratch

  2. Under OAuth & Permissions, add bot scopes: chat:write, commands, views:write

  3. Under Slash Commands, create /managelm with Request URL https://<your-host>/slack/events

  4. Under Interactivity, enable and set Request URL to https://<your-host>/slack/events

After creating the app

  1. Install the app to your workspace

  2. Copy the Bot User OAuth Token (xoxb-...) from OAuth & Permissions

  3. Copy the Signing Secret from Basic Information

Tip: For local development, enable Socket Mode in your app settings and generate an App-Level Token with connections:write scope. This way you don't need a public URL.

2. Create a ManageLM API Key

  1. In the ManageLM portal, go to Settings > MCP & API > API Keys

  2. Create a key and tick the authorizations the bot needs: Reports to start scans, Credentials to search credentials. Only permissions you hold yourself are offered.

  3. Copy the key (mlm_ak_...)

Important: the key acts as the user who created it, limited to the authorizations you ticked, and anyone in the Slack workspace who can reach the bot uses it with that access, in any channel or direct message. Restrict it with SLACK_ALLOWED_USERS and SLACK_ALLOWED_CHANNELS. It sees the servers that user can see. Portal settings and management, such as approving agents, stay in the portal.

3. Configure Environment

Copy the example file and fill in your credentials:

.env
# Slack credentials
SLACK_BOT_TOKEN=xoxb-your-token
SLACK_SIGNING_SECRET=your-signing-secret
# Only for Socket Mode: leave it out for HTTP mode
# SLACK_APP_TOKEN=xapp-your-app-token

# ManageLM
MANAGELM_PORTAL_URL=https://app.managelm.com
MANAGELM_API_KEY=mlm_ak_your-key

# Webhook
# Same secret as on the portal webhook
MANAGELM_WEBHOOK_SECRET=your-webhook-secret
PORT=3100

# Who may use the bot (optional, comma-separated Slack IDs). Unset: anyone in the workspace
SLACK_ALLOWED_USERS=U0123456789,U9876543210
SLACK_ALLOWED_CHANNELS=C0123456789

# Channel routing (optional): warnings and critical events, then all other events
SLACK_CHANNEL_ALERTS=C0123456789
SLACK_CHANNEL_INFO=C9876543210

Self-hosted users: Set MANAGELM_PORTAL_URL to your own portal instance URL instead of app.managelm.com.

4. Register the Webhook

An admin, in the ManageLM portal, goes to Settings > MCP & API > Webhooks and creates a webhook:

FieldValue
URLhttps://<your-host>/webhook
EventsSelect the event categories you want notifications for
SecretSame value as MANAGELM_WEBHOOK_SECRET in your .env

The portal signs every delivery with HMAC-SHA256. The plugin verifies the X-Webhook-Signature header before processing any event.

5. Run the Plugin

Node.js

terminal
npm install
npm run build
node --env-file=.env dist/app.js

Docker

terminal
docker build -t managelm-slack .
docker run --env-file .env -p 3100:3100 managelm-slack

Docker Compose

docker-compose.yml
services:
  managelm-slack:
    build: .
    env_file: .env
    ports:
      - "3100:3100"
    restart: unless-stopped

Health check: Once running, visit http://<your-host>:3100/health to verify the plugin is up. You should see {"status":"ok"}.

Slash Commands

CommandDescription
/managelm statusList all agents with their status, sorted by state
/managelm runOpen a form to pick a server, a skill (or Auto) and an instruction
/managelm run <host> <skill> <instruction>Submit a task inline and get the result in Slack (auto lets the agent pick the skill)
/managelm task <task_id>Show a task's status and result
/managelm answer <task_id> <answer>Answer a task waiting for input. Replies are private.
/managelm scan <host> <type>Start a security, inventory, access, certificates or activity scan
/managelm search <kind> [text]Search agents, inventory, security, activity, monitors, backups, certificates, pki or credentials
/managelm helpShow available commands

Examples

slack
/managelm status
/managelm run web-prod-01 packages List outdated packages
/managelm run lb-01 auto Restart nginx
/managelm scan db-master security
/managelm search security ssh
/managelm search monitors

The run command works like submitting a task from Claude or the portal UI. It sends the instruction to the agent, waits up to 100 seconds for the result, and posts it back to the channel. A longer task is reported as still running, with the command to check it later.

Event Notifications

When a ManageLM webhook event fires, the plugin posts a Block Kit message with the event details and a View in Portal link:

CategoryEvents
Agentagent.enrolled (with a Review in Portal link), agent.approved, agent.online, agent.offline
Tasktask.completed, task.failed, task.needs_input, with a View Details button
Reportreport.completed, report.failed, report.stalled
Monitormonitor.down, monitor.up, monitor.stalled, monitor.created, monitor.deleted
Backupbackup.completed, backup.failed
Certificatecert.issued, cert.renewed, cert.renewal_failed, cert.revoked, cert.reactivated, cert.deleted
Credentialcredential.rotated, credential.rotation_failed
Keystorekeystore.access_denied, keystore.key_deleted
Pentestpentest.completed, pentest.failed
Sessionsconsole.opened, console.closed, desktop.opened, desktop.closed, files.opened

Interactive Buttons

Channel Routing

Route warnings and critical events to a dedicated alerts channel and informational events elsewhere. Alerts are the events the portal itself flags: agent offline, task failed, monitor down or stalled, backup or credential rotation failed, certificate renewal failed or revoked, keystore refusals and deleted keys, failed or stalled reports and pentests, and admin sessions opened.

.env
# Warnings and critical events
SLACK_CHANNEL_ALERTS=C0123456789
# All other events
SLACK_CHANNEL_INFO=C9876543210

If only one variable is set, every event goes to that channel. Make sure to invite the bot to the target channels. With neither set, the result of a task started from the run form comes to you as a direct message.

Finding channel IDs: Right-click a channel in Slack > View channel details > scroll to the bottom to find the Channel ID (starts with C).

Environment Reference

VariableRequiredDescription
SLACK_BOT_TOKENYesBot OAuth token (xoxb-...)
SLACK_SIGNING_SECRETYesSlack app signing secret
SLACK_APP_TOKENNoApp-level token for Socket Mode (xapp-...)
MANAGELM_PORTAL_URLYesManageLM portal URL
MANAGELM_API_KEYYesManageLM API key (mlm_ak_...)
MANAGELM_WEBHOOK_SECRETFor notificationsHMAC secret for webhook verification. Without it, /webhook rejects every delivery.
MANAGELM_PORTAL_PUBLIC_URLNoPublic URL for "View in Portal" links
PORTNoHTTP port for Slack events, the webhook and the health check (default: 3100)
SLACK_CHANNEL_ALERTSNoChannel ID for alert events
SLACK_CHANNEL_INFONoChannel ID for informational events
SLACK_ALLOWED_USERSNoComma-separated Slack user IDs allowed to use the bot. Unset: anyone in the workspace
SLACK_ALLOWED_CHANNELSNoComma-separated channel IDs the bot answers in. Unset: every channel and direct message

Security

Troubleshooting

Slash command returns "dispatch_failed"

Slack cannot reach your plugin. Verify your Request URL in the Slack app settings points to https://<your-host>/slack/events and the plugin is running. For local development, use Socket Mode instead.

No notifications appear in Slack

401 Invalid signature on webhooks

The MANAGELM_WEBHOOK_SECRET in your .env does not match the secret configured on the webhook in the portal. Update one to match the other. A delivery is also refused when the plugin host's clock is more than 5 minutes off: keep it synchronized (NTP).

Agent not found when using /managelm run

The name you typed doesn't exactly match an agent the key can see. The plugin matches the full hostname or display_name (case does not matter) and never guesses from a partial name: it suggests close matches instead. Use /managelm status to see exact names.

Permission denied

The key lacks an authorization the command needs (for example Reports for scan, Credentials for search credentials), or the key's creator cannot access that server. Create a key with the right authorizations.

Task still running

The task took longer than 100 seconds. It keeps running on the agent: check it with /managelm task <task_id>, or subscribe the webhook to task events to be notified when it finishes.