mirror of
https://github.com/paymog/slack-cli.git
synced 2026-09-18 23:43:49 +08:00
Add bot token (xoxb) support
- Add support for bot tokens as an alternative authentication method - Conditionally register search tool only for non-bot tokens (bots cannot use search.messages API) - Update isOAuth definition to include both xoxp and xoxb tokens for cleaner implementation - Add bot token configuration to manifest-dxt.json for DXT extension - Document bot token limitations in README and authentication setup guide 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
# User OAuth Token (starts with xoxp-)
|
||||||
|
SLACK_MCP_XOXP_TOKEN="" # Replace with your user OAuth token
|
||||||
|
|
||||||
|
# Bot OAuth Token (starts with xoxb-)
|
||||||
|
SLACK_MCP_XOXB_TOKEN="" # Replace with your bot token
|
||||||
|
|
||||||
|
# Session-based tokens (browser tokens)
|
||||||
SLACK_MCP_XOXC_TOKEN="" # Replace with your actual token
|
SLACK_MCP_XOXC_TOKEN="" # Replace with your actual token
|
||||||
SLACK_MCP_XOXD_TOKEN="" # Replace with your actual token
|
SLACK_MCP_XOXD_TOKEN="" # Replace with your actual token
|
||||||
SLACK_MCP_SSE_API_KEY="" # Replace with your actual API key
|
|
||||||
|
# SSE API Key for authentication
|
||||||
|
SLACK_MCP_SSE_API_KEY="" # Replace with your actual API key
|
||||||
@@ -60,6 +60,8 @@ Add a message to a public channel, private channel, or direct message (DM, or IM
|
|||||||
|
|
||||||
### 4. conversations_search_messages
|
### 4. conversations_search_messages
|
||||||
Search messages in a public channel, private channel, or direct message (DM, or IM) conversation using filters. All filters are optional, if not provided then search_query is required.
|
Search messages in a public channel, private channel, or direct message (DM, or IM) conversation using filters. All filters are optional, if not provided then search_query is required.
|
||||||
|
|
||||||
|
> **Note**: This tool is not available when using bot tokens (`xoxb-*`). Bot tokens cannot use the `search.messages` API.
|
||||||
- **Parameters:**
|
- **Parameters:**
|
||||||
- `search_query` (string, optional): Search query to filter messages. Example: 'marketing report' or full URL of Slack message e.g. 'https://slack.com/archives/C1234567890/p1234567890123456', then the tool will return a single message matching given URL, herewith all other parameters will be ignored.
|
- `search_query` (string, optional): Search query to filter messages. Example: 'marketing report' or full URL of Slack message e.g. 'https://slack.com/archives/C1234567890/p1234567890123456', then the tool will return a single message matching given URL, herewith all other parameters will be ignored.
|
||||||
- `filter_in_channel` (string, optional): Filter messages in a specific channel by its ID or name. Example: `C1234567890` or `#general`. If not provided, all channels will be searched.
|
- `filter_in_channel` (string, optional): Filter messages in a specific channel by its ID or name. Example: `C1234567890` or `#general`. If not provided, all channels will be searched.
|
||||||
@@ -123,6 +125,7 @@ Fetches a CSV directory of all users in the workspace.
|
|||||||
| `SLACK_MCP_XOXC_TOKEN` | Yes* | `nil` | Slack browser token (`xoxc-...`) |
|
| `SLACK_MCP_XOXC_TOKEN` | Yes* | `nil` | Slack browser token (`xoxc-...`) |
|
||||||
| `SLACK_MCP_XOXD_TOKEN` | Yes* | `nil` | Slack browser cookie `d` (`xoxd-...`) |
|
| `SLACK_MCP_XOXD_TOKEN` | Yes* | `nil` | Slack browser cookie `d` (`xoxd-...`) |
|
||||||
| `SLACK_MCP_XOXP_TOKEN` | Yes* | `nil` | User OAuth token (`xoxp-...`) — alternative to xoxc/xoxd |
|
| `SLACK_MCP_XOXP_TOKEN` | Yes* | `nil` | User OAuth token (`xoxp-...`) — alternative to xoxc/xoxd |
|
||||||
|
| `SLACK_MCP_XOXB_TOKEN` | Yes* | `nil` | Bot token (`xoxb-...`) — alternative to xoxp/xoxc/xoxd. Bot has limited access (invited channels only, no search) |
|
||||||
| `SLACK_MCP_PORT` | No | `13080` | Port for the MCP server to listen on |
|
| `SLACK_MCP_PORT` | No | `13080` | Port for the MCP server to listen on |
|
||||||
| `SLACK_MCP_HOST` | No | `127.0.0.1` | Host for the MCP server to listen on |
|
| `SLACK_MCP_HOST` | No | `127.0.0.1` | Host for the MCP server to listen on |
|
||||||
| `SLACK_MCP_API_KEY` | No | `nil` | Bearer token for SSE and HTTP transports |
|
| `SLACK_MCP_API_KEY` | No | `nil` | Bearer token for SSE and HTTP transports |
|
||||||
@@ -139,7 +142,7 @@ Fetches a CSV directory of all users in the workspace.
|
|||||||
| `SLACK_MCP_CHANNELS_CACHE` | No | `.channels_cache_v2.json` | Path to the channels cache file. Used to cache Slack channel information to avoid repeated API calls on startup. |
|
| `SLACK_MCP_CHANNELS_CACHE` | No | `.channels_cache_v2.json` | Path to the channels cache file. Used to cache Slack channel information to avoid repeated API calls on startup. |
|
||||||
| `SLACK_MCP_LOG_LEVEL` | No | `info` | Log-level for stdout or stderr. Valid values are: `debug`, `info`, `warn`, `error`, `panic` and `fatal` |
|
| `SLACK_MCP_LOG_LEVEL` | No | `info` | Log-level for stdout or stderr. Valid values are: `debug`, `info`, `warn`, `error`, `panic` and `fatal` |
|
||||||
|
|
||||||
*You need either `xoxp` **or** both `xoxc`/`xoxd` tokens for authentication.
|
*You need one of: `xoxp` (user), `xoxb` (bot), or both `xoxc`/`xoxd` tokens for authentication.
|
||||||
|
|
||||||
### Limitations matrix & Cache
|
### Limitations matrix & Cache
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
Open up your Slack in your browser and login.
|
Open up your Slack in your browser and login.
|
||||||
|
|
||||||
#### Lookup `SLACK_MCP_XOXC_TOKEN`
|
> **Note**: You only need one of the following: an `xoxp-*` User OAuth token, an `xoxb-*` Bot token, or both `xoxc-*` and `xoxd-*` session tokens. User/Bot tokens are more secure and do not require a browser session. If multiple are provided, priority is `xoxp` > `xoxb` > `xoxc/xoxd`.
|
||||||
|
|
||||||
|
#### Option 1: Using `SLACK_MCP_XOXC_TOKEN`/`SLACK_MCP_XOXD_TOKEN` (Browser session)
|
||||||
|
|
||||||
|
##### Lookup `SLACK_MCP_XOXC_TOKEN`
|
||||||
|
|
||||||
- Open your browser's Developer Console.
|
- Open your browser's Developer Console.
|
||||||
- In Firefox, under `Tools -> Browser Tools -> Web Developer tools` in the menu bar
|
- In Firefox, under `Tools -> Browser Tools -> Web Developer tools` in the menu bar
|
||||||
@@ -16,7 +20,7 @@ Open up your Slack in your browser and login.
|
|||||||
Token value is printed right after the executed command (it starts with
|
Token value is printed right after the executed command (it starts with
|
||||||
`xoxc-`), save it somewhere for now.
|
`xoxc-`), save it somewhere for now.
|
||||||
|
|
||||||
#### Lookup `SLACK_MCP_XOXD_TOKEN`
|
##### Lookup `SLACK_MCP_XOXD_TOKEN`
|
||||||
|
|
||||||
- Switch to "Application" tab and select "Cookies" in the left navigation pane.
|
- Switch to "Application" tab and select "Cookies" in the left navigation pane.
|
||||||
- Find the cookie with the name `d`. That's right, just the letter `d`.
|
- Find the cookie with the name `d`. That's right, just the letter `d`.
|
||||||
@@ -24,7 +28,7 @@ Token value is printed right after the executed command (it starts with
|
|||||||
- Press Ctrl+C or Cmd+C to copy it's value to clipboard.
|
- Press Ctrl+C or Cmd+C to copy it's value to clipboard.
|
||||||
- Save it for later.
|
- Save it for later.
|
||||||
|
|
||||||
#### Alternative: Using `SLACK_MCP_XOXP_TOKEN` (User OAuth)
|
#### Option 2: Using `SLACK_MCP_XOXP_TOKEN` (User OAuth)
|
||||||
|
|
||||||
Instead of using browser-based tokens (`xoxc`/`xoxd`), you can use a User OAuth token:
|
Instead of using browser-based tokens (`xoxc`/`xoxd`), you can use a User OAuth token:
|
||||||
|
|
||||||
@@ -47,6 +51,7 @@ Instead of using browser-based tokens (`xoxc`/`xoxd`), you can use a User OAuth
|
|||||||
3. Install the app to your workspace
|
3. Install the app to your workspace
|
||||||
4. Copy the "User OAuth Token" (starts with `xoxp-`)
|
4. Copy the "User OAuth Token" (starts with `xoxp-`)
|
||||||
|
|
||||||
|
##### App manifest (preconfigured scopes)
|
||||||
To create the app from a manifest with permissions preconfigured, use the following code snippet:
|
To create the app from a manifest with permissions preconfigured, use the following code snippet:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -81,6 +86,17 @@ To create the app from a manifest with permissions preconfigured, use the follow
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**: You only need **either** XOXP token **or** both XOXC/XOXD tokens. XOXP user tokens are more secure and don't require browser session extraction.
|
#### Option 3: Using `SLACK_MCP_XOXB_TOKEN` (Bot Token)
|
||||||
|
|
||||||
|
You can also use a Bot token instead of a User token:
|
||||||
|
|
||||||
|
1. Go to [api.slack.com/apps](https://api.slack.com/apps) and create a new app
|
||||||
|
2. Under "OAuth & Permissions", add Bot Token Scopes (same as User scopes above, except `search:read`)
|
||||||
|
3. Install the app to your workspace
|
||||||
|
4. Copy the "Bot User OAuth Token" (starts with `xoxb-`)
|
||||||
|
5. **Important**: Bot must be invited to channels for access
|
||||||
|
|
||||||
|
> **Note**: Bot tokens cannot use `search.messages` API, so `conversations_search_messages` tool will not be available.
|
||||||
|
|
||||||
|
|
||||||
See next: [Installation](02-installation.md)
|
See next: [Installation](02-installation.md)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ For [Claude Desktop](https://claude.ai/download) users, you can use the DXT exte
|
|||||||
2. Click on the `Extensions` tab.
|
2. Click on the `Extensions` tab.
|
||||||
3. Drag and drop the downloaded .dxt file to install it and click "Install".
|
3. Drag and drop the downloaded .dxt file to install it and click "Install".
|
||||||
5. Fill all required configuration fields
|
5. Fill all required configuration fields
|
||||||
- Authentication method: `xoxc/xoxd` or `xoxp`.
|
- Authentication method: `xoxc/xoxd`, `xoxp`, or `xoxb`.
|
||||||
- Value for `SLACK_MCP_XOXC_TOKEN` and `SLACK_MCP_XOXD_TOKEN` in case of `xoxc/xoxd` method, or `SLACK_MCP_XOXP_TOKEN` in case of `xoxp`.
|
- Value for `SLACK_MCP_XOXC_TOKEN` and `SLACK_MCP_XOXD_TOKEN` in case of `xoxc/xoxd` method, `SLACK_MCP_XOXP_TOKEN` in case of `xoxp`, or `SLACK_MCP_XOXB_TOKEN` in case of `xoxb`.
|
||||||
- You may also enable `Add Message Tool` to allow posting messages to channels.
|
- You may also enable `Add Message Tool` to allow posting messages to channels.
|
||||||
- You may also change User-Agent if needed if you have Enterprise Slack.
|
- You may also change User-Agent if needed if you have Enterprise Slack.
|
||||||
6. Enable MCP Server.
|
6. Enable MCP Server.
|
||||||
@@ -27,6 +27,7 @@ Below are prepared configurations:
|
|||||||
|
|
||||||
- `npx` and `xoxc/xoxd` method: [](cursor://anysphere.cursor-deeplink/mcp/install?name=slack-mcp-server&config=eyJjb21tYW5kIjogIm5weCAteSBzbGFjay1tY3Atc2VydmVyQGxhdGVzdCAtLXRyYW5zcG9ydCBzdGRpbyIsImVudiI6IHsiU0xBQ0tfTUNQX1hPWENfVE9LRU4iOiAieG94Yy0uLi4iLCAiU0xBQ0tfTUNQX1hPWERfVE9LRU4iOiAieG94ZC0uLi4ifSwiZGlzYWJsZWQiOiBmYWxzZSwiYXV0b0FwcHJvdmUiOiBbXX0%3D)
|
- `npx` and `xoxc/xoxd` method: [](cursor://anysphere.cursor-deeplink/mcp/install?name=slack-mcp-server&config=eyJjb21tYW5kIjogIm5weCAteSBzbGFjay1tY3Atc2VydmVyQGxhdGVzdCAtLXRyYW5zcG9ydCBzdGRpbyIsImVudiI6IHsiU0xBQ0tfTUNQX1hPWENfVE9LRU4iOiAieG94Yy0uLi4iLCAiU0xBQ0tfTUNQX1hPWERfVE9LRU4iOiAieG94ZC0uLi4ifSwiZGlzYWJsZWQiOiBmYWxzZSwiYXV0b0FwcHJvdmUiOiBbXX0%3D)
|
||||||
- `npx` and `xoxp` method: [](cursor://anysphere.cursor-deeplink/mcp/install?name=slack-mcp-server&config=eyJjb21tYW5kIjogIm5weCAteSBzbGFjay1tY3Atc2VydmVyQGxhdGVzdCAtLXRyYW5zcG9ydCBzdGRpbyIsImVudiI6IHsiU0xBQ0tfTUNQX1hPWFBfVE9LRU4iOiAieG94cC0uLi4ifSwiZGlzYWJsZWQiOiBmYWxzZSwiYXV0b0FwcHJvdmUiOiBbXX0%3D)
|
- `npx` and `xoxp` method: [](cursor://anysphere.cursor-deeplink/mcp/install?name=slack-mcp-server&config=eyJjb21tYW5kIjogIm5weCAteSBzbGFjay1tY3Atc2VydmVyQGxhdGVzdCAtLXRyYW5zcG9ydCBzdGRpbyIsImVudiI6IHsiU0xBQ0tfTUNQX1hPWFBfVE9LRU4iOiAieG94cC0uLi4ifSwiZGlzYWJsZWQiOiBmYWxzZSwiYXV0b0FwcHJvdmUiOiBbXX0%3D)
|
||||||
|
- `npx` and `xoxb` method: [](cursor://anysphere.cursor-deeplink/mcp/install?name=slack-mcp-server&config=eyJjb21tYW5kIjogIm5weCAteSBzbGFjay1tY3Atc2VydmVyQGxhdGVzdCAtLXRyYW5zcG9ydCBzdGRpbyIsImVudiI6IHsiU0xBQ0tfTUNQX1hPWEJfVE9LRU4iOiAieG94Yi0uLi4ifSwiZGlzYWJsZWQiOiBmYWxzZSwiYXV0b0FwcHJvdmUiOiBbXX0%3D)
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> Remember to replace tokens in the configuration with your own tokens, as they are just examples.
|
> Remember to replace tokens in the configuration with your own tokens, as they are just examples.
|
||||||
@@ -60,7 +61,27 @@ Open your `claude_desktop_config.json` and add the mcp server to the list of `mc
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option 2: Using XOXC/XOXD Tokens**
|
**Option 2: Using XOXB Token (Bot)**
|
||||||
|
``` json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"slack": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"slack-mcp-server@latest",
|
||||||
|
"--transport",
|
||||||
|
"stdio"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"SLACK_MCP_XOXB_TOKEN": "xoxb-..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 3: Using XOXC/XOXD Tokens**
|
||||||
``` json
|
``` json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
|
|||||||
+10
-2
@@ -31,6 +31,7 @@
|
|||||||
"SLACK_MCP_XOXC_TOKEN": "${user_config.xoxc_token}",
|
"SLACK_MCP_XOXC_TOKEN": "${user_config.xoxc_token}",
|
||||||
"SLACK_MCP_XOXD_TOKEN": "${user_config.xoxd_token}",
|
"SLACK_MCP_XOXD_TOKEN": "${user_config.xoxd_token}",
|
||||||
"SLACK_MCP_XOXP_TOKEN": "${user_config.xoxp_token}",
|
"SLACK_MCP_XOXP_TOKEN": "${user_config.xoxp_token}",
|
||||||
|
"SLACK_MCP_XOXB_TOKEN": "${user_config.xoxb_token}",
|
||||||
"SLACK_MCP_USER_AGENT": "${user_config.user_agent}",
|
"SLACK_MCP_USER_AGENT": "${user_config.user_agent}",
|
||||||
"SLACK_MCP_ADD_MESSAGE_TOOL": "${user_config.add_message_tool}",
|
"SLACK_MCP_ADD_MESSAGE_TOOL": "${user_config.add_message_tool}",
|
||||||
"SLACK_MCP_USERS_CACHE": "${HOME}/.users_cache.json",
|
"SLACK_MCP_USERS_CACHE": "${HOME}/.users_cache.json",
|
||||||
@@ -51,8 +52,8 @@
|
|||||||
"user_config": {
|
"user_config": {
|
||||||
"auth_method": {
|
"auth_method": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"title": "Authentication Method: xoxc/xoxd or xoxp",
|
"title": "Authentication Method: xoxc/xoxd, xoxp, or xoxb",
|
||||||
"description": "Select the authentication method for the Slack MCP Server. You can choose between 'xoxc/xoxd' (browser based) or 'xoxp' (OAuth2).",
|
"description": "Select the authentication method for the Slack MCP Server. You can choose between 'xoxc/xoxd' (browser based), 'xoxp' (User OAuth), or 'xoxb' (Bot OAuth).",
|
||||||
"default": "",
|
"default": "",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
@@ -77,6 +78,13 @@
|
|||||||
"sensitive": true,
|
"sensitive": true,
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
|
"xoxb_token": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Value for xoxb token (Bot)",
|
||||||
|
"description": "Bot OAuth token for channel-specific automation. Bot must be invited to channels for access. Note: Search functionality is not available with bot tokens.",
|
||||||
|
"sensitive": true,
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
"user_agent": {
|
"user_agent": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"title": "Value for user agent",
|
"title": "Value for user agent",
|
||||||
|
|||||||
+57
-6
@@ -79,6 +79,7 @@ type MCPSlackClient struct {
|
|||||||
|
|
||||||
isEnterprise bool
|
isEnterprise bool
|
||||||
isOAuth bool
|
isOAuth bool
|
||||||
|
isBotToken bool
|
||||||
teamEndpoint string
|
teamEndpoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +136,13 @@ func NewMCPSlackClient(authProvider auth.Provider, logger *zap.Logger) (*MCPSlac
|
|||||||
}
|
}
|
||||||
|
|
||||||
isEnterprise := authResp.EnterpriseID != ""
|
isEnterprise := authResp.EnterpriseID != ""
|
||||||
|
token := authProvider.SlackToken()
|
||||||
|
|
||||||
|
// Token type detection
|
||||||
|
// isOAuth: Official OAuth tokens (xoxp or xoxb) - uses Standard API
|
||||||
|
// isBotToken: Bot token - determines feature availability (e.g., search)
|
||||||
|
isOAuth := strings.HasPrefix(token, "xoxp-") || strings.HasPrefix(token, "xoxb-")
|
||||||
|
isBotToken := strings.HasPrefix(token, "xoxb-")
|
||||||
|
|
||||||
return &MCPSlackClient{
|
return &MCPSlackClient{
|
||||||
slackClient: slackClient,
|
slackClient: slackClient,
|
||||||
@@ -142,7 +150,8 @@ func NewMCPSlackClient(authProvider auth.Provider, logger *zap.Logger) (*MCPSlac
|
|||||||
authResponse: authResponse,
|
authResponse: authResponse,
|
||||||
authProvider: authProvider,
|
authProvider: authProvider,
|
||||||
isEnterprise: isEnterprise,
|
isEnterprise: isEnterprise,
|
||||||
isOAuth: strings.HasPrefix(authProvider.SlackToken(), "xoxp-"),
|
isOAuth: isOAuth,
|
||||||
|
isBotToken: isBotToken,
|
||||||
teamEndpoint: authResp.URL,
|
teamEndpoint: authResp.URL,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -268,6 +277,10 @@ func (c *MCPSlackClient) AuthResponse() *slack.AuthTestResponse {
|
|||||||
return c.authResponse
|
return c.authResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MCPSlackClient) IsBotToken() bool {
|
||||||
|
return c.isBotToken
|
||||||
|
}
|
||||||
|
|
||||||
func (c *MCPSlackClient) Raw() struct {
|
func (c *MCPSlackClient) Raw() struct {
|
||||||
Slack *slack.Client
|
Slack *slack.Client
|
||||||
Edge *edge.Client
|
Edge *edge.Client
|
||||||
@@ -287,8 +300,23 @@ func New(transport string, logger *zap.Logger) *ApiProvider {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check for XOXP token first (User OAuth)
|
// Read all environment variables
|
||||||
xoxpToken := os.Getenv("SLACK_MCP_XOXP_TOKEN")
|
xoxpToken := os.Getenv("SLACK_MCP_XOXP_TOKEN")
|
||||||
|
xoxbToken := os.Getenv("SLACK_MCP_XOXB_TOKEN")
|
||||||
|
xoxcToken := os.Getenv("SLACK_MCP_XOXC_TOKEN")
|
||||||
|
xoxdToken := os.Getenv("SLACK_MCP_XOXD_TOKEN")
|
||||||
|
|
||||||
|
// Warn if both user and bot tokens are set
|
||||||
|
if xoxpToken != "" && xoxbToken != "" {
|
||||||
|
logger.Warn(
|
||||||
|
"Both SLACK_MCP_XOXP_TOKEN and SLACK_MCP_XOXB_TOKEN are set. "+
|
||||||
|
"Using User token (xoxp) for full features. "+
|
||||||
|
"Bot token will be ignored.",
|
||||||
|
zap.String("context", "console"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 1: XOXP token (User OAuth)
|
||||||
if xoxpToken != "" {
|
if xoxpToken != "" {
|
||||||
authProvider, err = auth.NewValueAuth(xoxpToken, "")
|
authProvider, err = auth.NewValueAuth(xoxpToken, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -298,12 +326,24 @@ func New(transport string, logger *zap.Logger) *ApiProvider {
|
|||||||
return newWithXOXP(transport, authProvider, logger)
|
return newWithXOXP(transport, authProvider, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to XOXC/XOXD tokens (session-based)
|
// Priority 2: XOXB token (Bot)
|
||||||
xoxcToken := os.Getenv("SLACK_MCP_XOXC_TOKEN")
|
if xoxbToken != "" {
|
||||||
xoxdToken := os.Getenv("SLACK_MCP_XOXD_TOKEN")
|
authProvider, err = auth.NewValueAuth(xoxbToken, "")
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("Failed to create auth provider with XOXB token", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Using Bot token authentication",
|
||||||
|
zap.String("context", "console"),
|
||||||
|
zap.String("token_type", "xoxb"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return newWithXOXB(transport, authProvider, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 3: XOXC/XOXD tokens (session-based)
|
||||||
if xoxcToken == "" || xoxdToken == "" {
|
if xoxcToken == "" || xoxdToken == "" {
|
||||||
logger.Fatal("Authentication required: Either SLACK_MCP_XOXP_TOKEN (User OAuth) or both SLACK_MCP_XOXC_TOKEN and SLACK_MCP_XOXD_TOKEN (session-based) environment variables must be provided")
|
logger.Fatal("Authentication required: Either SLACK_MCP_XOXP_TOKEN, SLACK_MCP_XOXB_TOKEN, or both SLACK_MCP_XOXC_TOKEN and SLACK_MCP_XOXD_TOKEN must be provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
authProvider, err = auth.NewValueAuth(xoxcToken, xoxdToken)
|
authProvider, err = auth.NewValueAuth(xoxcToken, xoxdToken)
|
||||||
@@ -356,6 +396,12 @@ func newWithXOXP(transport string, authProvider auth.ValueAuth, logger *zap.Logg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newWithXOXB(transport string, authProvider auth.ValueAuth, logger *zap.Logger) *ApiProvider {
|
||||||
|
// Bot tokens do not support demo mode, but otherwise share the same
|
||||||
|
// initialization logic as user OAuth tokens.
|
||||||
|
return newWithXOXP(transport, authProvider, logger)
|
||||||
|
}
|
||||||
|
|
||||||
func newWithXOXC(transport string, authProvider auth.ValueAuth, logger *zap.Logger) *ApiProvider {
|
func newWithXOXC(transport string, authProvider auth.ValueAuth, logger *zap.Logger) *ApiProvider {
|
||||||
var (
|
var (
|
||||||
client *MCPSlackClient
|
client *MCPSlackClient
|
||||||
@@ -676,6 +722,11 @@ func (ap *ApiProvider) Slack() SlackAPI {
|
|||||||
return ap.client
|
return ap.client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ap *ApiProvider) IsBotToken() bool {
|
||||||
|
client, ok := ap.client.(*MCPSlackClient)
|
||||||
|
return ok && client != nil && client.IsBotToken()
|
||||||
|
}
|
||||||
|
|
||||||
func mapChannel(
|
func mapChannel(
|
||||||
id, name, nameNormalized, topic, purpose, user string,
|
id, name, nameNormalized, topic, purpose, user string,
|
||||||
members []string,
|
members []string,
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func NewMCPServer(provider *provider.ApiProvider, logger *zap.Logger) *MCPServer
|
|||||||
),
|
),
|
||||||
), conversationsHandler.ConversationsAddMessageHandler)
|
), conversationsHandler.ConversationsAddMessageHandler)
|
||||||
|
|
||||||
s.AddTool(mcp.NewTool("conversations_search_messages",
|
conversationsSearchTool := mcp.NewTool("conversations_search_messages",
|
||||||
mcp.WithDescription("Search messages in a public channel, private channel, or direct message (DM, or IM) conversation using filters. All filters are optional, if not provided then search_query is required."),
|
mcp.WithDescription("Search messages in a public channel, private channel, or direct message (DM, or IM) conversation using filters. All filters are optional, if not provided then search_query is required."),
|
||||||
mcp.WithString("search_query",
|
mcp.WithString("search_query",
|
||||||
mcp.Description("Search query to filter messages. Example: 'marketing report' or full URL of Slack message e.g. 'https://slack.com/archives/C1234567890/p1234567890123456', then the tool will return a single message matching given URL, herewith all other parameters will be ignored."),
|
mcp.Description("Search query to filter messages. Example: 'marketing report' or full URL of Slack message e.g. 'https://slack.com/archives/C1234567890/p1234567890123456', then the tool will return a single message matching given URL, herewith all other parameters will be ignored."),
|
||||||
@@ -133,7 +133,11 @@ func NewMCPServer(provider *provider.ApiProvider, logger *zap.Logger) *MCPServer
|
|||||||
mcp.DefaultNumber(20),
|
mcp.DefaultNumber(20),
|
||||||
mcp.Description("The maximum number of items to return. Must be an integer between 1 and 100."),
|
mcp.Description("The maximum number of items to return. Must be an integer between 1 and 100."),
|
||||||
),
|
),
|
||||||
), conversationsHandler.ConversationsSearchHandler)
|
)
|
||||||
|
// Only register search tool for non-bot tokens (bot tokens cannot use search.messages API)
|
||||||
|
if !provider.IsBotToken() {
|
||||||
|
s.AddTool(conversationsSearchTool, conversationsHandler.ConversationsSearchHandler)
|
||||||
|
}
|
||||||
|
|
||||||
channelsHandler := handler.NewChannelsHandler(provider, logger)
|
channelsHandler := handler.NewChannelsHandler(provider, logger)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user