@agentiqus/slack-mcp-client 0.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/README.md +49 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +99 -0
- package/index.ts +136 -0
- package/package.json +39 -0
- package/tsconfig.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @agentiqus/slack-mcp-client
|
|
2
|
+
|
|
3
|
+
A thin stdio MCP server that connects AI tools (Cursor, Claude Desktop) to Slack through the [MCP Orchestrator](https://github.com/faruk-agentiqus/slack-mcp-orchestrator).
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
This package is not used directly. The MCP Orchestrator Slack app generates a configuration JSON for you.
|
|
8
|
+
|
|
9
|
+
1. Install the MCP Orchestrator app in your Slack workspace
|
|
10
|
+
2. Open the app's Home tab, set your permissions, and click **Generate MCP Config**
|
|
11
|
+
3. Paste the generated JSON into your AI tool's MCP config file
|
|
12
|
+
|
|
13
|
+
### Cursor
|
|
14
|
+
|
|
15
|
+
Paste into `~/.cursor/mcp.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"slack": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": ["-y", "@agentiqus/slack-mcp-client"],
|
|
23
|
+
"env": {
|
|
24
|
+
"MCP_TOKEN": "<your-token>",
|
|
25
|
+
"MCP_API_URL": "https://slack-mcp-orchestrator.fly.dev/api/mcp"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Claude Desktop
|
|
33
|
+
|
|
34
|
+
Paste into your Claude Desktop config file.
|
|
35
|
+
|
|
36
|
+
## Environment Variables
|
|
37
|
+
|
|
38
|
+
| Variable | Description |
|
|
39
|
+
| ------------- | ----------------------------------------------------- |
|
|
40
|
+
| `MCP_TOKEN` | Per-user JWT issued by the MCP Orchestrator Slack app |
|
|
41
|
+
| `MCP_API_URL` | Base URL of the MCP Orchestrator API |
|
|
42
|
+
|
|
43
|
+
## How It Works
|
|
44
|
+
|
|
45
|
+
This package runs as a local stdio process. It receives MCP tool calls from your AI tool, forwards them to the MCP Orchestrator API with your JWT, and returns the results. All permission enforcement happens server-side. Your Slack bot token never leaves the server.
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @agentiqus/slack-mcp-client
|
|
4
|
+
*
|
|
5
|
+
* A thin stdio MCP server that forwards all tool calls to the
|
|
6
|
+
* MCP Orchestrator HTTP API. It holds no business logic — just
|
|
7
|
+
* authentication forwarding and protocol bridging.
|
|
8
|
+
*
|
|
9
|
+
* Required env vars:
|
|
10
|
+
* MCP_TOKEN - Per-user JWT issued by the orchestrator
|
|
11
|
+
* MCP_API_URL - Base URL of the orchestrator API (e.g. https://host/api/mcp)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @agentiqus/slack-mcp-client
|
|
4
|
+
*
|
|
5
|
+
* A thin stdio MCP server that forwards all tool calls to the
|
|
6
|
+
* MCP Orchestrator HTTP API. It holds no business logic — just
|
|
7
|
+
* authentication forwarding and protocol bridging.
|
|
8
|
+
*
|
|
9
|
+
* Required env vars:
|
|
10
|
+
* MCP_TOKEN - Per-user JWT issued by the orchestrator
|
|
11
|
+
* MCP_API_URL - Base URL of the orchestrator API (e.g. https://host/api/mcp)
|
|
12
|
+
*/
|
|
13
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Configuration
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const MCP_TOKEN = process.env.MCP_TOKEN;
|
|
20
|
+
const MCP_API_URL = process.env.MCP_API_URL;
|
|
21
|
+
if (!MCP_TOKEN) {
|
|
22
|
+
process.stderr.write('ERROR: MCP_TOKEN environment variable is required.\n');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
if (!MCP_API_URL) {
|
|
26
|
+
process.stderr.write('ERROR: MCP_API_URL environment variable is required.\n');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// HTTP helpers
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
async function apiRequest(path, body) {
|
|
33
|
+
const url = `${MCP_API_URL}${path}`;
|
|
34
|
+
const response = await fetch(url, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: {
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
Authorization: `Bearer ${MCP_TOKEN}`,
|
|
39
|
+
},
|
|
40
|
+
body: JSON.stringify(body),
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const text = await response.text();
|
|
44
|
+
let message;
|
|
45
|
+
try {
|
|
46
|
+
const json = JSON.parse(text);
|
|
47
|
+
message = json.error ?? text;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
message = text;
|
|
51
|
+
}
|
|
52
|
+
if (response.status === 401) {
|
|
53
|
+
throw new Error(`Authentication failed: ${message}. Regenerate your MCP config in Slack.`);
|
|
54
|
+
}
|
|
55
|
+
if (response.status === 403) {
|
|
56
|
+
throw new Error(`Permission denied: ${message}`);
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`API error (${response.status}): ${message}`);
|
|
59
|
+
}
|
|
60
|
+
return response.json();
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// MCP Server
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
const server = new Server({ name: '@agentiqus/slack-mcp-client', version: '0.1.0' }, { capabilities: { tools: {} } });
|
|
66
|
+
// --- tools/list ---------------------------------------------------------------
|
|
67
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
68
|
+
const result = (await apiRequest('/tools/list', {}));
|
|
69
|
+
return { tools: result.tools };
|
|
70
|
+
});
|
|
71
|
+
// --- tools/call ---------------------------------------------------------------
|
|
72
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
73
|
+
try {
|
|
74
|
+
const result = (await apiRequest('/tools/call', {
|
|
75
|
+
name: request.params.name,
|
|
76
|
+
arguments: request.params.arguments ?? {},
|
|
77
|
+
}));
|
|
78
|
+
return { content: result.content };
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: 'text', text: `Error: ${message}` }],
|
|
84
|
+
isError: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Start
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
async function main() {
|
|
92
|
+
const transport = new StdioServerTransport();
|
|
93
|
+
await server.connect(transport);
|
|
94
|
+
process.stderr.write('Slack MCP client connected via stdio.\n');
|
|
95
|
+
}
|
|
96
|
+
main().catch((err) => {
|
|
97
|
+
process.stderr.write(`Fatal: ${err}\n`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
package/index.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @agentiqus/slack-mcp-client
|
|
5
|
+
*
|
|
6
|
+
* A thin stdio MCP server that forwards all tool calls to the
|
|
7
|
+
* MCP Orchestrator HTTP API. It holds no business logic — just
|
|
8
|
+
* authentication forwarding and protocol bridging.
|
|
9
|
+
*
|
|
10
|
+
* Required env vars:
|
|
11
|
+
* MCP_TOKEN - Per-user JWT issued by the orchestrator
|
|
12
|
+
* MCP_API_URL - Base URL of the orchestrator API (e.g. https://host/api/mcp)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
16
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
|
+
import {
|
|
18
|
+
CallToolRequestSchema,
|
|
19
|
+
ListToolsRequestSchema,
|
|
20
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Configuration
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
const MCP_TOKEN = process.env.MCP_TOKEN;
|
|
27
|
+
const MCP_API_URL = process.env.MCP_API_URL;
|
|
28
|
+
|
|
29
|
+
if (!MCP_TOKEN) {
|
|
30
|
+
process.stderr.write('ERROR: MCP_TOKEN environment variable is required.\n');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (!MCP_API_URL) {
|
|
34
|
+
process.stderr.write(
|
|
35
|
+
'ERROR: MCP_API_URL environment variable is required.\n'
|
|
36
|
+
);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// HTTP helpers
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
async function apiRequest(
|
|
45
|
+
path: string,
|
|
46
|
+
body: Record<string, unknown>
|
|
47
|
+
): Promise<unknown> {
|
|
48
|
+
const url = `${MCP_API_URL}${path}`;
|
|
49
|
+
const response = await fetch(url, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
Authorization: `Bearer ${MCP_TOKEN}`,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(body),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
const text = await response.text();
|
|
60
|
+
let message: string;
|
|
61
|
+
try {
|
|
62
|
+
const json = JSON.parse(text);
|
|
63
|
+
message = json.error ?? text;
|
|
64
|
+
} catch {
|
|
65
|
+
message = text;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (response.status === 401) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Authentication failed: ${message}. Regenerate your MCP config in Slack.`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (response.status === 403) {
|
|
74
|
+
throw new Error(`Permission denied: ${message}`);
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`API error (${response.status}): ${message}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return response.json();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// MCP Server
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
const server = new Server(
|
|
87
|
+
{ name: '@agentiqus/slack-mcp-client', version: '0.1.0' },
|
|
88
|
+
{ capabilities: { tools: {} } }
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// --- tools/list ---------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
94
|
+
const result = (await apiRequest('/tools/list', {})) as {
|
|
95
|
+
tools: Array<{
|
|
96
|
+
name: string;
|
|
97
|
+
description: string;
|
|
98
|
+
inputSchema: Record<string, unknown>;
|
|
99
|
+
}>;
|
|
100
|
+
};
|
|
101
|
+
return { tools: result.tools };
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// --- tools/call ---------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
server.setRequestHandler(CallToolRequestSchema, async request => {
|
|
107
|
+
try {
|
|
108
|
+
const result = (await apiRequest('/tools/call', {
|
|
109
|
+
name: request.params.name,
|
|
110
|
+
arguments: request.params.arguments ?? {},
|
|
111
|
+
})) as { content: Array<{ type: string; text: string }> };
|
|
112
|
+
|
|
113
|
+
return { content: result.content };
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
116
|
+
return {
|
|
117
|
+
content: [{ type: 'text', text: `Error: ${message}` }],
|
|
118
|
+
isError: true,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Start
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
async function main(): Promise<void> {
|
|
128
|
+
const transport = new StdioServerTransport();
|
|
129
|
+
await server.connect(transport);
|
|
130
|
+
process.stderr.write('Slack MCP client connected via stdio.\n');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
main().catch(err => {
|
|
134
|
+
process.stderr.write(`Fatal: ${err}\n`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentiqus/slack-mcp-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Thin stdio MCP server that proxies Slack operations through the MCP Orchestrator API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"slack-mcp-client": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"slack",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"ai-tools",
|
|
19
|
+
"cursor",
|
|
20
|
+
"claude"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/faruk-agentiqus/slack-mcp-orchestrator.git",
|
|
25
|
+
"directory": "packages/slack-mcp-client"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/faruk-agentiqus/slack-mcp-orchestrator#readme",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
30
|
+
"zod": "^3.25.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"typescript": "^5.9.3"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|