slack-workspace-mcp-server 0.0.1

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.
Files changed (46) hide show
  1. package/README.md +122 -0
  2. package/build/index.d.ts +2 -0
  3. package/build/index.integration-with-mock.d.ts +2 -0
  4. package/build/index.integration-with-mock.js +34 -0
  5. package/build/index.js +76 -0
  6. package/package.json +47 -0
  7. package/shared/index.d.ts +4 -0
  8. package/shared/index.js +7 -0
  9. package/shared/logging.d.ts +10 -0
  10. package/shared/logging.js +21 -0
  11. package/shared/server.d.ts +134 -0
  12. package/shared/server.js +68 -0
  13. package/shared/slack-client/lib/add-reaction.d.ts +5 -0
  14. package/shared/slack-client/lib/add-reaction.js +30 -0
  15. package/shared/slack-client/lib/get-channel.d.ts +5 -0
  16. package/shared/slack-client/lib/get-channel.js +24 -0
  17. package/shared/slack-client/lib/get-channels.d.ts +10 -0
  18. package/shared/slack-client/lib/get-channels.js +37 -0
  19. package/shared/slack-client/lib/get-messages.d.ts +16 -0
  20. package/shared/slack-client/lib/get-messages.js +38 -0
  21. package/shared/slack-client/lib/get-thread.d.ts +16 -0
  22. package/shared/slack-client/lib/get-thread.js +39 -0
  23. package/shared/slack-client/lib/post-message.d.ts +10 -0
  24. package/shared/slack-client/lib/post-message.js +44 -0
  25. package/shared/slack-client/lib/update-message.d.ts +5 -0
  26. package/shared/slack-client/lib/update-message.js +32 -0
  27. package/shared/slack-client/slack-client.integration-mock.d.ts +16 -0
  28. package/shared/slack-client/slack-client.integration-mock.js +106 -0
  29. package/shared/tools/get-channel.d.ts +55 -0
  30. package/shared/tools/get-channel.js +136 -0
  31. package/shared/tools/get-channels.d.ts +46 -0
  32. package/shared/tools/get-channels.js +107 -0
  33. package/shared/tools/get-thread.d.ts +54 -0
  34. package/shared/tools/get-thread.js +130 -0
  35. package/shared/tools/post-message.d.ts +44 -0
  36. package/shared/tools/post-message.js +81 -0
  37. package/shared/tools/react-to-message.d.ts +51 -0
  38. package/shared/tools/react-to-message.js +90 -0
  39. package/shared/tools/reply-to-thread.d.ts +59 -0
  40. package/shared/tools/reply-to-thread.js +97 -0
  41. package/shared/tools/update-message.d.ts +51 -0
  42. package/shared/tools/update-message.js +87 -0
  43. package/shared/tools.d.ts +18 -0
  44. package/shared/tools.js +78 -0
  45. package/shared/types.d.ts +112 -0
  46. package/shared/types.js +5 -0
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ const PARAM_DESCRIPTIONS = {
3
+ channel_id: 'The channel ID where the message exists (e.g., "C1234567890"). ' +
4
+ 'Get channel IDs using the slack_get_channels tool.',
5
+ message_ts: 'The timestamp of the message to update (e.g., "1234567890.123456"). ' +
6
+ 'This is shown as "ts" in message outputs.',
7
+ text: 'The new content for the message. Completely replaces the existing text. ' +
8
+ 'Supports Slack markdown: *bold*, _italic_, `code`, ```code blocks```.',
9
+ };
10
+ export const UpdateMessageSchema = z.object({
11
+ channel_id: z.string().min(1).describe(PARAM_DESCRIPTIONS.channel_id),
12
+ message_ts: z.string().min(1).describe(PARAM_DESCRIPTIONS.message_ts),
13
+ text: z.string().min(1).describe(PARAM_DESCRIPTIONS.text),
14
+ });
15
+ const TOOL_DESCRIPTION = `Update an existing message in Slack.
16
+
17
+ Modifies the content of a message that was previously posted. The message will show an "(edited)" indicator after being updated.
18
+
19
+ **Returns:**
20
+ - Confirmation of the update
21
+ - The updated message content
22
+
23
+ **Use cases:**
24
+ - Fix typos or errors in a message
25
+ - Update information that has changed
26
+ - Add clarifications to a previous message
27
+ - Mark a task or question as resolved by editing the message
28
+
29
+ **Note:**
30
+ - You can only edit messages that the bot posted
31
+ - The edit history is not preserved - only the final content is shown
32
+ - Consider adding reactions instead if you just want to acknowledge a message`;
33
+ export function updateMessageTool(server, clientFactory) {
34
+ return {
35
+ name: 'slack_update_message',
36
+ description: TOOL_DESCRIPTION,
37
+ inputSchema: {
38
+ type: 'object',
39
+ properties: {
40
+ channel_id: {
41
+ type: 'string',
42
+ description: PARAM_DESCRIPTIONS.channel_id,
43
+ },
44
+ message_ts: {
45
+ type: 'string',
46
+ description: PARAM_DESCRIPTIONS.message_ts,
47
+ },
48
+ text: {
49
+ type: 'string',
50
+ description: PARAM_DESCRIPTIONS.text,
51
+ },
52
+ },
53
+ required: ['channel_id', 'message_ts', 'text'],
54
+ },
55
+ handler: async (args) => {
56
+ try {
57
+ const parsed = UpdateMessageSchema.parse(args);
58
+ const client = clientFactory();
59
+ const message = await client.updateMessage(parsed.channel_id, parsed.message_ts, parsed.text);
60
+ const time = new Date(parseFloat(message.ts) * 1000).toISOString();
61
+ return {
62
+ content: [
63
+ {
64
+ type: 'text',
65
+ text: `Message updated successfully!\n\n` +
66
+ `Channel: ${parsed.channel_id}\n` +
67
+ `Timestamp: ${message.ts}\n` +
68
+ `Updated at: ${time}\n\n` +
69
+ `New content:\n${parsed.text}`,
70
+ },
71
+ ],
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ content: [
77
+ {
78
+ type: 'text',
79
+ text: `Error updating message: ${error instanceof Error ? error.message : 'Unknown error'}`,
80
+ },
81
+ ],
82
+ isError: true,
83
+ };
84
+ }
85
+ },
86
+ };
87
+ }
@@ -0,0 +1,18 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { ClientFactory } from './server.js';
3
+ /**
4
+ * Tool groups for permission-based access control
5
+ */
6
+ export type ToolGroup = 'readonly' | 'write';
7
+ /**
8
+ * Parse enabled tool groups from environment variable
9
+ */
10
+ export declare function parseEnabledToolGroups(enabledGroupsParam?: string): ToolGroup[];
11
+ /**
12
+ * Creates a function to register all tools with the server
13
+ */
14
+ export declare function createRegisterTools(clientFactory: ClientFactory, enabledGroups?: ToolGroup[]): (server: Server) => void;
15
+ /**
16
+ * Backward compatibility export
17
+ */
18
+ export declare function registerTools(server: Server): void;
@@ -0,0 +1,78 @@
1
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
2
+ import { logWarning } from './logging.js';
3
+ import { getChannelsTool } from './tools/get-channels.js';
4
+ import { getChannelTool } from './tools/get-channel.js';
5
+ import { getThreadTool } from './tools/get-thread.js';
6
+ import { postMessageTool } from './tools/post-message.js';
7
+ import { replyToThreadTool } from './tools/reply-to-thread.js';
8
+ import { updateMessageTool } from './tools/update-message.js';
9
+ import { reactToMessageTool } from './tools/react-to-message.js';
10
+ const ALL_TOOL_GROUPS = ['readonly', 'write'];
11
+ /**
12
+ * Parse enabled tool groups from environment variable
13
+ */
14
+ export function parseEnabledToolGroups(enabledGroupsParam) {
15
+ if (!enabledGroupsParam) {
16
+ return ALL_TOOL_GROUPS;
17
+ }
18
+ const requestedGroups = enabledGroupsParam.split(',').map((g) => g.trim().toLowerCase());
19
+ const validGroups = requestedGroups.filter((g) => ALL_TOOL_GROUPS.includes(g));
20
+ if (validGroups.length === 0) {
21
+ logWarning('parseEnabledToolGroups', `No valid tool groups found in "${enabledGroupsParam}". Valid groups: ${ALL_TOOL_GROUPS.join(', ')}`);
22
+ return ALL_TOOL_GROUPS;
23
+ }
24
+ return validGroups;
25
+ }
26
+ /**
27
+ * All available tools with their group assignments
28
+ */
29
+ const ALL_TOOLS = [
30
+ // Read-only tools
31
+ { factory: getChannelsTool, groups: ['readonly', 'write'] },
32
+ { factory: getChannelTool, groups: ['readonly', 'write'] },
33
+ { factory: getThreadTool, groups: ['readonly', 'write'] },
34
+ // Write tools
35
+ { factory: postMessageTool, groups: ['write'] },
36
+ { factory: replyToThreadTool, groups: ['write'] },
37
+ { factory: updateMessageTool, groups: ['write'] },
38
+ { factory: reactToMessageTool, groups: ['write'] },
39
+ ];
40
+ /**
41
+ * Creates a function to register all tools with the server
42
+ */
43
+ export function createRegisterTools(clientFactory, enabledGroups) {
44
+ const groups = enabledGroups || parseEnabledToolGroups(process.env.ENABLED_TOOLGROUPS);
45
+ return (server) => {
46
+ // Filter tools by enabled groups and create instances
47
+ const tools = ALL_TOOLS.filter((def) => def.groups.some((g) => groups.includes(g))).map((def) => def.factory(server, clientFactory));
48
+ // List available tools
49
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
50
+ return {
51
+ tools: tools.map((tool) => ({
52
+ name: tool.name,
53
+ description: tool.description,
54
+ inputSchema: tool.inputSchema,
55
+ })),
56
+ };
57
+ });
58
+ // Handle tool calls
59
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
60
+ const { name, arguments: args } = request.params;
61
+ const tool = tools.find((t) => t.name === name);
62
+ if (!tool) {
63
+ throw new Error(`Unknown tool: ${name}`);
64
+ }
65
+ return await tool.handler(args);
66
+ });
67
+ };
68
+ }
69
+ /**
70
+ * Backward compatibility export
71
+ */
72
+ export function registerTools(server) {
73
+ const factory = () => {
74
+ throw new Error('No client factory provided - use createRegisterTools for dependency injection');
75
+ };
76
+ const register = createRegisterTools(factory);
77
+ register(server);
78
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Slack API Types
3
+ * Based on Slack Web API responses
4
+ */
5
+ export interface Channel {
6
+ id: string;
7
+ name: string;
8
+ is_channel: boolean;
9
+ is_group: boolean;
10
+ is_im: boolean;
11
+ is_mpim: boolean;
12
+ is_private: boolean;
13
+ is_archived: boolean;
14
+ is_general: boolean;
15
+ is_member: boolean;
16
+ topic?: {
17
+ value: string;
18
+ creator: string;
19
+ last_set: number;
20
+ };
21
+ purpose?: {
22
+ value: string;
23
+ creator: string;
24
+ last_set: number;
25
+ };
26
+ num_members?: number;
27
+ created: number;
28
+ creator?: string;
29
+ }
30
+ export interface Message {
31
+ type: string;
32
+ subtype?: string;
33
+ user?: string;
34
+ bot_id?: string;
35
+ text: string;
36
+ ts: string;
37
+ thread_ts?: string;
38
+ reply_count?: number;
39
+ reply_users_count?: number;
40
+ latest_reply?: string;
41
+ reply_users?: string[];
42
+ reactions?: Reaction[];
43
+ attachments?: Attachment[];
44
+ blocks?: Block[];
45
+ edited?: {
46
+ user: string;
47
+ ts: string;
48
+ };
49
+ }
50
+ export interface Reaction {
51
+ name: string;
52
+ count: number;
53
+ users: string[];
54
+ }
55
+ export interface Attachment {
56
+ id?: number;
57
+ fallback?: string;
58
+ color?: string;
59
+ pretext?: string;
60
+ author_name?: string;
61
+ author_link?: string;
62
+ author_icon?: string;
63
+ title?: string;
64
+ title_link?: string;
65
+ text?: string;
66
+ fields?: Array<{
67
+ title: string;
68
+ value: string;
69
+ short: boolean;
70
+ }>;
71
+ image_url?: string;
72
+ thumb_url?: string;
73
+ footer?: string;
74
+ footer_icon?: string;
75
+ ts?: number;
76
+ }
77
+ export interface Block {
78
+ type: string;
79
+ block_id?: string;
80
+ text?: {
81
+ type: string;
82
+ text: string;
83
+ emoji?: boolean;
84
+ };
85
+ elements?: unknown[];
86
+ }
87
+ export interface ThreadWithReplies {
88
+ messages: Message[];
89
+ has_more: boolean;
90
+ response_metadata?: {
91
+ next_cursor?: string;
92
+ };
93
+ }
94
+ export interface User {
95
+ id: string;
96
+ name: string;
97
+ real_name?: string;
98
+ display_name?: string;
99
+ is_bot: boolean;
100
+ is_admin?: boolean;
101
+ profile?: {
102
+ display_name?: string;
103
+ real_name?: string;
104
+ image_48?: string;
105
+ image_72?: string;
106
+ };
107
+ }
108
+ export interface PaginatedResponse<T> {
109
+ items: T[];
110
+ has_more: boolean;
111
+ next_cursor?: string;
112
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Slack API Types
3
+ * Based on Slack Web API responses
4
+ */
5
+ export {};