Skip to content

feat: add Slack MCP Server support as HTTP Server#47

Merged
mwbrooks merged 28 commits intomainfrom
slack-mcp-server
Apr 7, 2026
Merged

feat: add Slack MCP Server support as HTTP Server#47
mwbrooks merged 28 commits intomainfrom
slack-mcp-server

Conversation

@mwbrooks
Copy link
Copy Markdown
Member

@mwbrooks mwbrooks commented Apr 1, 2026

Type of change

  • New feature
  • Bug fix
  • Documentation

Summary

This pull request adds Slack MCP Server support. The MCP Server currently support User Tokens, so it requires OAuth and a HTTP Server. The goal is to allow Casey to run as a Socket Mode server without the Slack MCP Server or as a HTTP Server with Slack MCP Server support.

  • Add app_oauth.py as an alternative to app.py that starts an HTTP server instead of using Socket Mode.
  • Shared manifest.json for Socket Mode and HTTP configured for ngrok.
  • Update README.md files with setup instructions.
  • Update App Home to display whether Slack MCP Server is disconnected/connected.
  • Update App Home with a "Connect to Slack MCP Server" link.
  • Tweak system prompt to use the Slack MCP Tools to get info.

Reviewers

  • Follow the README.md → HTTP OAuth section for setup
  • Test the Password reset use-case
    • with the Slack MCP, it should find your email address automatically
    • without the Slack MCP, it should ask for your email address

Requirements

  • I have ensured the changes I am contributing align with existing patterns and have tested and linted my code
  • I've read and agree to the Code of Conduct

Add app_oauth.py as an alternative to app.py that starts an HTTP server
instead of using Socket Mode. Include manifest_oauth.json with request
URLs configured for ngrok and update READMEs with setup instructions.
@mwbrooks mwbrooks added the enhancement New feature or request label Apr 1, 2026
mwbrooks and others added 9 commits April 1, 2026 16:22
Add a toggle button to the App Home that tracks account connection state
using an in-memory store. This is a placeholder for the real OAuth flow.
This reverts commit 9fe578d.
Replace the deep-link authorize URL with the standard /slack/install
path for the App Home connect link. Remove the MCP server try/except
fallback from run_casey() to avoid silently dropping all MCP tools on
connection errors. Clean up unused AuthorizeUrlGenerator.
Comment thread pydantic-ai/listeners/events/app_mentioned.py Outdated
Comment thread pydantic-ai/agent/casey.py Outdated
Comment thread pydantic-ai/.gitignore
Comment on lines +42 to +43
# oauth data
data/
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.

question: Is data/ the standard directory name? Or, should we use something more specific?

Comment thread pydantic-ai/oauth.py Outdated
Comment on lines +17 to +26
USER_SCOPES = [
"search:read",
"channels:history",
"channels:read",
"groups:history",
"groups:read",
"im:history",
"mpim:history",
"users:read",
]
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: These scopes should match what's in the manifest file

mwbrooks added 13 commits April 6, 2026 13:18
…ents-sdk

Port all pydantic-ai branch changes to the other two implementations:
- Add Slack MCP Server integration with OAuth user token
- Replace button-based App Home UI with text-based MCP status
- Use AsyncOAuthSettings for claude-agent-sdk's AsyncApp
- Add MCP setup steps to README OAuth sections
- Expand user scopes for MCP capabilities
- Update system prompt with Slack MCP Server section
- Simplify app_home_opened to use context.user_token
RunContextWrapper.context IS the CaseyDeps instance directly — unlike
Pydantic AI's RunContext which has a .deps property. The incorrect
.deps access raised AttributeError silently caught by the SDK.
Prevents accidentally committing App IDs from maintainer environments.
This top-level gitignore is not part of the app templates.
@mwbrooks mwbrooks marked this pull request as ready for review April 7, 2026 18:44
@mwbrooks mwbrooks requested a review from WilliamBergamin April 7, 2026 18:44
mwbrooks added 3 commits April 7, 2026 11:47
Update the agent system prompt and tool descriptions so the agent tries
to look up the user's email from their Slack profile before triggering a
password reset, falling back to asking the user if the lookup fails.
…le file

Merge both manifests into a single manifest.json per directory. The
superset manifest includes user scopes and placeholder URLs using
ngrok-free.app, which validates against Slack's schema. For HTTP/OAuth
mode, developers just set socket_mode_enabled to false and replace
ngrok-free.app with their ngrok domain.
@mwbrooks mwbrooks merged commit 0008a5d into main Apr 7, 2026
7 checks passed
@mwbrooks mwbrooks deleted the slack-mcp-server branch April 7, 2026 22:40
Copy link
Copy Markdown
Contributor

@WilliamBergamin WilliamBergamin left a comment

Choose a reason for hiding this comment

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

Very nice work on this 💯 🚀

Comment on lines +24 to +25
redirect_uri = os.environ.get("SLACK_REDIRECT_URI", "")
install_url = urljoin(redirect_uri, "/slack/install")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice 💯 I like this better then what I did before

Comment thread claude-agent-sdk/oauth.py
@@ -0,0 +1,89 @@
import json
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When working on the project I was wondering if we could actually move this logic at the top of app_oauth.py that way everything is in one file 🤔

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.

I would love to do that! When I originally tried, it caused a circular dependency with app_home_opened.py. But maybe our new approach removed those dependencies entirely 👀 I'll make a note to look.

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.

Great suggestion @WilliamBergamin! I've been able to combine app_oauth.py and oauth.py now, which is much better!

Commit 13a37ea

[tool.ruff.format]

[tool.pytest.ini_options]
asyncio_mode = "auto"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure we need this since the sample uses sync python 🤔

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.

Good call @WilliamBergamin!

Since we use the @pytest.mark.asyncio decorators on the async tests, we can use asyncio_mode = "strict" and because strict is the default, we can remove it entirely. The auto allows async tests to skip the decorator and automatically run as an async test. But generally I prefer the explicit use of the decorator and it's one less configuration setting.

Commit 9fb82fe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants