@pilat/mcp-notify 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -7
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +7 -2
- package/dist/server.js.map +1 -1
- package/dist/slack/client.d.ts +1 -0
- package/dist/slack/client.d.ts.map +1 -1
- package/dist/slack/client.js +18 -4
- package/dist/slack/client.js.map +1 -1
- package/dist/slack/send.d.ts.map +1 -1
- package/dist/slack/send.js +28 -20
- package/dist/slack/send.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
# mcp-notify
|
|
2
2
|
|
|
3
|
-
Minimal MCP server for sending Slack messages
|
|
3
|
+
Minimal MCP server for sending Slack messages. Supports both bot tokens (xoxb) and user tokens (xoxc + cookie auth). Fire-and-forget — single `send_message` tool, nothing else.
|
|
4
4
|
|
|
5
5
|
> **Looking for a full-featured Slack MCP?** Check out [korotovsky/slack-mcp-server](https://github.com/korotovsky/slack-mcp-server) — it supports reading, searching, reactions, threads, DMs, and much more. We recommend it for most use cases.
|
|
6
6
|
>
|
|
7
7
|
> This project exists because we needed two things it doesn't offer:
|
|
8
|
-
> - **Bot signature** — every message gets a `:robot_face:` context block so it's clear the message was sent by an AI assistant, not a human
|
|
8
|
+
> - **Bot signature** — in user-token mode, every message gets a `:robot_face:` context block so it's clear the message was sent by an AI assistant, not a human. In bot-token mode, the app name/icon already serves this purpose.
|
|
9
9
|
> - **Concurrent safety** — SQLite with WAL mode and check-lock-recheck sync pattern, safe for multiple MCP instances running in parallel
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
### Claude Code
|
|
14
14
|
|
|
15
|
-
Add to your MCP config (`~/.claude.json` globally or `.mcp.json` per project)
|
|
15
|
+
Add to your MCP config (`~/.claude.json` globally or `.mcp.json` per project).
|
|
16
|
+
|
|
17
|
+
**Bot token (recommended for Slack apps):**
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"mcp-notify": {
|
|
23
|
+
"type": "stdio",
|
|
24
|
+
"command": "npx",
|
|
25
|
+
"args": ["-y", "@pilat/mcp-notify"],
|
|
26
|
+
"env": {
|
|
27
|
+
"SLACK_MCP_BOT_TOKEN": "xoxb-..."
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**User token (xoxc + cookie):**
|
|
16
35
|
|
|
17
36
|
```json
|
|
18
37
|
{
|
|
@@ -35,6 +54,10 @@ Add to your MCP config (`~/.claude.json` globally or `.mcp.json` per project):
|
|
|
35
54
|
Use `npx @pilat/mcp-notify` as the command with stdio transport. Pass credentials as environment variables:
|
|
36
55
|
|
|
37
56
|
```bash
|
|
57
|
+
# Bot token
|
|
58
|
+
SLACK_MCP_BOT_TOKEN=xoxb-... npx @pilat/mcp-notify
|
|
59
|
+
|
|
60
|
+
# User token
|
|
38
61
|
SLACK_MCP_XOXC_TOKEN=xoxc-... SLACK_MCP_XOXD_TOKEN=xoxd-... npx @pilat/mcp-notify
|
|
39
62
|
```
|
|
40
63
|
|
|
@@ -42,11 +65,21 @@ SLACK_MCP_XOXC_TOKEN=xoxc-... SLACK_MCP_XOXD_TOKEN=xoxd-... npx @pilat/mcp-notif
|
|
|
42
65
|
|
|
43
66
|
| Variable | Required | Description |
|
|
44
67
|
|----------|----------|-------------|
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
68
|
+
| `SLACK_MCP_BOT_TOKEN` | One of bot/user | Bot token (`xoxb-...`) from your Slack app |
|
|
69
|
+
| `SLACK_MCP_XOXC_TOKEN` | One of bot/user | User's `xoxc-...` token |
|
|
70
|
+
| `SLACK_MCP_XOXD_TOKEN` | With xoxc | User's `xoxd-...` session token (value of the `d` cookie) |
|
|
47
71
|
| `SLACK_MCP_DATA_DIR` | No | Custom path for SQLite cache (default: `~/.local/share/mcp-notify`) |
|
|
48
72
|
|
|
49
|
-
|
|
73
|
+
Set either `SLACK_MCP_BOT_TOKEN` **or** `SLACK_MCP_XOXC_TOKEN` + `SLACK_MCP_XOXD_TOKEN`. Setting both bot and user tokens is an error.
|
|
74
|
+
|
|
75
|
+
### Bot token setup
|
|
76
|
+
|
|
77
|
+
1. Create a Slack app at [api.slack.com/apps](https://api.slack.com/apps)
|
|
78
|
+
2. Add the following OAuth scopes: `channels:read`, `groups:read`, `users:read`, `usergroups:read`, `chat:write`
|
|
79
|
+
3. Install the app to your workspace
|
|
80
|
+
4. Copy the **Bot User OAuth Token** (`xoxb-...`)
|
|
81
|
+
|
|
82
|
+
### User token setup (xoxc + cookie)
|
|
50
83
|
|
|
51
84
|
1. Open Slack in browser (not desktop app)
|
|
52
85
|
2. Open DevTools → Network tab
|
|
@@ -57,7 +90,7 @@ SLACK_MCP_XOXC_TOKEN=xoxc-... SLACK_MCP_XOXD_TOKEN=xoxd-... npx @pilat/mcp-notif
|
|
|
57
90
|
|
|
58
91
|
## Architecture
|
|
59
92
|
|
|
60
|
-
Single tool: `send_message`.
|
|
93
|
+
Single tool: `send_message`. In user-token mode, messages include a `:robot_face:` context block. In bot-token mode, messages are sent without the signature (the app name/icon already identifies the sender). Both modes use Block Kit with plain text fallback.
|
|
61
94
|
|
|
62
95
|
- **SQLite cache** (`~/.local/share/mcp-notify/data.db`, WAL mode) — channels, users, user groups with lazy sync on first cache miss, 24h TTL
|
|
63
96
|
- **Mention resolution** — `@username` → `<@U123>`, `@grouphandle` → `<!subteam^ID>`. Groups take priority. Resolved in parallel.
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AASnE,wBAAgB,YAAY,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AASnE,wBAAgB,YAAY,IAAI,MAAM,CAqGrC;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAKjD"}
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,7 @@ const SERVER_INSTRUCTIONS = `Slack message sender (write-only). Single tool: sen
|
|
|
7
7
|
export function createServer() {
|
|
8
8
|
const server = new Server({
|
|
9
9
|
name: 'mcp-notify',
|
|
10
|
-
version: '1.
|
|
10
|
+
version: '1.3.0',
|
|
11
11
|
}, {
|
|
12
12
|
capabilities: {
|
|
13
13
|
tools: {},
|
|
@@ -18,7 +18,7 @@ export function createServer() {
|
|
|
18
18
|
tools: [
|
|
19
19
|
{
|
|
20
20
|
name: 'send_message',
|
|
21
|
-
description: `Send a message to a Slack channel or thread
|
|
21
|
+
description: `Send a message to a Slack channel or thread. In user-token mode, messages are tagged with :robot_face: so recipients know it was AI-assisted. In bot-token mode, the app identity serves this purpose.
|
|
22
22
|
|
|
23
23
|
NOTE: This tool posts to channels only. DMs are not supported.
|
|
24
24
|
|
|
@@ -49,6 +49,10 @@ FORMAT — Slack mrkdwn (NOT Markdown):
|
|
|
49
49
|
type: 'string',
|
|
50
50
|
description: 'Thread timestamp for replying in a thread (e.g. "1718033467.085279"). See URL extraction in tool description.',
|
|
51
51
|
},
|
|
52
|
+
reply_broadcast: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
description: 'When replying in a thread (thread_ts required), also post the message to the channel. Like the "Also send to #channel" checkbox in Slack.',
|
|
55
|
+
},
|
|
52
56
|
},
|
|
53
57
|
required: ['channel', 'message'],
|
|
54
58
|
},
|
|
@@ -71,6 +75,7 @@ FORMAT — Slack mrkdwn (NOT Markdown):
|
|
|
71
75
|
channel: params.channel,
|
|
72
76
|
message: params.message,
|
|
73
77
|
thread_ts: typeof params.thread_ts === 'string' ? params.thread_ts : undefined,
|
|
78
|
+
reply_broadcast: typeof params.reply_broadcast === 'boolean' ? params.reply_broadcast : undefined,
|
|
74
79
|
});
|
|
75
80
|
return {
|
|
76
81
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,mBAAmB,GAAG,6HAA6H,CAAC;AAE1J,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;QACD,YAAY,EAAE,mBAAmB;KAClC,CACF,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,cAAc;gBACpB,WAAW,EAAE;;;;;;;;;;;;;;;6EAewD;gBACrE,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,8IAA8I;yBAC5J;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,mEAAmE;yBACjF;wBACD,SAAS,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,+GAA+G;yBAC7H;qBACF;oBACD,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;iBACjC;aACF;SACF;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,IAAI,CAAC;YACH,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,MAAM,MAAM,GAAG,IAA2C,CAAC;oBAC3D,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;wBAC3D,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,WAAW,EAAE,0CAA0C,CAAC,CAAC;oBAC7F,CAAC;oBACD,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;wBAC3D,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,WAAW,EAAE,0CAA0C,CAAC,CAAC;oBAC7F,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;wBAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;wBACvB,OAAO,EAAE,MAAM,CAAC,OAAO;wBACvB,SAAS,EAAE,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/slack/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/slack/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/slack/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAM3C,wBAAgB,cAAc,IAAI,SAAS,CAmC1C;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
|
package/dist/slack/client.js
CHANGED
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
import { WebClient } from '@slack/web-api';
|
|
2
2
|
import { SlackMcpError, ErrorCode } from '../utils/errors.js';
|
|
3
3
|
let _client = null;
|
|
4
|
+
let _botMode = false;
|
|
4
5
|
export function getSlackClient() {
|
|
5
6
|
if (_client)
|
|
6
7
|
return _client;
|
|
7
|
-
const
|
|
8
|
+
const botToken = process.env.SLACK_MCP_BOT_TOKEN;
|
|
9
|
+
const xoxcToken = process.env.SLACK_MCP_XOXC_TOKEN;
|
|
8
10
|
const xoxd = process.env.SLACK_MCP_XOXD_TOKEN;
|
|
9
|
-
if (
|
|
10
|
-
throw new SlackMcpError(ErrorCode.CONFIG_MISSING, 'SLACK_MCP_XOXC_TOKEN
|
|
11
|
+
if (botToken && xoxcToken) {
|
|
12
|
+
throw new SlackMcpError(ErrorCode.CONFIG_MISSING, 'Both SLACK_MCP_BOT_TOKEN and SLACK_MCP_XOXC_TOKEN are set. Use one or the other, not both.');
|
|
13
|
+
}
|
|
14
|
+
if (botToken) {
|
|
15
|
+
_botMode = true;
|
|
16
|
+
_client = new WebClient(botToken);
|
|
17
|
+
return _client;
|
|
18
|
+
}
|
|
19
|
+
if (!xoxcToken) {
|
|
20
|
+
throw new SlackMcpError(ErrorCode.CONFIG_MISSING, 'Either SLACK_MCP_BOT_TOKEN or SLACK_MCP_XOXC_TOKEN environment variable is required');
|
|
11
21
|
}
|
|
12
22
|
if (!xoxd) {
|
|
13
23
|
throw new SlackMcpError(ErrorCode.CONFIG_MISSING, 'SLACK_MCP_XOXD_TOKEN environment variable is required');
|
|
14
24
|
}
|
|
15
|
-
|
|
25
|
+
_botMode = false;
|
|
26
|
+
_client = new WebClient(xoxcToken, {
|
|
16
27
|
headers: { Cookie: `d=${xoxd}` },
|
|
17
28
|
});
|
|
18
29
|
return _client;
|
|
19
30
|
}
|
|
31
|
+
export function isBotMode() {
|
|
32
|
+
return _botMode;
|
|
33
|
+
}
|
|
20
34
|
//# sourceMappingURL=client.js.map
|
package/dist/slack/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/slack/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE9D,IAAI,OAAO,GAAqB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/slack/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE9D,IAAI,OAAO,GAAqB,IAAI,CAAC;AACrC,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAE9C,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,aAAa,CACrB,SAAS,CAAC,cAAc,EACxB,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CACrB,SAAS,CAAC,cAAc,EACxB,qFAAqF,CACtF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,cAAc,EAAE,uDAAuD,CAAC,CAAC;IAC7G,CAAC;IAED,QAAQ,GAAG,KAAK,CAAC;IACjB,OAAO,GAAG,IAAI,SAAS,CAAC,SAAS,EAAE;QACjC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,EAAE;KACjC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/slack/send.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/slack/send.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AASxE,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/slack/send.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AASxE,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyFvF"}
|
package/dist/slack/send.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SlackMcpError, ErrorCode } from '../utils/errors.js';
|
|
2
|
-
import { getSlackClient } from './client.js';
|
|
2
|
+
import { getSlackClient, isBotMode } from './client.js';
|
|
3
3
|
import { getChannelId } from '../cache/channels.js';
|
|
4
4
|
import { convertMentions } from '../mentions/resolver.js';
|
|
5
5
|
const THREAD_TS_RE = /^\d+\.\d{6}$/;
|
|
@@ -10,6 +10,10 @@ export async function sendMessage(params) {
|
|
|
10
10
|
if (params.thread_ts && !THREAD_TS_RE.test(params.thread_ts)) {
|
|
11
11
|
throw new SlackMcpError(ErrorCode.SEND_FAILED, `Invalid thread_ts format "${params.thread_ts}". Expected format: "1234567890.123456".`);
|
|
12
12
|
}
|
|
13
|
+
// Validate reply_broadcast requires thread_ts
|
|
14
|
+
if (params.reply_broadcast && !params.thread_ts) {
|
|
15
|
+
throw new SlackMcpError(ErrorCode.SEND_FAILED, 'reply_broadcast requires thread_ts. You can only broadcast a thread reply to the channel.');
|
|
16
|
+
}
|
|
13
17
|
// Resolve mentions
|
|
14
18
|
const convertedMessage = await convertMentions(params.message, client);
|
|
15
19
|
// Resolve channel
|
|
@@ -17,12 +21,12 @@ export async function sendMessage(params) {
|
|
|
17
21
|
if (!channelId) {
|
|
18
22
|
throw new SlackMcpError(ErrorCode.CHANNEL_NOT_FOUND, `Channel "${params.channel}" not found (tried as both name and ID). Verify it exists and you have access.`);
|
|
19
23
|
}
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const sharedArgs = { channel: channelId, unfurl_links: false, unfurl_media: false };
|
|
25
|
+
const baseArgs = params.reply_broadcast && params.thread_ts
|
|
26
|
+
? { ...sharedArgs, thread_ts: params.thread_ts, reply_broadcast: true }
|
|
27
|
+
: params.thread_ts
|
|
28
|
+
? { ...sharedArgs, thread_ts: params.thread_ts }
|
|
29
|
+
: sharedArgs;
|
|
26
30
|
const makeResult = (ts, fallback) => ({
|
|
27
31
|
status: 'success',
|
|
28
32
|
message: fallback ? 'Message sent successfully (plain text fallback)' : 'Message sent successfully',
|
|
@@ -31,24 +35,28 @@ export async function sendMessage(params) {
|
|
|
31
35
|
message_ts: ts,
|
|
32
36
|
sent_message: convertedMessage,
|
|
33
37
|
thread_ts: params.thread_ts,
|
|
38
|
+
reply_broadcast: params.reply_broadcast,
|
|
34
39
|
});
|
|
35
40
|
// Skip Block Kit if message exceeds the 3000-char section limit
|
|
36
41
|
if (convertedMessage.length > BLOCK_KIT_TEXT_LIMIT) {
|
|
37
42
|
return sendPlainText(client, baseArgs, convertedMessage, params.channel, makeResult);
|
|
38
43
|
}
|
|
39
44
|
// Build Block Kit blocks
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const sectionBlock = {
|
|
46
|
+
type: 'section',
|
|
47
|
+
text: { type: 'mrkdwn', text: convertedMessage },
|
|
48
|
+
};
|
|
49
|
+
const blocks = isBotMode()
|
|
50
|
+
? [sectionBlock]
|
|
51
|
+
: [
|
|
52
|
+
sectionBlock,
|
|
53
|
+
{
|
|
54
|
+
type: 'context',
|
|
55
|
+
elements: [
|
|
56
|
+
{ type: 'mrkdwn', text: ':robot_face: Sent by AI assistant' },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
];
|
|
52
60
|
try {
|
|
53
61
|
const result = await client.chat.postMessage({
|
|
54
62
|
...baseArgs,
|
|
@@ -72,7 +80,7 @@ async function sendPlainText(client, baseArgs, message, channelName, makeResult)
|
|
|
72
80
|
try {
|
|
73
81
|
const result = await client.chat.postMessage({
|
|
74
82
|
...baseArgs,
|
|
75
|
-
text: `:robot_face: ${message}`,
|
|
83
|
+
text: isBotMode() ? message : `:robot_face: ${message}`,
|
|
76
84
|
});
|
|
77
85
|
return makeResult(result.ts, true);
|
|
78
86
|
}
|
package/dist/slack/send.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/slack/send.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/slack/send.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface SendMessageParams {
|
|
|
2
2
|
channel: string;
|
|
3
3
|
message: string;
|
|
4
4
|
thread_ts?: string;
|
|
5
|
+
reply_broadcast?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export interface SendMessageResult {
|
|
7
8
|
status: 'success' | 'error';
|
|
@@ -11,5 +12,6 @@ export interface SendMessageResult {
|
|
|
11
12
|
message_ts?: string;
|
|
12
13
|
sent_message?: string;
|
|
13
14
|
thread_ts?: string;
|
|
15
|
+
reply_broadcast?: boolean;
|
|
14
16
|
}
|
|
15
17
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pilat/mcp-notify",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for sending Slack messages
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "MCP server for sending Slack messages (bot token or user xoxc + cookie auth)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|