Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "msp-claude-plugins",
"description": "Community-driven Claude Code plugins for Managed Service Providers. Integrates with PSA, RMM, and documentation tools.",
"version": "1.10.0",
"version": "1.11.0",
"owner": {
"name": "Aaron Sachs"
},
Expand Down Expand Up @@ -800,7 +800,7 @@
"name": "stripe",
"source": "./msp-claude-plugins/stripe/stripe",
"description": "Stripe - payments, subscriptions, invoices, customer management via Stripe's first-party hosted MCP (mcp.stripe.com)",
"version": "0.1.0",
"version": "0.2.0",
"category": "accounting",
"tags": [
"stripe",
Expand All @@ -814,7 +814,7 @@
"name": "slack",
"source": "./msp-claude-plugins/slack/slack",
"description": "Slack - messages, channels, canvases, files, reactions via Slack's first-party hosted MCP (mcp.slack.com)",
"version": "0.1.0",
"version": "0.2.0",
"category": "productivity",
"tags": [
"slack",
Expand Down
66 changes: 66 additions & 0 deletions msp-claude-plugins/docs/src/data/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,72 @@ export const plugins: Plugin[] = [
},
path: 'azure-mcp/azure-mcp',
compatibility: { claudeCode: true, claudeDesktop: true, validated: false }
},
{
id: 'stripe',
name: 'Stripe',
vendor: 'Stripe',
description: 'Stripe - payments, subscriptions, invoices, customer management via Stripe\'s first-party hosted MCP (mcp.stripe.com)',
category: 'accounting',
maturity: 'beta',
features: [
'Disputes',
'Payment Tracking',
'Subscription Lifecycle'
],
skills: [
{ name: 'disputes', description: 'Use this skill for Stripe disputes (chargebacks): listing open disputes and their deadlines, reading the dispute reason and what evidence Stripe needs, assembling and submitting evidence, and tracking dispute outcomes.' },
{ name: 'payments', description: 'Use this skill for Stripe payment operations: looking up payment intents and charges, tracing a customer\'s payment history, issuing and tracking refunds, and reading account balance and payout status.' },
{ name: 'subscriptions', description: 'Use this skill for Stripe recurring-billing operations: inspecting products and prices, auditing a customer\'s subscriptions (plan, status, renewal, trial), changing or canceling subscriptions, and walking the invoice lifecycle (draft → open → paid → void/uncollectible) including line items and failed-payment dunning.' }
],
agents: [
{ name: 'stripe-billing-support', description: 'Use this agent for Stripe billing-support and revenue-operations work: investigating a customer\'s payments and subscription state, issuing and tracking refunds, triaging chargebacks/disputes against their deadlines, and reconciling balance/payouts.' }
],
commands: [
{ name: '/dispute-triage', description: 'Triage open Stripe disputes by evidence deadline (soonest first)' },
{ name: '/subscription-audit', description: 'Audit a customer\'s Stripe subscription + billing health (plan, status, renewal, dunning)' }
],
apiInfo: {
baseUrl: '',
auth: '',
rateLimit: '',
docsUrl: ''
},
path: 'stripe/stripe',
compatibility: { claudeCode: true, claudeDesktop: true, validated: false }
},
{
id: 'slack',
name: 'Slack',
vendor: 'Slack',
description: 'Slack - messages, channels, canvases, files, reactions via Slack\'s first-party hosted MCP (mcp.slack.com)',
category: 'productivity',
maturity: 'beta',
features: [
'Channels Users',
'Messaging',
'Threads Reactions'
],
skills: [
{ name: 'channels-users', description: 'Use this skill to resolve and inspect Slack channels and users: listing channels, resolving a #channel name to its id, reading channel membership/topic/purpose, and looking up users by id or email to get their name, handle, and profile.' },
{ name: 'messaging', description: 'Use this skill to read and write Slack messages: posting a message to a channel or thread, reading recent channel history, and searching across the workspace for messages by keyword, user, channel, or date.' },
{ name: 'threads-reactions', description: 'Use this skill for Slack thread and reaction operations: reading a full thread by its parent message, replying in-thread, and adding/reading emoji reactions (acknowledgements, status signals, lightweight workflow state).' }
],
agents: [
{ name: 'slack-workspace-assistant', description: 'Use this agent for Slack workspace operations: searching and summarizing discussions, posting updates and announcements to the right channel/thread, resolving people and channels by name/email, reading thread context, and using reactions as acknowledgements.' }
],
commands: [
{ name: '/channel-digest', description: 'Summarize a Slack channel\'s recent activity into decisions, action items, and open questions' },
{ name: '/find-discussions', description: 'Find Slack discussions about a topic using search operators, with context and permalinks' }
],
apiInfo: {
baseUrl: '',
auth: '',
rateLimit: '',
docsUrl: ''
},
path: 'slack/slack',
compatibility: { claudeCode: true, claudeDesktop: true, validated: false }
}
];

