@jtalk22/slack-mcp 1.0.4 → 1.1.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/src/web-server.js CHANGED
@@ -5,16 +5,21 @@
5
5
  * Exposes Slack MCP tools as REST endpoints for browser access.
6
6
  * Run alongside or instead of the MCP server for web-based access.
7
7
  *
8
- * @version 1.0.0
8
+ * @version 1.1.0
9
9
  */
10
10
 
11
11
  import express from "express";
12
+ import { randomBytes } from "crypto";
12
13
  import { fileURLToPath } from "url";
13
14
  import { dirname, join } from "path";
15
+ import { existsSync, readFileSync, writeFileSync } from "fs";
16
+ import { execSync } from "child_process";
17
+ import { homedir } from "os";
14
18
  import { loadTokens } from "../lib/token-store.js";
15
19
 
16
20
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
21
  import {
22
+ handleTokenStatus,
18
23
  handleHealthCheck,
19
24
  handleRefreshTokens,
20
25
  handleListConversations,
@@ -30,9 +35,33 @@ import {
30
35
  const app = express();
31
36
  const PORT = process.env.PORT || 3000;
32
37
 
33
- // Default API key for convenience - override with SLACK_API_KEY env var for production
34
- const DEFAULT_API_KEY = "slack-mcp-local";
35
- const API_KEY = process.env.SLACK_API_KEY || DEFAULT_API_KEY;
38
+ // Secure API key management
39
+ const API_KEY_FILE = join(homedir(), ".slack-mcp-api-key");
40
+
41
+ function getOrCreateAPIKey() {
42
+ // Priority 1: Environment variable
43
+ if (process.env.SLACK_API_KEY) {
44
+ return process.env.SLACK_API_KEY;
45
+ }
46
+
47
+ // Priority 2: Key file
48
+ if (existsSync(API_KEY_FILE)) {
49
+ try {
50
+ return readFileSync(API_KEY_FILE, "utf-8").trim();
51
+ } catch {}
52
+ }
53
+
54
+ // Priority 3: Generate new secure key
55
+ const newKey = `smcp_${randomBytes(24).toString('base64url')}`;
56
+ try {
57
+ writeFileSync(API_KEY_FILE, newKey);
58
+ execSync(`chmod 600 "${API_KEY_FILE}"`);
59
+ } catch {}
60
+
61
+ return newKey;
62
+ }
63
+
64
+ const API_KEY = getOrCreateAPIKey();
36
65
 
37
66
  // Middleware
38
67
  app.use(express.json());
@@ -94,6 +123,16 @@ app.get("/", (req, res) => {
94
123
  });
95
124
  });
96
125
 
126
+ // Token status (detailed health + cache info)
127
+ app.get("/token-status", authenticate, async (req, res) => {
128
+ try {
129
+ const result = await handleTokenStatus();
130
+ res.json(extractContent(result));
131
+ } catch (e) {
132
+ res.status(500).json({ error: e.message });
133
+ }
134
+ });
135
+
97
136
  // Health check
98
137
  app.get("/health", authenticate, async (req, res) => {
99
138
  try {
@@ -242,11 +281,14 @@ async function main() {
242
281
  }
243
282
 
244
283
  app.listen(PORT, () => {
245
- console.log(`\nšŸš€ Slack Web API Server running at http://localhost:${PORT}`);
246
- console.log(`\nšŸ”‘ API Key: ${API_KEY}`);
247
- console.log(`\nExample usage:`);
248
- console.log(` curl -H "Authorization: Bearer ${API_KEY}" http://localhost:${PORT}/health`);
249
- console.log(` curl -H "Authorization: Bearer ${API_KEY}" http://localhost:${PORT}/conversations`);
284
+ // Print to stderr to keep logs clean (stdout reserved for JSON in some setups)
285
+ console.error(`\n${"═".repeat(60)}`);
286
+ console.error(` Slack Web API Server v1.1.0`);
287
+ console.error(`${"═".repeat(60)}`);
288
+ console.error(`\n Dashboard: http://localhost:${PORT}/?key=${API_KEY}`);
289
+ console.error(`\n API Key: ${API_KEY}`);
290
+ console.error(`\n curl -H "Authorization: Bearer ${API_KEY}" http://localhost:${PORT}/health`);
291
+ console.error(`\n${"═".repeat(60)}\n`);
250
292
  });
251
293
  }
252
294