Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ca4a3cf
feat: scaffold ai/slackbot-mcp-client directory structure
zimeg Jun 16, 2026
9ca5919
feat: track .env.example files for MCP client examples
zimeg Jun 16, 2026
1974f67
feat(no-auth): implement Bolt + MCP dice game server
zimeg Jun 16, 2026
074eccd
test(no-auth): add integration tests for dice game MCP server
zimeg Jun 16, 2026
f5f3e28
feat(slack-identity): implement Bolt + MCP profile card server
zimeg Jun 16, 2026
57d078a
test(slack-identity): add integration tests, update CI and README
zimeg Jun 16, 2026
5a194ed
fix: add mypy to all examples, fix type errors
zimeg Jun 16, 2026
d45246f
fix: correct DCR link in root README to match directory name
zimeg Jun 16, 2026
e3d33cd
fix: match root README format to JS examples repo
zimeg Jun 16, 2026
4e61225
ci: sort showcase examples alphabetically
zimeg Jun 16, 2026
91800c7
fix: resolve MCP routing, CSP, and host-header issues
zimeg Jun 16, 2026
bebe344
refactor: polish to mirror adjacent example
zimeg Jun 16, 2026
b2c2b8b
refactor: clean up app structure, tests, and dependencies
zimeg Jun 16, 2026
a26e658
style: add missing blank line before class definition
zimeg Jun 16, 2026
a6cac92
fix: correct MCP SDK quickstart link in docstrings
zimeg Jun 16, 2026
6c45bf5
style: remove docstrings and section comments from tests
zimeg Jun 16, 2026
f237146
fix: pin exact dependency versions to match repo convention
zimeg Jun 16, 2026
c5a97ae
test: mirror JS test request IDs and resource assertions
zimeg Jun 16, 2026
3e3eb76
test: match JS Accept header in signed requests
zimeg Jun 16, 2026
e7e1448
refactor: mirror JS sign_request return shape in tests
zimeg Jun 16, 2026
e73d797
docs: clarify ngrok and manifest setup comments
zimeg Jun 16, 2026
c1a0e3d
test: match JS auth.test mock response
zimeg Jun 16, 2026
2a944f1
test: align slack-identity mock data and assertions with JS
zimeg Jun 16, 2026
4832f25
refactor: simplify slack-identity app and align storage dirs with JS
zimeg Jun 17, 2026
2b14b57
style: keep missing-context message on a single line
zimeg Jun 17, 2026
5cb4071
refactor: expect missing auth with inline request handler
zimeg Jun 17, 2026
4b8580e
feat: split rich responses into dedicated examples
zimeg Jun 18, 2026
00794e8
chore: alphabetize dependabot entries and inline install message
zimeg Jun 18, 2026
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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ updates:
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "ai/slackbot-mcp-client/no-auth"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "ai/slackbot-mcp-client/rich-responses/mcp-apps"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "ai/slackbot-mcp-client/slack-identity"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "block-kit"
schedule:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ jobs:
name: "pytest@python3.14"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
showcase:
- "ai/slackbot-mcp-client/no-auth"
- "ai/slackbot-mcp-client/rich-responses/mcp-apps"
- "ai/slackbot-mcp-client/slack-identity"
- "block-kit"
steps:
- name: Checkout code
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

This collections of examples highlights features of a Slack app in the language of Bolt for Python.

## Available demonstration
## Available demonstrations

- **[AI in Slack](./ai)**: Agent experiences and MCP features in an interactive conversation interface.
- **[Block Kit](./block-kit)**: The framework of visual components arranged to create app layouts.
9 changes: 9 additions & 0 deletions ai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# AI in Slack

Agent experiences and MCP features in an interactive conversation interface.

