Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Slack #13

Merged
merged 2 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

115 changes: 115 additions & 0 deletions src/slack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Slack MCP Server

MCP Server for the Slack API, enabling Claude to interact with Slack workspaces.

## Tools

1. `slack_list_channels`
- List public channels in the workspace
- Optional inputs:
- `limit` (number, default: 100, max: 200): Maximum number of channels to return
- `cursor` (string): Pagination cursor for next page
- Returns: List of channels with their IDs and information

2. `slack_post_message`
- Post a new message to a Slack channel
- Required inputs:
- `channel_id` (string): The ID of the channel to post to
- `text` (string): The message text to post
- Returns: Message posting confirmation and timestamp

3. `slack_reply_to_thread`
- Reply to a specific message thread
- Required inputs:
- `channel_id` (string): The channel containing the thread
- `thread_ts` (string): Timestamp of the parent message
- `text` (string): The reply text
- Returns: Reply confirmation and timestamp

4. `slack_add_reaction`
- Add an emoji reaction to a message
- Required inputs:
- `channel_id` (string): The channel containing the message
- `timestamp` (string): Message timestamp to react to
- `reaction` (string): Emoji name without colons
- Returns: Reaction confirmation

5. `slack_get_channel_history`
- Get recent messages from a channel
- Required inputs:
- `channel_id` (string): The channel ID
- Optional inputs:
- `limit` (number, default: 10): Number of messages to retrieve
- Returns: List of messages with their content and metadata

6. `slack_get_thread_replies`
- Get all replies in a message thread
- Required inputs:
- `channel_id` (string): The channel containing the thread
- `thread_ts` (string): Timestamp of the parent message
- Returns: List of replies with their content and metadata

7. `slack_search_messages`
- Search for messages across channels
- Required inputs:
- `query` (string): The search query
- Optional inputs:
- `count` (number, default: 5): Number of results to return
- Returns: Matching messages with their context

8. `slack_get_users`
- Get list of workspace users with basic profile information
- Optional inputs:
- `cursor` (string): Pagination cursor for next page
- `limit` (number, default: 100, max: 200): Maximum users to return
- Returns: List of users with their basic profiles

9. `slack_get_user_profile`
- Get detailed profile information for a specific user
- Required inputs:
- `user_id` (string): The user's ID
- Returns: Detailed user profile information

## Setup

1. Create a Slack App:
- Visit the [Slack Apps page](https://api.slack.com/apps)
- Click "Create New App"
- Choose "From scratch"
- Name your app and select your workspace

2. Configure Bot Token Scopes:
Navigate to "OAuth & Permissions" and add these scopes:
- `channels:history` - View messages and other content in public channels
- `channels:read` - View basic channel information
- `chat:write` - Send messages as the app
- `reactions:write` - Add emoji reactions to messages
- `users:read` - View users and their basic information

4. Install App to Workspace:
- Click "Install to Workspace" and authorize the app
- Save the "Bot User OAuth Token" that starts with `xoxb-`

5. Get your Team ID (starts with a `T`) by following [this guidance](https://slack.com/help/articles/221769328-Locate-your-Slack-URL-or-ID#find-your-workspace-or-org-id)

### Usage with the Claude Desktop app
Add the following to your `claude_desktop_config.json`:
```json
{
"mcp-server-slack": {
"command": "mcp-server-slack",
"env": {
"SLACK_BOT_TOKEN": "xoxb-your-bot-token",
"SLACK_TEAM_ID": "T01234567"
}
}
}
```

### Troubleshooting

If you encounter permission errors, verify that:
1. All required scopes are added to your Slack app
2. The app is properly installed to your workspace
3. The tokens and workspace ID are correctly copied to your configuration
4. The app has been added to the channels it needs to access
69 changes: 4 additions & 65 deletions src/slack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ interface GetThreadRepliesArgs {
thread_ts: string;
}

interface SearchMessagesArgs {
query: string;
count?: number;
}

interface GetUsersArgs {
cursor?: string;
limit?: number;
Expand Down Expand Up @@ -180,26 +175,6 @@ const getThreadRepliesTool: Tool = {
},
};

const searchMessagesTool: Tool = {
name: "slack_search_messages",
description: "Search for messages across channels",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "The search query",
},
count: {
type: "number",
description: "Number of results to return (default 5)",
default: 5,
},
},
required: ["query"],
},
};

const getUsersTool: Tool = {
name: "slack_get_users",
description:
Expand Down Expand Up @@ -237,17 +212,12 @@ const getUserProfileTool: Tool = {

class SlackClient {
private botHeaders: { Authorization: string; "Content-Type": string };
private userHeaders: { Authorization: string; "Content-Type": string };

constructor(botToken: string, userToken: string) {
constructor(botToken: string) {
this.botHeaders = {
Authorization: `Bearer ${botToken}`,
"Content-Type": "application/json",
};
this.userHeaders = {
Authorization: `Bearer ${userToken}`,
"Content-Type": "application/json",
};
}

async getChannels(limit: number = 100, cursor?: string): Promise<any> {
Expand Down Expand Up @@ -350,20 +320,6 @@ class SlackClient {
return response.json();
}

async searchMessages(query: string, count: number = 5): Promise<any> {
const params = new URLSearchParams({
query: query,
count: count.toString(),
});

const response = await fetch(
`https://slack.com/api/search.messages?${params}`,
{ headers: this.userHeaders },
);

return response.json();
}

async getUsers(limit: number = 100, cursor?: string): Promise<any> {
const params = new URLSearchParams({
limit: Math.min(limit, 200).toString(),
Expand Down Expand Up @@ -398,12 +354,11 @@ class SlackClient {

async function main() {
const botToken = process.env.SLACK_BOT_TOKEN;
const userToken = process.env.SLACK_USER_TOKEN;
const teamId = process.env.SLACK_TEAM_ID;

if (!botToken || !userToken || !teamId) {
if (!botToken || !teamId) {
console.error(
"Please set SLACK_BOT_TOKEN, SLACK_USER_TOKEN, and SLACK_TEAM_ID environment variables",
"Please set SLACK_BOT_TOKEN and SLACK_TEAM_ID environment variables",
);
process.exit(1);
}
Expand All @@ -421,7 +376,7 @@ async function main() {
},
);

const slackClient = new SlackClient(botToken, userToken);
const slackClient = new SlackClient(botToken);

server.setRequestHandler(
CallToolRequestSchema,
Expand Down Expand Up @@ -528,21 +483,6 @@ async function main() {
};
}

case "slack_search_messages": {
const args = request.params
.arguments as unknown as SearchMessagesArgs;
if (!args.query) {
throw new Error("Missing required argument: query");
}
const response = await slackClient.searchMessages(
args.query,
args.count,
);
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(
Expand Down Expand Up @@ -595,7 +535,6 @@ async function main() {
addReactionTool,
getChannelHistoryTool,
getThreadRepliesTool,
searchMessagesTool,
getUsersTool,
getUserProfileTool,
],
Expand Down
2 changes: 1 addition & 1 deletion src/slack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"watch": "tsc --watch"
},
"dependencies": {
"@modelcontextprotocol/sdk": "0.5.0"
"@modelcontextprotocol/sdk": "0.6.0"
},
"devDependencies": {
"shx": "^0.3.4",
Expand Down