slack-max-api-mcp 1.0.7 → 1.0.8
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/.env.example +4 -0
- package/README.md +26 -19
- package/package.json +2 -1
- package/src/slack-mcp-server.js +56 -8
package/.env.example
CHANGED
|
@@ -38,6 +38,10 @@ SLACK_CLIENT_SECRET=
|
|
|
38
38
|
|
|
39
39
|
# Optional auto-onboarding trigger for interactive `slack-max-api-mcp` runs
|
|
40
40
|
# SLACK_AUTO_ONBOARD=true
|
|
41
|
+
# Built-in default team gateway used when no auto-onboard gateway is set:
|
|
42
|
+
# SLACK_DEFAULT_TEAM_GATEWAY_URL=https://43.202.54.65.sslip.io
|
|
43
|
+
# SLACK_DEFAULT_TEAM_GATEWAY_INSECURE_TLS=true
|
|
44
|
+
# SLACK_GATEWAY_INSECURE_TLS=true
|
|
41
45
|
# SLACK_AUTO_ONBOARD_URL=https://mcp-gateway.example.com/onboard.ps1?token=...
|
|
42
46
|
# or
|
|
43
47
|
# SLACK_AUTO_ONBOARD_GATEWAY=https://mcp-gateway.example.com
|
package/README.md
CHANGED
|
@@ -62,17 +62,26 @@ Slack Web API를 Codex/Claude Code에서 바로 사용할 수 있게 만든 `std
|
|
|
62
62
|
2. USER 토큰 사용 시 메시지/파일 검색, 채널 읽기, 메시지 전송 가능
|
|
63
63
|
3. BOT으로 검색은 토큰 타입 제한(`not_allowed_token_type`)이 있어 USER 토큰 사용 권장
|
|
64
64
|
|
|
65
|
-
## 설치 및 실행
|
|
66
|
-
|
|
67
|
-
```powershell
|
|
68
|
-
npm install -g slack-max-api-mcp@latest
|
|
69
|
-
slack-max-api-mcp
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
## 설치 및 실행
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
npm install -g slack-max-api-mcp@latest
|
|
69
|
+
slack-max-api-mcp
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
팀원 기본 온보딩(현재 패키지 기본값):
|
|
73
|
+
1. 추가 환경변수 없이 `slack-max-api-mcp` 실행 시 자동 온보딩 시도
|
|
74
|
+
2. 기본 게이트웨이: `https://43.202.54.65.sslip.io`
|
|
75
|
+
3. 승인 후 Codex 등록 1회:
|
|
76
|
+
|
|
77
|
+
```powershell
|
|
78
|
+
codex mcp add slack-max -- npx -y slack-max-api-mcp
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
또는:
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
npx -y slack-max-api-mcp
|
|
76
85
|
```
|
|
77
86
|
|
|
78
87
|
## Codex / Claude Code 연결
|
|
@@ -122,9 +131,7 @@ npx -y slack-max-api-mcp gateway start
|
|
|
122
131
|
### 팀원 경험 (토큰 전달 없이 권장)
|
|
123
132
|
|
|
124
133
|
```powershell
|
|
125
|
-
|
|
126
|
-
npx -y slack-max-api-mcp onboard run --gateway "https://your-gateway.example.com"
|
|
127
|
-
Remove-Item Env:NODE_TLS_REJECT_UNAUTHORIZED
|
|
134
|
+
npx -y slack-max-api-mcp onboard run
|
|
128
135
|
```
|
|
129
136
|
|
|
130
137
|
자동 동작:
|
|
@@ -155,7 +162,7 @@ powershell -ExecutionPolicy Bypass -Command "irm 'https://your-gateway.example.c
|
|
|
155
162
|
|
|
156
163
|
### 팀원 경험 (설치 후 `slack-max-api-mcp`만 실행)
|
|
157
164
|
|
|
158
|
-
|
|
165
|
+
현재 패키지 기본 게이트웨이(`https://43.202.54.65.sslip.io`)를 계속 사용할 경우 팀원은 다음만 수행하면 됩니다.
|
|
159
166
|
|
|
160
167
|
```powershell
|
|
161
168
|
npm install -g slack-max-api-mcp@latest
|
|
@@ -168,10 +175,10 @@ slack-max-api-mcp
|
|
|
168
175
|
3. Slack Allow 승인
|
|
169
176
|
4. 완료 후 Codex에서 바로 사용
|
|
170
177
|
|
|
171
|
-
|
|
172
|
-
1. `
|
|
173
|
-
2. `
|
|
174
|
-
3.
|
|
178
|
+
게이트웨이 주소를 바꿔야 할 때만(운영자):
|
|
179
|
+
1. `SLACK_DEFAULT_TEAM_GATEWAY_URL`
|
|
180
|
+
2. `SLACK_DEFAULT_TEAM_GATEWAY_INSECURE_TLS` (`true/false`)
|
|
181
|
+
3. 또는 기존 방식대로 `SLACK_AUTO_ONBOARD_URL`, `SLACK_AUTO_ONBOARD_GATEWAY` 사용 가능
|
|
175
182
|
|
|
176
183
|
## 2) 단독/개인 운영: 로컬 OAuth 모드
|
|
177
184
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slack-max-api-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Slack MCP server (stdio) for Codex and Claude Code",
|
|
5
5
|
"main": "src/slack-mcp-server.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"type": "commonjs",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
30
|
+
"undici": "^7.16.0",
|
|
30
31
|
"zod": "^4.3.6"
|
|
31
32
|
}
|
|
32
33
|
}
|
package/src/slack-mcp-server.js
CHANGED
|
@@ -6,6 +6,7 @@ const http = require("node:http");
|
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
const crypto = require("node:crypto");
|
|
8
8
|
const { spawn } = require("node:child_process");
|
|
9
|
+
const { Agent, fetch: undiciFetch } = require("undici");
|
|
9
10
|
const { McpServer } = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
10
11
|
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
11
12
|
const { z } = require("zod");
|
|
@@ -57,8 +58,20 @@ const GATEWAY_PUBLIC_ONBOARD_PROFILE_PREFIX =
|
|
|
57
58
|
const GATEWAY_STATE_TTL_MS = Number(process.env.SLACK_GATEWAY_STATE_TTL_MS || 15 * 60 * 1000);
|
|
58
59
|
const INVITE_TOKEN_DEFAULT_DAYS = Number(process.env.SLACK_INVITE_TOKEN_DEFAULT_DAYS || 7);
|
|
59
60
|
const AUTO_ONBOARD_ENABLED = process.env.SLACK_AUTO_ONBOARD !== "false";
|
|
61
|
+
const DEFAULT_TEAM_GATEWAY_URL =
|
|
62
|
+
process.env.SLACK_DEFAULT_TEAM_GATEWAY_URL || "https://43.202.54.65.sslip.io";
|
|
63
|
+
const DEFAULT_TEAM_GATEWAY_INSECURE_TLS =
|
|
64
|
+
process.env.SLACK_DEFAULT_TEAM_GATEWAY_INSECURE_TLS !== "false";
|
|
65
|
+
const GATEWAY_INSECURE_TLS =
|
|
66
|
+
process.env.SLACK_GATEWAY_INSECURE_TLS === "true"
|
|
67
|
+
? true
|
|
68
|
+
: process.env.SLACK_GATEWAY_INSECURE_TLS === "false"
|
|
69
|
+
? false
|
|
70
|
+
: null;
|
|
60
71
|
const AUTO_ONBOARD_GATEWAY =
|
|
61
|
-
process.env.SLACK_AUTO_ONBOARD_GATEWAY ||
|
|
72
|
+
process.env.SLACK_AUTO_ONBOARD_GATEWAY ||
|
|
73
|
+
process.env.SLACK_ONBOARD_GATEWAY_URL ||
|
|
74
|
+
DEFAULT_TEAM_GATEWAY_URL;
|
|
62
75
|
const AUTO_ONBOARD_PROFILE = process.env.SLACK_AUTO_ONBOARD_PROFILE || "";
|
|
63
76
|
const AUTO_ONBOARD_TOKEN = process.env.SLACK_AUTO_ONBOARD_TOKEN || process.env.SLACK_ONBOARD_TOKEN || "";
|
|
64
77
|
const AUTO_ONBOARD_URL = process.env.SLACK_AUTO_ONBOARD_URL || process.env.SLACK_ONBOARD_URL || "";
|
|
@@ -68,6 +81,11 @@ const ONBOARD_PACKAGE_SPEC =
|
|
|
68
81
|
process.env.SLACK_ONBOARD_INSTALL_SPEC ||
|
|
69
82
|
"slack-max-api-mcp@latest";
|
|
70
83
|
const ONBOARD_SKIP_TLS_VERIFY = process.env.SLACK_ONBOARD_SKIP_TLS_VERIFY === "true";
|
|
84
|
+
const INSECURE_TLS_DISPATCHER = new Agent({
|
|
85
|
+
connect: {
|
|
86
|
+
rejectUnauthorized: false,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
71
89
|
|
|
72
90
|
function parseSimpleEnvFile(filePath) {
|
|
73
91
|
if (!fs.existsSync(filePath)) return {};
|
|
@@ -127,6 +145,33 @@ function ensureParentDirectory(filePath) {
|
|
|
127
145
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
128
146
|
}
|
|
129
147
|
|
|
148
|
+
function normalizeBaseUrl(url) {
|
|
149
|
+
return String(url || "").trim().replace(/\/+$/, "");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function normalizeUrlOrigin(url) {
|
|
153
|
+
try {
|
|
154
|
+
const parsed = new URL(String(url || "").trim());
|
|
155
|
+
return `${parsed.protocol}//${parsed.host}`.replace(/\/+$/, "");
|
|
156
|
+
} catch {
|
|
157
|
+
return normalizeBaseUrl(url);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function shouldUseInsecureGatewayTls(url) {
|
|
162
|
+
if (!url) return false;
|
|
163
|
+
if (GATEWAY_INSECURE_TLS !== null) return GATEWAY_INSECURE_TLS;
|
|
164
|
+
if (!DEFAULT_TEAM_GATEWAY_INSECURE_TLS) return false;
|
|
165
|
+
return normalizeUrlOrigin(url) === normalizeUrlOrigin(DEFAULT_TEAM_GATEWAY_URL);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function fetchWithOptionalInsecureGatewayTls(url, options) {
|
|
169
|
+
if (!shouldUseInsecureGatewayTls(url)) {
|
|
170
|
+
return undiciFetch(url, options);
|
|
171
|
+
}
|
|
172
|
+
return undiciFetch(url, { ...(options || {}), dispatcher: INSECURE_TLS_DISPATCHER });
|
|
173
|
+
}
|
|
174
|
+
|
|
130
175
|
function emptyTokenStore() {
|
|
131
176
|
return { version: 1, default_profile: null, profiles: {} };
|
|
132
177
|
}
|
|
@@ -354,7 +399,8 @@ async function callSlackApiViaGateway(method, params = {}, tokenOverride, option
|
|
|
354
399
|
throw new Error("Gateway URL is missing. Set SLACK_GATEWAY_URL to use gateway mode.");
|
|
355
400
|
}
|
|
356
401
|
|
|
357
|
-
const
|
|
402
|
+
const gatewayCallUrl = `${runtimeGateway.url}/api/slack/call`;
|
|
403
|
+
const response = await fetchWithOptionalInsecureGatewayTls(gatewayCallUrl, {
|
|
358
404
|
method: "POST",
|
|
359
405
|
headers: buildGatewayAuthHeaders(runtimeGateway.apiKey),
|
|
360
406
|
body: JSON.stringify({
|
|
@@ -404,7 +450,8 @@ async function slackHttpViaGateway(input) {
|
|
|
404
450
|
throw new Error("Gateway URL is missing. Set SLACK_GATEWAY_URL to use gateway mode.");
|
|
405
451
|
}
|
|
406
452
|
|
|
407
|
-
const
|
|
453
|
+
const gatewayHttpUrl = `${runtimeGateway.url}/api/slack/http`;
|
|
454
|
+
const response = await fetchWithOptionalInsecureGatewayTls(gatewayHttpUrl, {
|
|
408
455
|
method: "POST",
|
|
409
456
|
headers: buildGatewayAuthHeaders(runtimeGateway.apiKey),
|
|
410
457
|
body: JSON.stringify({
|
|
@@ -1018,11 +1065,12 @@ function printOnboardHelp() {
|
|
|
1018
1065
|
"Slack Max onboarding helper",
|
|
1019
1066
|
"",
|
|
1020
1067
|
"Usage:",
|
|
1021
|
-
" slack-max-api-mcp onboard run --gateway https://gateway.example.com [--token <invite_token>]",
|
|
1068
|
+
" slack-max-api-mcp onboard run [--gateway https://gateway.example.com] [--token <invite_token>]",
|
|
1022
1069
|
" [--profile NAME] [--team T123] [--scope a,b] [--user-scope c,d]",
|
|
1023
|
-
" slack-max-api-mcp onboard quick --gateway https://gateway.example.com",
|
|
1070
|
+
" slack-max-api-mcp onboard quick [--gateway https://gateway.example.com]",
|
|
1024
1071
|
" slack-max-api-mcp onboard help",
|
|
1025
1072
|
"",
|
|
1073
|
+
`Default gateway (if omitted): ${DEFAULT_TEAM_GATEWAY_URL}`,
|
|
1026
1074
|
"If --token is omitted, it uses gateway public onboarding endpoint (/onboard/bootstrap).",
|
|
1027
1075
|
"This command writes local client config and opens the Slack OAuth approval page automatically.",
|
|
1028
1076
|
];
|
|
@@ -1031,11 +1079,11 @@ function printOnboardHelp() {
|
|
|
1031
1079
|
|
|
1032
1080
|
async function runOnboardStart(args) {
|
|
1033
1081
|
const { options } = parseCliArgs(args);
|
|
1034
|
-
const gateway =
|
|
1082
|
+
const gateway = normalizeBaseUrl(options.gateway || options.url || DEFAULT_TEAM_GATEWAY_URL);
|
|
1035
1083
|
const token = String(options.token || "");
|
|
1036
1084
|
if (!gateway) {
|
|
1037
1085
|
throw new Error(
|
|
1038
|
-
"Usage: slack-max-api-mcp onboard run --gateway <url> [--token <invite_token>] [--profile <name>]"
|
|
1086
|
+
"Usage: slack-max-api-mcp onboard run [--gateway <url>] [--token <invite_token>] [--profile <name>]"
|
|
1039
1087
|
);
|
|
1040
1088
|
}
|
|
1041
1089
|
|
|
@@ -1057,7 +1105,7 @@ async function runOnboardStart(args) {
|
|
|
1057
1105
|
return `${gateway}/onboard/bootstrap${query ? `?${query}` : ""}`;
|
|
1058
1106
|
})();
|
|
1059
1107
|
|
|
1060
|
-
const response = await
|
|
1108
|
+
const response = await fetchWithOptionalInsecureGatewayTls(onboardingUrl, {
|
|
1061
1109
|
method: "GET",
|
|
1062
1110
|
headers: { Accept: "application/json" },
|
|
1063
1111
|
});
|