Read the [docs](https://docs.slack.dev/ai/) to learn concepts behind these constructions, or explore implementations of specific features.

## What's on display

- **[Slackbot MCP Client](slackbot-mcp-client/)**: Connect MCP servers to Slackbot with different options for authentication.
18 changes: 18 additions & 0 deletions ai/slackbot-mcp-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Slackbot MCP Client

Connect MCP servers to Slackbot with different options for authentication.

Read the [docs](https://docs.slack.dev/ai/slackbot-mcp-client) to explore more concepts around MCP.

## Included examples

### Authentication methods

- **[Dynamic client registration](https://docs.slack.dev/ai/slackbot-mcp-client#dcr)**: Connect a remote MCP server to the Slackbot MCP client using Dynamic Client Registration (DCR). [Implementation](./dynamic-client-registration/).
- **[External auth](https://docs.slack.dev/ai/slackbot-mcp-client#manual-oauth)**: Connect a remote MCP server to the Slackbot MCP client with manual OAuth provider configuration. [Implementation](./external-auth/).
- **[No auth](https://docs.slack.dev/ai/slackbot-mcp-client#no-auth)**: Run an unauthenticated MCP server for the Slackbot MCP client. [Implementation](./no-auth/).
- **[Slack identity](https://docs.slack.dev/ai/slackbot-mcp-client#slack-identity)**: Run an MCP server for the Slackbot MCP client that authenticates against existing installations. [Implementation](./slack-identity/).

### Rich responses

- **[MCP Apps](https://docs.slack.dev/ai/slackbot-mcp-client/returning-rich-responses#mcp-apps)**: Run an MCP server for the Slackbot MCP client that responds with an interactive UI. [Implementation](./rich-responses/mcp-apps/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
apps.dev.json
cache/
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"manifest": {
"source": "local"
},
"project_id": "00000000-0000-0000-0000-000000000000"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"get-manifest": "cat manifest.json #"
}
}
11 changes: 11 additions & 0 deletions ai/slackbot-mcp-client/dynamic-client-registration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Dynamic Client Registration

Connect a remote MCP server to the Slackbot MCP client using [Dynamic Client Registration](https://blog.modelcontextprotocol.io/posts/client_registration/) (DCR).

## Setup

```sh
$ slack install --environment deployed # Create Slack app
```

Ask Slackbot: "Find all active documents in my Notion workspace"
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"display_information": {
"name": "MCP Client - DCR",
"description": "Connects Notion MCP server to Slackbot MCP client using dynamic client registration"
},
"features": {
"bot_user": {
"display_name": "MCP Client - DCR",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": ["mcp:connect"]
}
},
"settings": {
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": false
},
"mcp_servers": {
"Notion": {
"url": "https://mcp.notion.com/mcp",
"auth_type": "dynamic_client_registration"
}
}
}
2 changes: 2 additions & 0 deletions ai/slackbot-mcp-client/external-auth/.slack/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
apps.dev.json
cache/
6 changes: 6 additions & 0 deletions ai/slackbot-mcp-client/external-auth/.slack/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"manifest": {
"source": "local"
},
"project_id": "00000000-0000-0000-0000-000000000000"
}
5 changes: 5 additions & 0 deletions ai/slackbot-mcp-client/external-auth/.slack/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"get-manifest": "cat manifest.json #"
}
}
16 changes: 16 additions & 0 deletions ai/slackbot-mcp-client/external-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# External Auth

Connect a remote MCP server to the Slackbot MCP client with manual OAuth provider configuration.

## Setup

> Callback URL: https://oauth2.slack.com/external/auth/callback
```sh
$ open https://github.com/settings/developers # Create GitHub app
$ slack manifest # Replace values
$ slack install --environment deployed # Create Slack app
$ slack external-auth add-secret
```

Ask Slackbot: "Show me my recent GitHub pull requests"
51 changes: 51 additions & 0 deletions ai/slackbot-mcp-client/external-auth/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"display_information": {
"name": "MCP Client - External Auth",
"description": "Connects GitHub MCP server to Slackbot MCP client using an external auth provider"
},
"features": {
"bot_user": {
"display_name": "MCP Client - External Auth",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": ["mcp:connect"]
}
},
"settings": {
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": false
},
"external_auth_providers": {
"oauth2": {
"github": {
"provider_type": "CUSTOM",
"options": {
"client_id": "YOUR_GITHUB_CLIENT_ID",
"scope": ["repo"],
"provider_name": "GitHub",
"authorization_url": "https://github.com/login/oauth/authorize",
"token_url": "https://github.com/login/oauth/access_token",
"identity_config": {
"url": "https://api.github.com/user",
"account_identifier": "$.login"
},
"use_pkce": false,
"token_url_config": {
"use_basic_auth_scheme": false
}
}
}
}
},
"mcp_servers": {
"GitHub": {
"url": "https://api.githubcopilot.com/mcp/",
"auth_type": "manual_auth",
"auth_provider_key": "github"
}
}
}
3 changes: 3 additions & 0 deletions ai/slackbot-mcp-client/no-auth/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SLACK_BOT_TOKEN=
SLACK_SIGNING_SECRET=
PORT=3000
4 changes: 4 additions & 0 deletions ai/slackbot-mcp-client/no-auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
__pycache__
.venv
.env*
!.env.example
2 changes: 2 additions & 0 deletions ai/slackbot-mcp-client/no-auth/.slack/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
apps.dev.json
cache/
6 changes: 6 additions & 0 deletions ai/slackbot-mcp-client/no-auth/.slack/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"manifest": {
"source": "local"
},
"project_id": "00000000-0000-0000-0000-000000000000"
}
5 changes: 5 additions & 0 deletions ai/slackbot-mcp-client/no-auth/.slack/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"get-hooks": "python3 -m slack_cli_hooks.hooks.get_hooks"
}
}
16 changes: 16 additions & 0 deletions ai/slackbot-mcp-client/no-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# No Auth

Run an unauthenticated MCP server for the Slackbot MCP client.

## Setup

```sh
$ ngrok http 3000 --host-header=rewrite # Update manifest with new URL

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👾 note: This is a requirement to broken app configurations due to unexpected host validation. We prefer to claim proxied requests are from localhost.

$ slack manifest # Review saved values
$ slack install --environment local # Create a new app
$ slack app settings # Gather signing secret
$ slack env set SLACK_SIGNING_SECRET
$ slack run
```

Ask Slackbot: "Roll 2d20"
9 changes: 9 additions & 0 deletions ai/slackbot-mcp-client/no-auth/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import os

import uvicorn

from src.app import app

if __name__ == "__main__":
port = int(os.environ.get("PORT", "3000"))
uvicorn.run(app, host="0.0.0.0", port=port)
28 changes: 28 additions & 0 deletions ai/slackbot-mcp-client/no-auth/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"display_information": {
"name": "MCP Client - No Auth",
"description": "Connects app MCP server to Slackbot MCP client without authentication"
},
"features": {
"bot_user": {
"display_name": "MCP Client - No Auth",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": ["mcp:connect"]
}
},
"settings": {
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": false
},
"mcp_servers": {
"Dice Game": {
"url": "https://1234-56-78-90-0.ngrok-free.app/mcp",
"auth_type": "no_auth"
}
}
}
10 changes: 10 additions & 0 deletions ai/slackbot-mcp-client/no-auth/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
httpx2==2.4.0
mcp==1.27.2
mypy==2.1.0
pytest==9.1.0
ruff==0.15.17
slack_bolt==1.28.0
slack_cli_hooks==0.3.0
slack_sdk==3.42.0
starlette==1.3.1
uvicorn==0.49.0
Empty file.
Loading