mirror of
				https://github.com/open-webui/openapi-servers
				synced 2025-06-26 18:17:04 +00:00 
			
		
		
		
	Delete servers/slack/slack.ts
This commit is contained in:
		
							parent
							
								
									fd91c939f2
								
							
						
					
					
						commit
						fa3eda516e
					
				| @ -1,582 +0,0 @@ | ||||
| #!/usr/bin/env node | ||||
| import { Server } from "@modelcontextprotocol/sdk/server/index.js"; | ||||
| import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; | ||||
| import { | ||||
|   CallToolRequest, | ||||
|   CallToolRequestSchema, | ||||
|   ListToolsRequestSchema, | ||||
|   Tool, | ||||
| } from "@modelcontextprotocol/sdk/types.js"; | ||||
| 
 | ||||
| // Type definitions for tool arguments
 | ||||
| interface ListChannelsArgs { | ||||
|   limit?: number; | ||||
|   cursor?: string; | ||||
| } | ||||
| 
 | ||||
| interface PostMessageArgs { | ||||
|   channel_id: string; | ||||
|   text: string; | ||||
| } | ||||
| 
 | ||||
| interface ReplyToThreadArgs { | ||||
|   channel_id: string; | ||||
|   thread_ts: string; | ||||
|   text: string; | ||||
| } | ||||
| 
 | ||||
| interface AddReactionArgs { | ||||
|   channel_id: string; | ||||
|   timestamp: string; | ||||
|   reaction: string; | ||||
| } | ||||
| 
 | ||||
| interface GetChannelHistoryArgs { | ||||
|   channel_id: string; | ||||
|   limit?: number; | ||||
| } | ||||
| 
 | ||||
| interface GetThreadRepliesArgs { | ||||
|   channel_id: string; | ||||
|   thread_ts: string; | ||||
| } | ||||
| 
 | ||||
| interface GetUsersArgs { | ||||
|   cursor?: string; | ||||
|   limit?: number; | ||||
| } | ||||
| 
 | ||||
| interface GetUserProfileArgs { | ||||
|   user_id: string; | ||||
| } | ||||
| 
 | ||||
| // Tool definitions
 | ||||
| const listChannelsTool: Tool = { | ||||
|   name: "slack_list_channels", | ||||
|   description: "List public or pre-defined channels in the workspace with pagination", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       limit: { | ||||
|         type: "number", | ||||
|         description: | ||||
|           "Maximum number of channels to return (default 100, max 200)", | ||||
|         default: 100, | ||||
|       }, | ||||
|       cursor: { | ||||
|         type: "string", | ||||
|         description: "Pagination cursor for next page of results", | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const postMessageTool: Tool = { | ||||
|   name: "slack_post_message", | ||||
|   description: "Post a new message to a Slack channel", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       channel_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the channel to post to", | ||||
|       }, | ||||
|       text: { | ||||
|         type: "string", | ||||
|         description: "The message text to post", | ||||
|       }, | ||||
|     }, | ||||
|     required: ["channel_id", "text"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const replyToThreadTool: Tool = { | ||||
|   name: "slack_reply_to_thread", | ||||
|   description: "Reply to a specific message thread in Slack", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       channel_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the channel containing the thread", | ||||
|       }, | ||||
|       thread_ts: { | ||||
|         type: "string", | ||||
|         description: "The timestamp of the parent message in the format '1234567890.123456'. Timestamps in the format without the period can be converted by adding the period such that 6 numbers come after it.", | ||||
|       }, | ||||
|       text: { | ||||
|         type: "string", | ||||
|         description: "The reply text", | ||||
|       }, | ||||
|     }, | ||||
|     required: ["channel_id", "thread_ts", "text"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const addReactionTool: Tool = { | ||||
|   name: "slack_add_reaction", | ||||
|   description: "Add a reaction emoji to a message", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       channel_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the channel containing the message", | ||||
|       }, | ||||
|       timestamp: { | ||||
|         type: "string", | ||||
|         description: "The timestamp of the message to react to", | ||||
|       }, | ||||
|       reaction: { | ||||
|         type: "string", | ||||
|         description: "The name of the emoji reaction (without ::)", | ||||
|       }, | ||||
|     }, | ||||
|     required: ["channel_id", "timestamp", "reaction"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const getChannelHistoryTool: Tool = { | ||||
|   name: "slack_get_channel_history", | ||||
|   description: "Get recent messages from a channel", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       channel_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the channel", | ||||
|       }, | ||||
|       limit: { | ||||
|         type: "number", | ||||
|         description: "Number of messages to retrieve (default 10)", | ||||
|         default: 10, | ||||
|       }, | ||||
|     }, | ||||
|     required: ["channel_id"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const getThreadRepliesTool: Tool = { | ||||
|   name: "slack_get_thread_replies", | ||||
|   description: "Get all replies in a message thread", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       channel_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the channel containing the thread", | ||||
|       }, | ||||
|       thread_ts: { | ||||
|         type: "string", | ||||
|         description: "The timestamp of the parent message in the format '1234567890.123456'. Timestamps in the format without the period can be converted by adding the period such that 6 numbers come after it.", | ||||
|       }, | ||||
|     }, | ||||
|     required: ["channel_id", "thread_ts"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const getUsersTool: Tool = { | ||||
|   name: "slack_get_users", | ||||
|   description: | ||||
|     "Get a list of all users in the workspace with their basic profile information", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       cursor: { | ||||
|         type: "string", | ||||
|         description: "Pagination cursor for next page of results", | ||||
|       }, | ||||
|       limit: { | ||||
|         type: "number", | ||||
|         description: "Maximum number of users to return (default 100, max 200)", | ||||
|         default: 100, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| const getUserProfileTool: Tool = { | ||||
|   name: "slack_get_user_profile", | ||||
|   description: "Get detailed profile information for a specific user", | ||||
|   inputSchema: { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|       user_id: { | ||||
|         type: "string", | ||||
|         description: "The ID of the user", | ||||
|       }, | ||||
|     }, | ||||
|     required: ["user_id"], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| class SlackClient { | ||||
|   private botHeaders: { Authorization: string; "Content-Type": string }; | ||||
| 
 | ||||
|   constructor(botToken: string) { | ||||
|     this.botHeaders = { | ||||
|       Authorization: `Bearer ${botToken}`, | ||||
|       "Content-Type": "application/json", | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   async getChannels(limit: number = 100, cursor?: string): Promise<any> { | ||||
|     const predefinedChannelIds = process.env.SLACK_CHANNEL_IDS; | ||||
|     if (!predefinedChannelIds) { | ||||
|       const params = new URLSearchParams({ | ||||
|         types: "public_channel", | ||||
|         exclude_archived: "true", | ||||
|         limit: Math.min(limit, 200).toString(), | ||||
|         team_id: process.env.SLACK_TEAM_ID!, | ||||
|       }); | ||||
|    | ||||
|       if (cursor) { | ||||
|         params.append("cursor", cursor); | ||||
|       } | ||||
|    | ||||
|       const response = await fetch( | ||||
|         `https://slack.com/api/conversations.list?${params}`, | ||||
|         { headers: this.botHeaders }, | ||||
|       ); | ||||
|    | ||||
|       return response.json(); | ||||
|     } | ||||
| 
 | ||||
|     const predefinedChannelIdsArray = predefinedChannelIds.split(",").map((id: string) => id.trim()); | ||||
|     const channels = []; | ||||
| 
 | ||||
|     for (const channelId of predefinedChannelIdsArray) { | ||||
|       const params = new URLSearchParams({ | ||||
|         channel: channelId, | ||||
|       }); | ||||
| 
 | ||||
|       const response = await fetch( | ||||
|         `https://slack.com/api/conversations.info?${params}`, | ||||
|         { headers: this.botHeaders } | ||||
|       ); | ||||
|       const data = await response.json(); | ||||
| 
 | ||||
|       if (data.ok && data.channel && !data.channel.is_archived) { | ||||
|         channels.push(data.channel); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       ok: true, | ||||
|       channels: channels, | ||||
|       response_metadata: { next_cursor: "" }, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   async postMessage(channel_id: string, text: string): Promise<any> { | ||||
|     const response = await fetch("https://slack.com/api/chat.postMessage", { | ||||
|       method: "POST", | ||||
|       headers: this.botHeaders, | ||||
|       body: JSON.stringify({ | ||||
|         channel: channel_id, | ||||
|         text: text, | ||||
|       }), | ||||
|     }); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async postReply( | ||||
|     channel_id: string, | ||||
|     thread_ts: string, | ||||
|     text: string, | ||||
|   ): Promise<any> { | ||||
|     const response = await fetch("https://slack.com/api/chat.postMessage", { | ||||
|       method: "POST", | ||||
|       headers: this.botHeaders, | ||||
|       body: JSON.stringify({ | ||||
|         channel: channel_id, | ||||
|         thread_ts: thread_ts, | ||||
|         text: text, | ||||
|       }), | ||||
|     }); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async addReaction( | ||||
|     channel_id: string, | ||||
|     timestamp: string, | ||||
|     reaction: string, | ||||
|   ): Promise<any> { | ||||
|     const response = await fetch("https://slack.com/api/reactions.add", { | ||||
|       method: "POST", | ||||
|       headers: this.botHeaders, | ||||
|       body: JSON.stringify({ | ||||
|         channel: channel_id, | ||||
|         timestamp: timestamp, | ||||
|         name: reaction, | ||||
|       }), | ||||
|     }); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async getChannelHistory( | ||||
|     channel_id: string, | ||||
|     limit: number = 10, | ||||
|   ): Promise<any> { | ||||
|     const params = new URLSearchParams({ | ||||
|       channel: channel_id, | ||||
|       limit: limit.toString(), | ||||
|     }); | ||||
| 
 | ||||
|     const response = await fetch( | ||||
|       `https://slack.com/api/conversations.history?${params}`, | ||||
|       { headers: this.botHeaders }, | ||||
|     ); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async getThreadReplies(channel_id: string, thread_ts: string): Promise<any> { | ||||
|     const params = new URLSearchParams({ | ||||
|       channel: channel_id, | ||||
|       ts: thread_ts, | ||||
|     }); | ||||
| 
 | ||||
|     const response = await fetch( | ||||
|       `https://slack.com/api/conversations.replies?${params}`, | ||||
|       { headers: this.botHeaders }, | ||||
|     ); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async getUsers(limit: number = 100, cursor?: string): Promise<any> { | ||||
|     const params = new URLSearchParams({ | ||||
|       limit: Math.min(limit, 200).toString(), | ||||
|       team_id: process.env.SLACK_TEAM_ID!, | ||||
|     }); | ||||
| 
 | ||||
|     if (cursor) { | ||||
|       params.append("cursor", cursor); | ||||
|     } | ||||
| 
 | ||||
|     const response = await fetch(`https://slack.com/api/users.list?${params}`, { | ||||
|       headers: this.botHeaders, | ||||
|     }); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| 
 | ||||
|   async getUserProfile(user_id: string): Promise<any> { | ||||
|     const params = new URLSearchParams({ | ||||
|       user: user_id, | ||||
|       include_labels: "true", | ||||
|     }); | ||||
| 
 | ||||
|     const response = await fetch( | ||||
|       `https://slack.com/api/users.profile.get?${params}`, | ||||
|       { headers: this.botHeaders }, | ||||
|     ); | ||||
| 
 | ||||
|     return response.json(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| async function main() { | ||||
|   const botToken = process.env.SLACK_BOT_TOKEN; | ||||
|   const teamId = process.env.SLACK_TEAM_ID; | ||||
| 
 | ||||
|   if (!botToken || !teamId) { | ||||
|     console.error( | ||||
|       "Please set SLACK_BOT_TOKEN and SLACK_TEAM_ID environment variables", | ||||
|     ); | ||||
|     process.exit(1); | ||||
|   } | ||||
| 
 | ||||
|   console.error("Starting Slack MCP Server..."); | ||||
|   const server = new Server( | ||||
|     { | ||||
|       name: "Slack MCP Server", | ||||
|       version: "1.0.0", | ||||
|     }, | ||||
|     { | ||||
|       capabilities: { | ||||
|         tools: {}, | ||||
|       }, | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   const slackClient = new SlackClient(botToken); | ||||
| 
 | ||||
|   server.setRequestHandler( | ||||
|     CallToolRequestSchema, | ||||
|     async (request: CallToolRequest) => { | ||||
|       console.error("Received CallToolRequest:", request); | ||||
|       try { | ||||
|         if (!request.params.arguments) { | ||||
|           throw new Error("No arguments provided"); | ||||
|         } | ||||
| 
 | ||||
|         switch (request.params.name) { | ||||
|           case "slack_list_channels": { | ||||
|             const args = request.params | ||||
|               .arguments as unknown as ListChannelsArgs; | ||||
|             const response = await slackClient.getChannels( | ||||
|               args.limit, | ||||
|               args.cursor, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_post_message": { | ||||
|             const args = request.params.arguments as unknown as PostMessageArgs; | ||||
|             if (!args.channel_id || !args.text) { | ||||
|               throw new Error( | ||||
|                 "Missing required arguments: channel_id and text", | ||||
|               ); | ||||
|             } | ||||
|             const response = await slackClient.postMessage( | ||||
|               args.channel_id, | ||||
|               args.text, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_reply_to_thread": { | ||||
|             const args = request.params | ||||
|               .arguments as unknown as ReplyToThreadArgs; | ||||
|             if (!args.channel_id || !args.thread_ts || !args.text) { | ||||
|               throw new Error( | ||||
|                 "Missing required arguments: channel_id, thread_ts, and text", | ||||
|               ); | ||||
|             } | ||||
|             const response = await slackClient.postReply( | ||||
|               args.channel_id, | ||||
|               args.thread_ts, | ||||
|               args.text, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_add_reaction": { | ||||
|             const args = request.params.arguments as unknown as AddReactionArgs; | ||||
|             if (!args.channel_id || !args.timestamp || !args.reaction) { | ||||
|               throw new Error( | ||||
|                 "Missing required arguments: channel_id, timestamp, and reaction", | ||||
|               ); | ||||
|             } | ||||
|             const response = await slackClient.addReaction( | ||||
|               args.channel_id, | ||||
|               args.timestamp, | ||||
|               args.reaction, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_get_channel_history": { | ||||
|             const args = request.params | ||||
|               .arguments as unknown as GetChannelHistoryArgs; | ||||
|             if (!args.channel_id) { | ||||
|               throw new Error("Missing required argument: channel_id"); | ||||
|             } | ||||
|             const response = await slackClient.getChannelHistory( | ||||
|               args.channel_id, | ||||
|               args.limit, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_get_thread_replies": { | ||||
|             const args = request.params | ||||
|               .arguments as unknown as GetThreadRepliesArgs; | ||||
|             if (!args.channel_id || !args.thread_ts) { | ||||
|               throw new Error( | ||||
|                 "Missing required arguments: channel_id and thread_ts", | ||||
|               ); | ||||
|             } | ||||
|             const response = await slackClient.getThreadReplies( | ||||
|               args.channel_id, | ||||
|               args.thread_ts, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_get_users": { | ||||
|             const args = request.params.arguments as unknown as GetUsersArgs; | ||||
|             const response = await slackClient.getUsers( | ||||
|               args.limit, | ||||
|               args.cursor, | ||||
|             ); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           case "slack_get_user_profile": { | ||||
|             const args = request.params | ||||
|               .arguments as unknown as GetUserProfileArgs; | ||||
|             if (!args.user_id) { | ||||
|               throw new Error("Missing required argument: user_id"); | ||||
|             } | ||||
|             const response = await slackClient.getUserProfile(args.user_id); | ||||
|             return { | ||||
|               content: [{ type: "text", text: JSON.stringify(response) }], | ||||
|             }; | ||||
|           } | ||||
| 
 | ||||
|           default: | ||||
|             throw new Error(`Unknown tool: ${request.params.name}`); | ||||
|         } | ||||
|       } catch (error) { | ||||
|         console.error("Error executing tool:", error); | ||||
|         return { | ||||
|           content: [ | ||||
|             { | ||||
|               type: "text", | ||||
|               text: JSON.stringify({ | ||||
|                 error: error instanceof Error ? error.message : String(error), | ||||
|               }), | ||||
|             }, | ||||
|           ], | ||||
|         }; | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   server.setRequestHandler(ListToolsRequestSchema, async () => { | ||||
|     console.error("Received ListToolsRequest"); | ||||
|     return { | ||||
|       tools: [ | ||||
|         listChannelsTool, | ||||
|         postMessageTool, | ||||
|         replyToThreadTool, | ||||
|         addReactionTool, | ||||
|         getChannelHistoryTool, | ||||
|         getThreadRepliesTool, | ||||
|         getUsersTool, | ||||
|         getUserProfileTool, | ||||
|       ], | ||||
|     }; | ||||
|   }); | ||||
| 
 | ||||
|   const transport = new StdioServerTransport(); | ||||
|   console.error("Connecting server to transport..."); | ||||
|   await server.connect(transport); | ||||
| 
 | ||||
|   console.error("Slack MCP Server running on stdio"); | ||||
| } | ||||
| 
 | ||||
| main().catch((error) => { | ||||
|   console.error("Fatal error in main():", error); | ||||
|   process.exit(1); | ||||
| }); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user