A scalable, multi-tenant platform for hosting MCP (Model Context Protocol) servers with OAuth integration and connector plugins for various services. Built for seamless integration with Claude Desktop and other MCP clients.
- Multi-Tenant Architecture: Path-based tenant isolation (
yourdomain.com/tenant1/mcp
) - MCP Protocol Compliance: Full WebSocket, HTTP, and SSE transport with Claude Desktop compatibility
- OAuth 2.0 Integration: Secure authentication for GitHub, GitLab, Google, and other services
- Plugin System: Extensible connector architecture for easy service integration
- Built-in Connectors:
- β GitHub - Full repository access, issues, PRs, file content, search
- π§ GitLab, Google Docs, Notion (coming soon)
- Web Management Interface: React-based frontend for tenant and connector management
- Flexible Database Support: PostgreSQL and Supabase with robust data persistence using SQLAlchemy
- Docker Support: Complete containerization for development and production
- Kubernetes Ready: Helm charts for cloud deployment with database provider flexibility
- Admin API: RESTful API for tenant and connector management
- Real-time Debugging: Token scope checking and connection diagnostics
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β MCP Client βββββΊβ FastAPI App βββββΊβ Connectors β
β (Claude Desktop)β β β β β
GitHub β
βββββββββββββββββββ β βββββββββββββ β β π§ GitLab β
β βMulti-Tenantβ β β π§ Notion β
βββββββββββββββββββ β β Router β β β π§ Slack β
β React Frontend βββββΊβ βββββββββββββ β β + Custom β
β (Web Interface) β β β βββββββββββββββββββ
βββββββββββββββββββ β βββββββββββββ β
β βOAuth Flow β β βββββββββββββββββββ
βββββββββββββββββββ β β & Tokens β βββββΊβ PostgreSQL/ β
β OAuth Provider βββββΊβ βββββββββββββ β β Supabase β
β (GitHub, etc) β βββββββββββββββββββ βββββββββββββββββββ
βββββββββββββββββββ
- Docker and Docker Compose
- Python 3.11+ (for local development)
- Database: PostgreSQL (included in Docker setup) or Supabase (hosted)
-
Clone and setup:
git clone <repository-url> cd sage-mcp make setup
-
Configure OAuth (optional):
cp .env.example .env # Edit .env with your OAuth credentials
-
Start the platform:
make up
-
Access the services:
- Frontend: http://localhost:3001 (React management interface)
- API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Database Admin: http://localhost:8080 (Adminer)
- Health Check: http://localhost:8000/health
-
Install dependencies:
pip install -e .
-
Setup database:
# Start PostgreSQL docker-compose up postgres -d
-
Run the application:
uvicorn sage_mcp.main:app --reload
- Open the frontend: http://localhost:3001
- Create a tenant using the web interface
- Add connectors and configure OAuth credentials
- Copy the MCP server URL for your Claude Desktop configuration
Add to your Claude Desktop configuration:
{
"mcpServers": {
"sage-mcp": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"],
"env": {
"MCP_SERVER_URL": "ws://localhost:8000/api/v1/{tenant-slug}/mcp"
}
}
}
}
Or use the HTTP endpoint:
http://localhost:8000/api/v1/{tenant-slug}/mcp
Once GitHub OAuth is configured, you'll have access to 24 comprehensive tools:
Repository Management (6 tools):
github_list_repositories
- List accessible repositories with filtersgithub_get_repository
- Get detailed repository informationgithub_search_repositories
- Search repositories by querygithub_get_repo_stats
- Get repository statistics and languagesgithub_list_contributors
- List contributors with contribution countsgithub_get_file_content
- Get file content from repositories
Commits & Code Changes (3 tools):
github_list_commits
- List commits with filters (author, date, path)github_get_commit
- Get commit details including diffs and statsgithub_compare_commits
- Compare branches or commits
Branch Management (2 tools):
github_list_branches
- List repository branchesgithub_get_branch
- Get branch details and protection status
Issues & Pull Requests (2 tools):
github_list_issues
- List repository issues with filtersgithub_list_pull_requests
- List pull requests with filters
User Information & Activity (4 tools):
github_get_user_info
- Get user profile and repositoriesgithub_get_user_stats
- Get comprehensive user statisticsgithub_get_user_activity
- Get recent user activity eventsgithub_list_organizations
- List user's organizations
GitHub Actions / Workflows (3 tools):
github_list_workflows
- List repository workflowsgithub_list_workflow_runs
- List workflow run historygithub_get_workflow_run
- Get detailed workflow run information
Releases (2 tools):
github_list_releases
- List repository releasesgithub_get_release
- Get release details and assets
OAuth & Debugging (2 tools):
github_check_token_scopes
- Debug OAuth token permissionsgithub_list_organizations
- List accessible organizations
curl -X POST "http://localhost:8000/api/v1/admin/tenants" \
-H "Content-Type: application/json" \
-d '{
"slug": "acme-corp",
"name": "ACME Corporation",
"description": "ACME Corp tenant",
"contact_email": "admin@acme.com"
}'
curl -X POST "http://localhost:8000/api/v1/admin/tenants/acme-corp/connectors" \
-H "Content-Type: application/json" \
-d '{
"connector_type": "github",
"name": "ACME GitHub",
"description": "GitHub integration for ACME"
}'
Use the included PostgreSQL Docker container for local development:
# Default configuration (already in .env)
DATABASE_PROVIDER=postgresql
DATABASE_URL=postgresql://sage_mcp:password@localhost:5432/sage_mcp
Use Supabase as a managed PostgreSQL alternative:
- Create a Supabase project at supabase.com
- Configure your environment:
# Update your .env file DATABASE_PROVIDER=supabase SUPABASE_URL=https://your-project.supabase.co SUPABASE_SERVICE_ROLE_KEY=your-service-role-key # SUPABASE_ANON_KEY is optional for direct database access
- Disable local PostgreSQL in docker-compose (optional):
# Comment out postgres service dependencies if using Supabase docker-compose up app frontend -d
Benefits of Supabase:
- β Hosted PostgreSQL with automatic backups
- β Built-in authentication and real-time features
- β Global CDN and edge functions
- β Automatic SSL and security
- β No local database setup required
# Application
DEBUG=true
ENVIRONMENT=development
HOST=0.0.0.0
PORT=8000
# Database Configuration
DATABASE_PROVIDER=postgresql # Options: postgresql, supabase
DATABASE_URL=postgresql://user:pass@localhost:5432/sage_mcp
# Supabase Configuration (only needed if DATABASE_PROVIDER=supabase)
# SUPABASE_URL=https://your-project.supabase.co
# SUPABASE_ANON_KEY=your-anon-key
# SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Note: Redis dependency has been removed for simplicity
# Security
SECRET_KEY=your-secret-key
# Base URL Configuration
BASE_URL=http://localhost:8000
# Public URL (for OAuth callbacks with tunneling services like ngrok)
# When using ngrok or similar tunneling services for OAuth testing,
# set this to your public URL. If not set, the application will use
# BASE_URL or detect from request headers.
# Example: PUBLIC_URL=https://your-ngrok-url.ngrok-free.app
PUBLIC_URL=
# OAuth - GitHub
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# OAuth - GitLab
GITLAB_CLIENT_ID=your-gitlab-client-id
GITLAB_CLIENT_SECRET=your-gitlab-client-secret
# OAuth - Google
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# OAuth - Slack
SLACK_CLIENT_ID=your-slack-client-id
SLACK_CLIENT_SECRET=your-slack-client-secret
Some OAuth providers (like Slack) don't accept localhost
or http://
URLs for callback URLs. To test OAuth locally with these providers, use ngrok:
-
Install and start ngrok:
# Install ngrok (https://ngrok.com/download) # Start ngrok tunnel to your frontend ngrok http 3001
-
Configure PUBLIC_URL:
# Add to your .env file PUBLIC_URL=https://your-ngrok-url.ngrok-free.app
-
Restart the application:
docker-compose down docker-compose up -d
-
Update OAuth app settings: Use your ngrok URL in the OAuth provider's callback URL settings
Note: The PUBLIC_URL
environment variable ensures that OAuth redirect URIs use your public ngrok URL instead of localhost, which is required by providers like Slack.
- Go to GitHub Settings > Developer settings > OAuth Apps
- Create a new OAuth App with these settings:
- Application name: Your app name
- Homepage URL:
http://localhost:3001
(or your ngrok URL) - Authorization callback URL:
http://localhost:3001/oauth/success
(or your ngrok URL +/oauth/success
)
- Copy Client ID and Client Secret to your
.env
file - Important: For organization repositories, ensure your OAuth app has organization access:
- Organization Settings > Third-party access > Grant access to your OAuth app
Required Scopes: repo
, user:email
, read:org
- Go to GitLab Settings > Applications
- Create a new application
- Set Redirect URI to:
http://localhost:8000/api/v1/oauth/{tenant}/callback/gitlab
(or use your ngrok URL) - Copy Application ID and Secret to your
.env
file
- Go to Slack API Dashboard
- Create a new app or select an existing one
- Navigate to OAuth & Permissions
- Add Redirect URL:
https://your-ngrok-url.ngrok-free.app/api/v1/oauth/{tenant}/callback/slack
- Important: Slack requires HTTPS URLs, so you must use ngrok or another tunneling service
- Under Bot Token Scopes, add these scopes:
channels:history
channels:read
chat:write
users:read
team:read
reactions:read
reactions:write
- Copy Client ID and Client Secret to your
.env
file asSLACK_CLIENT_ID
andSLACK_CLIENT_SECRET
- Install the app to your workspace
Important: Make sure the scopes in your Slack app settings exactly match the scopes requested by the application.
-
Create connector class:
# src/sage_mcp/connectors/myservice.py from .base import BaseConnector from .registry import register_connector from ..models.connector import ConnectorType @register_connector(ConnectorType.MYSERVICE) class MyServiceConnector(BaseConnector): @property def display_name(self) -> str: return "My Service" @property def description(self) -> str: return "Integration with My Service" @property def requires_oauth(self) -> bool: return True async def get_tools(self, connector, oauth_cred=None): # Return list of MCP tools pass async def execute_tool(self, connector, tool_name, arguments, oauth_cred=None): # Execute tool logic pass
-
Add to connector enum:
# src/sage_mcp/models/connector.py class ConnectorType(enum.Enum): # ... existing types MYSERVICE = "myservice"
-
Import in main app:
# src/sage_mcp/main.py from .connectors import myservice # noqa
make up
The project includes comprehensive Helm charts for production deployment with flexible database options:
# Install with default PostgreSQL
helm install sage-mcp ./helm
# Install with Supabase backend
helm install sage-mcp ./helm \
--set database.provider=supabase \
--set postgresql.enabled=false \
--set supabase.url=https://your-project.supabase.co \
--set supabase.serviceRoleKey=your-service-role-key
Helm Configuration Options:
database.provider
:postgresql
orsupabase
postgresql.enabled
: Enable/disable PostgreSQL chart dependencysupabase.url
: Your Supabase project URLsupabase.serviceRoleKey
: Supabase service role key for database access
The project uses SQLite in-memory database for testing to simplify setup and improve speed:
# Install dev dependencies
pip install -e ".[dev]"
# Run backend tests
pytest tests/ -v --cov=src/sage_mcp --cov-report=term
# Run specific test
pytest tests/unit/test_config.py -v
The project includes comprehensive GitHub Actions workflows for automated testing and validation.
π View CI/CD Documentation for detailed information about:
- Continuous Integration pipeline
- Pull Request checks
- Release management
- Dependabot configuration
make help # Show all available commands
make build # Build Docker images
make up # Start all services
make down # Stop all services
make logs # View logs from all services
make logs-app # View backend logs only
make logs-frontend # View frontend logs only
make shell # Open shell in app container
make frontend-shell # Open shell in frontend container
make db-shell # Open PostgreSQL shell
make test # Run all tests (backend + frontend)
make test-backend # Run backend tests only
make test-frontend # Run frontend tests only
make test-coverage # Run tests with coverage reports
make lint # Run linting
make format # Format code
make clean # Clean up containers and volumes
make setup # Initial development setup
sage-mcp/
βββ src/sage_mcp/ # Backend (FastAPI)
β βββ api/ # FastAPI routes (admin, OAuth, MCP)
β βββ auth/ # Authentication handlers
β βββ connectors/ # Connector plugins
β β βββ github.py # β
GitHub integration
β β βββ gitlab.py # π§ GitLab (coming soon)
β β βββ base.py # Base connector class
β βββ database/ # Database utilities
β βββ mcp/ # MCP protocol implementation
β β βββ server.py # MCP server logic
β β βββ transport.py # WebSocket/HTTP transport
β βββ models/ # SQLAlchemy models
β βββ config.py # Configuration
β βββ main.py # Application entry point
βββ tests/ # Backend tests
β βββ unit/ # Unit tests
β βββ integration/ # Integration tests
β βββ conftest.py # Test configuration
βββ frontend/ # Frontend (React + TypeScript)
β βββ src/
β β βββ components/ # React components
β β βββ pages/ # Page components
β β βββ hooks/ # Custom React hooks
β β βββ utils/ # Utilities
β β βββ test/ # Test utilities and setup
β βββ package.json # Node.js dependencies
β βββ vite.config.ts # Vite configuration
β βββ vitest.config.ts # Test configuration
βββ helm/ # Kubernetes Helm charts
βββ docker-compose.yml # Local development setup
βββ Dockerfile # Backend container
βββ pyproject.toml # Python project config
βββ requirements.txt # Python dependencies
βββ LICENSE # Apache 2.0 License
βββ Makefile # Development commands
- OAuth 2.0 for secure service authentication with proper scope management
- Tenant isolation at the database and application level
- Secure credential storage with proper encryption for access tokens
- Rate limiting and request validation
- CORS and security headers configured
- Organization access control for GitHub repositories
- Token scope validation and debugging tools
- Health check endpoint:
/health
- Structured logging with request tracing
- Database connection monitoring
- OAuth token expiration tracking
- Real-time debugging tools:
github_check_token_scopes
- Validate OAuth permissionsgithub_list_organizations
- Check organization access- Detailed error messages for 403/auth issues
- MCP protocol compliance validation
- Connection diagnostics for Claude Desktop integration
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
Apache 2.0 License - see LICENSE file for details.
- Documentation: [Coming soon]
- Issues: [GitHub Issues]
- Email: support@sage-mcp.com
β Production Ready Features:
- Multi-tenant MCP server platform
- GitHub connector with full OAuth integration
- React-based management interface
- Claude Desktop compatible MCP protocol
- Flexible database backends (PostgreSQL/Supabase)
- Production-ready Helm charts with database provider options
- Organization repository access
- Real-time debugging and diagnostics
π§ In Development:
- GitLab connector
- Google Docs connector
- Notion connector
- Advanced connector configuration
- Additional database providers (MongoDB, DynamoDB)
π Recent Updates:
- β Supabase Support - Added hosted PostgreSQL alternative with intelligent URL generation
- β Flexible Database Configuration - Support for both PostgreSQL and Supabase backends
- β Enhanced Helm Charts - Production deployment with database provider options
- β All tests passing (40/40) with SQLite in-memory database
- β Simplified CI/CD with no PostgreSQL service required
- β Improved test coverage (41%) and automated quality checks
- Fixed MCP protocol compliance for Claude Desktop
- Implemented proper OAuth scope handling for organizations
- Added token debugging and diagnostic tools
- Updated tool names to follow MCP naming conventions
- Cleaned response format to eliminate validation errors
- Removed unused Redis dependency for simplified architecture
- Added comprehensive test suite (backend: pytest, frontend: vitest)
- Created Apache 2.0 license
- Enhanced development workflow with improved Makefile commands
Built with β€οΈ using FastAPI, SQLAlchemy, React, and the MCP protocol.