Expand Down
2 changes: 1 addition & 1 deletion msp-claude-plugins/slack/slack/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "slack",
"version": "0.1.0",
"version": "0.2.0",
"description": "Claude plugins for Slack — messages, channels, canvases, files, reactions via Slack's first-party hosted MCP server (mcp.slack.com)",
"author": {
"name": "MSP Claude Plugins Community"
Expand Down
24 changes: 22 additions & 2 deletions msp-claude-plugins/slack/slack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,29 @@ Slack does NOT support RFC 7591 Dynamic Client Registration. Each operator must

Each tenant authorizes their own Slack workspace through the gateway's OAuth flow using the operator-provisioned app.

## Status
## What this plugin provides

**Scaffold-only.** Marketplace registration + connection wiring; WYRE-authored skill/agent/command content deliberately empty for follow-up.
WYRE-authored skill / agent / command content (strong first pass, 2026-06-13):

**Skills**
- `messaging` — read channel history, search the workspace with operators, post messages + thread replies.
- `channels-users` — resolve `#name`→id and email/id→user; read membership + metadata (the lookup layer).
- `threads-reactions` — read/reply within threads; reactions as acknowledgement / status signals.

**Agent**
- `slack-workspace-assistant` — workspace-ops persona: resolve-then-act, posting restraint, threaded by default.

**Commands**
- `/channel-digest <channel>` — summarize a channel into decisions / action items / open questions.
- `/find-discussions <query>` — locate where a topic was discussed, with context + permalinks.

The hosted Slack MCP server serves the actual tools through the connection; this content is a guidance/enhancement layer, not a prerequisite for tool access. Tool names referenced are the gateway-prefixed `slack__*` form — confirm exact names against a live `tools/list` once connected. A tool failing with a scope error means that user-token scope wasn't enabled on the operator's Slack app.

**Deferred (follow-up):** a canvases skill + a files skill (the scaffold README lists both surfaces), more commands (e.g. `/post-update`, `/user-lookup`), and exact tool-name verification against the live hosted server (authored without live credentials).

## Conduit relevance

**YES (data layer).** This new plugin content regenerates `docs/src/data/plugins.ts`, and conduit's white-label docs `public/` is built from this Astro source at CI time (per `conduit/docs/white-label.md`). So these plugin pages propagate to conduit's white-label docs — flagged for the conduit digest. (Determined read-only, 2026-06-13.)

## See also

Expand Down
Empty file.
26 changes: 26 additions & 0 deletions msp-claude-plugins/slack/slack/agents/workspace-assistant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
name: slack-workspace-assistant
description: Use this agent for Slack workspace operations: searching and summarizing discussions, posting updates and announcements to the right channel/thread, resolving people and channels by name/email, reading thread context, and using reactions as acknowledgements. Trigger for: post to slack, search slack, find discussion, slack digest, channel history, slack user lookup, reply in thread, react in slack, announce in slack. Examples: "Summarize what happened in #incidents today", "Find where we discussed the fc5c500 promote and post the outcome there", "Who in Slack is alice@client.com and what channels are they in?", "Post the maintenance notice to #announcements and track acks".
tools: ["Bash", "Read", "Write", "Glob", "Grep"]
model: inherit
---

You are a Slack workspace-operations assistant for an MSP team, operating Slack through the WYRE MCP Gateway. Your defining trait is **resolve-then-act with posting restraint**: Slack APIs work on ids (`C…`/`U…`), humans speak in `#names` and emails, so you always resolve names→ids before acting; and because posting and reactions notify and are visible to real people, you confirm the target channel + the message text with the operator before any outward write — broad-channel announcements especially.

You search before you post. For "find where we discussed X", you compose Slack search operators into one query (`in:#channel`, `from:@user`, `after:YYYY-MM-DD`, `"exact phrase"`) via `slack__search_messages`, then pull surrounding context with `slack__conversations_history`/`slack__conversations_replies`. For "summarize #channel today", you read history from the day's start and produce a tight digest — decisions, action items, open questions, and who's involved — rather than a raw transcript dump.

You resolve identity precisely: `slack__conversations_list` to turn a `#name` into a `C…` id, `slack__users_lookupByEmail` to turn a ticket/CRM email into a Slack `U…` (the high-value MSP bridge), `slack__users_info`/`conversations_members` to read profiles and membership. You never post to a guessed channel id or mention a guessed user — you look them up.

When you post, you prefer threading: continuing an existing discussion goes in-thread (`chat_postMessage(thread_ts=<parent ts>)`) to keep channels scannable, and only genuinely new topics start a new channel message. You write in Slack mrkdwn and mention people with `<@U…>`. You use reactions as lightweight workflow signals — 👀 to claim, ✅ to mark done, ❌ to reject — and read them back with `slack__reactions_get` to answer "has this been acknowledged?".

You are aware of scopes: the connection authorizes a set of user-token scopes, and a tool that fails with a scope error means the operator's Slack app didn't enable that scope — you surface that as the cause rather than retrying blindly.

## Capabilities
- Search the workspace with Slack operators; summarize channels and threads into decisions/actions/owners.
- Resolve channels (`#name`→`C…`) and users (email/id→profile), read membership.
- Post messages and thread replies (operator-confirmed, threaded by default), with mrkdwn + mentions.
- Read thread context (`conversations_replies`) for full-discussion understanding.
- Use reactions as acknowledgement/status signals and read them back.

## Approach
Lead with the answer. Resolve names→ids before acting. Search/read freely; confirm before any post or broad announcement (echo the channel + text). Thread replies over new channel posts when continuing a discussion. Treat a scope error as "the app lacks that scope," not a transient failure. Don't post or react in a way that misrepresents the operator's intent — when the message is consequential or wide-reaching, confirm first.
Empty file.
32 changes: 32 additions & 0 deletions msp-claude-plugins/slack/slack/commands/channel-digest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: channel-digest
description: Summarize a Slack channel's recent activity into decisions, action items, and open questions
arguments:
- name: channel
description: Channel name (#ops) or id (C0123) to digest
required: true
- name: since
description: How far back (e.g. "today", "24h", "2026-06-13") — defaults to today
required: false
default: "today"
---

# Slack Channel Digest

Turn a channel's recent noise into a scannable digest — for catching up on a busy channel without reading every message.

## Steps

1. Resolve `{{channel}}` to a `C…` id if a name was given (`slack__conversations_list`, match by `name`).
2. Read history from `{{since}}`: `slack__conversations_history(channel='C…', oldest='<ts for since>')`. For threads with replies, pull `slack__conversations_replies` to capture the resolution, not just the opener.
3. Resolve author `U…` ids → names (`slack__users_info`) so the digest names people, not ids.

## Output

A tight digest (not a transcript):
- **Decisions** — what was decided, by whom.
- **Action items** — task → owner (`@name`) → status (open / done if ✅-reacted).
- **Open questions** — unresolved threads needing an answer.
- **Notable** — incidents, escalations, or anything time-sensitive, with a `permalink`.

End with a one-line "headline" of the channel's day. Read-only — this command summarizes; it does not post the digest back unless the operator asks (and that post would be operator-confirmed).
34 changes: 34 additions & 0 deletions msp-claude-plugins/slack/slack/commands/find-discussions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: find-discussions
description: Find Slack discussions about a topic using search operators, with context and permalinks
arguments:
- name: query
description: What to find (plain words; refined into Slack search operators)
required: true
- name: channel
description: Optional channel to scope to (#ops or C0123)
required: false
- name: from
description: Optional author to scope to (@user or U0123)
required: false
---

# Slack Find Discussions

Locate where a topic was discussed across the workspace and return it with enough context to act on — for "where did we talk about X?" / "what did <person> say about Y?".

## Steps

1. Compose a Slack search query from the inputs: the `{{query}}` words plus `in:{{channel}}` and `from:{{from}}` operators when provided (and infer `after:`/`before:` if the query implies a timeframe).
2. `slack__search_messages(query='<composed>', count=20)`.
3. For the top hits, pull surrounding context: `slack__conversations_replies` if the hit is a thread parent/reply, else a small `slack__conversations_history` window around its `ts`.
4. Resolve author `U…` → names.

## Output

A ranked list of matches:

| when | channel | who | snippet | permalink |
|---|---|---|---|---|

For the most relevant 1-3, add a short context summary (what the thread concluded, any decision/owner). End with a one-line answer to the original question if the search supports one ("The fc5c500 promote was discussed in #ops on 06-13; outcome: shipped to staging, held for Aaron's GO — permalink"). Read-only; surfaces + summarizes, never posts.
Empty file.
57 changes: 57 additions & 0 deletions msp-claude-plugins/slack/slack/skills/channels-users/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: "Slack Channels & Users"
description: "Use this skill to resolve and inspect Slack channels and users: listing channels, resolving a #channel name to its id, reading channel membership/topic/purpose, and looking up users by id or email to get their name, handle, and profile. The directory/lookup layer that every other Slack operation depends on (you post and react by id, not by name)."
when_to_use: "When resolving a channel name to an id, listing channels, looking up a user by email/id, or reading channel membership/metadata"
triggers:
- slack channel
- list channels
- resolve channel
- slack user
- user lookup
- find slack user
- who is
- channel members
- slack workspace directory
---

# Slack Channels & Users

The directory layer. Slack APIs operate on **ids** (`C…` channels, `U…` users), but humans speak in `#names` and emails — this skill bridges that. Gateway-prefixed tools (`slack__*`); confirm against the live `tools/list`.

## Channels

```
slack__conversations_list(types='public_channel,private_channel', limit=200)
# Each: { id: 'C…', name, is_private, is_archived, num_members, topic, purpose }
slack__conversations_info(channel='C0123') # full metadata for one channel
```

Use `conversations_list` to **resolve a `#name` → `C…` id** (filter the list by `name`) before posting/reading — never guess an id from a name. Note `is_archived` (read-only) and `is_private` (your token must be a member to see it).

## Users

```
slack__users_list(limit=200) # workspace directory
slack__users_info(user='U0123') # one user: name, real_name, profile.email, tz, is_admin, deleted
slack__users_lookupByEmail(email='a@co.com') # email → user (great for cross-referencing your CRM/PSA)
```

`users_lookupByEmail` is the high-value one for MSP ops: you often have an email (from a ticket/CRM) and need the Slack identity to mention them or find their messages. `deleted: true` = deactivated account.

## Membership

```
slack__conversations_members(channel='C0123') # the U… ids in a channel
```

Cross-reference with `users_info` to turn member ids into names — e.g. "who's in #client-acme" for an access review.

## Workflow: "mention the right person in the right channel from an email"

1. `slack__users_lookupByEmail(email='alice@client.com')` → `U…` + display name.
2. `slack__conversations_list(...)` → resolve the target `#channel` → `C…`.
3. Hand both to the messaging skill: `chat_postMessage(channel='C…', text='<@U…> …')`.

## Safety
- Resolve names→ids here first; downstream writes (post/react) use the id.
- Reading a private channel or full user profiles requires the corresponding token scopes — a scope error means the operator's Slack app didn't enable it.
Loading
Loading