nathanjclark/mcp-server
If you are the rightful owner of mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Shuttle MCP Server is a comprehensive Model Context Protocol server built using Rust, Axum, and Shuttle, designed for production-ready deployment with advanced features like OAuth 2.1 authentication and AI integration.
Shuttle MCP Server
A complete Model Context Protocol (MCP) server built with Rust, Axum, and Shuttle. This template provides everything you need to build a production-ready MCP server with OAuth 2.1 authentication, database integration, AI tools, and a clean registry-based architecture.
🚀 What You Get
- 🔐 OAuth 2.1 Authentication - Secure authentication via Auth0
- 🗄️ PostgreSQL Database - Managed database with automatic migrations
- 🤖 AI Integration - AI-powered tools via the
rigcrate - 📊 Built-in Tools - Text processing, database queries, timestamps, and more
- 🔧 Registry System - Centralized management of tools, resources, and prompts
- ⚡ Full MCP Compliance - Complete JSON-RPC 2.0 implementation with proper authentication
- 🚀 One-Click Deploy - Deploy to Shuttle with a single command
🏗️ Architecture Overview
This server implements the complete MCP specification with authentication:
┌─────────────────┐ JSON-RPC 2.0 ┌─────────────────┐
│ MCP Client │ ────────────────────▶│ Shuttle MCP │
│ (Claude, etc.) │ │ Server │
│ │ ◄──── Tools ─────────│ │
│ │ ◄── Resources ───────│ 🔐 OAuth 2.1 │
│ │ ◄─── Prompts ────────│ 🗄️ PostgreSQL │
└─────────────────┘ │ 🤖 AI Tools │
└─────────────────┘
Authentication Flow
- Public Methods:
initialize,notifications/initialized,exit - Protected Methods: All tools, resources, and prompts require authentication
- Security: Users authenticate via OAuth 2.1 before accessing any functionality
📋 Prerequisites
-
Rust - Install from rustup.rs
-
Shuttle CLI - Recommended installation method:
# Linux/macOS curl -sSfL https://www.shuttle.dev/install | bash # Windows (PowerShell) # iwr https://www.shuttle.dev/install-win | iex # Alternative: Using Cargo # cargo install cargo-shuttle -
Auth0 Account - Free at auth0.com
-
Docker
🚀 Quick Start
1. Clone and Setup
git clone <this-repo-url>
cd mcp-server
2. Configure Auth0
- Go to Applications and click "Create Application"
- Choose "Regular Web Application"
- Go to connections and enable Google Social Connection
- Note your domain, client ID, and client secret from the application's settings
3. Create Secrets
# Create Secrets.toml in project root
cat > Secrets.toml << EOF
AUTH0_DOMAIN = 'your-tenant.auth0.com'
AUTH0_CLIENT_ID = 'your-client-id'
AUTH0_CLIENT_SECRET = 'your-client-secret'
AUTH0_CALLBACK_URL = 'http://localhost:8000/auth/callback'
SESSION_JWT_SECRET = 'your-very-long-random-secret-key-at-least-32-chars'
OPENAI_API_KEY = 'sk-your-openai-api-key' # Optional
EOF
4. Run Locally
shuttle run
5. Test Your Server
The easiest way to test your MCP server is using the official MCP Inspector - a visual testing tool designed specifically for MCP development.
Using MCP Inspector (Recommended)
The MCP Inspector provides a complete testing interface with no installation required:
# Test the Shuttle server directly
npx @modelcontextprotocol/inspector shuttle run
- Copy session token from CLI ouput after running the above command
- Open MCP Inspector in the Browser
- Choose Streamable HTTP as the transport type.
- Set URL as "http://localhost:8000/mcp"
- Click "Configuration" and then enter the copied session token into the "Proxy Session Token" field.
- Click Connect
- Go the "Auth" tab, select guided or quick auth flow and follow the steps.
The Inspector provides:
- Visual Interface: Interactive UI for testing tools, resources, and prompts
- Authentication Support: Built-in bearer token authentication for testing protected methods
- Real-time Debugging: Monitor JSON-RPC messages and server responses
- Export Configuration: Generate
mcp.jsonfiles for client integration
Basic Testing with curl
For quick verification, you can test public endpoints:
# Test MCP endpoint (initialize is public - no auth required)
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test-client", "version": "1.0.0"}
},
"id": 1
}'
# Test authentication flow (will redirect to Auth0)
curl -I http://localhost:8000/auth/login
Note: Testing protected MCP methods (tools, resources, prompts) requires authentication, which is much easier to handle with the MCP Inspector's built-in auth support.
🌐 Deploy to Production
1. Setup Shuttle
shuttle login
2. Deploy
shuttle deploy
Note: This deployment will not fully work as it does not yet have the required secrets. However, we need the deployment url in order to confugure the secrets - seee the next step.
3. Update Auth0 Settings
In your Auth0 application:
- Allowed Callback URLs:
https://your-mcp-server.shuttleapp.dev/auth/callback - Allowed Logout URLs:
https://your-mcp-server.shuttleapp.dev/
4. Update Production Secrets
# Update Secrets.toml
AUTH0_CALLBACK_URL = 'https://your-mcp-server.shuttleapp.dev/auth/callback'
# Keep other secrets the same
5. Re-Deploy
shuttle deploy
🔌 API Endpoints
Authentication
OAuth 2.1 Endpoints
| Endpoint | Method | Description |
|---|---|---|
/.well-known/oauth-authorization-server | GET | OAuth server metadata (RFC8414) |
/authorize | GET | Authorization endpoint with PKCE support |
/token | POST | Token endpoint for access tokens |
/register | POST | Dynamic client registration (RFC7591) |
OAuth Flow
- Client registers using
/registerendpoint - Client initiates auth flow via
/authorizewith PKCE - User authenticates and authorizes
- Client exchanges code for token via
/token - Client uses access token for MCP requests
Auth0 Callback Endpoint
This endpoint handles the Auth0 callback as part of the OAuth flow:
GET /auth/callback- Handle Auth0 callback and bind users to OAuth authorization codes
MCP Protocol
POST /mcp- Main MCP JSON-RPC 2.0 endpoint
🛠️ Available MCP Capabilities
Core Protocol Methods
| Method | Authentication | Description |
|---|---|---|
initialize | ❌ Public | Exchange capabilities and server info |
notifications/initialized | ❌ Public | Complete MCP handshake |
tools/list | ✅ Required | List available tools with schemas |
tools/call | ✅ Required | Execute tools |
resources/list | ✅ Required | List available data resources |
resources/read | ✅ Required | Read resource content |
prompts/list | ✅ Required | List available prompt templates |
prompts/get | ✅ Required | Get specific prompts |
Built-in Tools
| Tool | Description | Arguments |
|---|---|---|
text_length | Get character count | text: string |
text_transform | Transform text case | text: string, transform: enum |
text_search | Search for patterns | text: string, pattern: string |
timestamp | Get current UTC time | None |
ai_complete | Complete text prompts | prompt: string |
ai_summarize | Summarize long text | text: string |
user_stats | Get database statistics | None |
Built-in Resources
| Resource | Description | Content Type |
|---|---|---|
user://stats | User statistics from database | application/json |
Built-in Prompts
| Prompt | Description | Arguments |
|---|---|---|
code_review | Generate code review prompts | code: string, language?: string |
explain_error | Generate error explanation prompts | error: string |
🔧 Extending Your Server
Adding New Tools
- Implement the tool in
src/tools/:
// src/tools/my_tools.rs
pub fn calculate_fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => calculate_fibonacci(n - 1) + calculate_fibonacci(n - 2)
}
}
- Register in the registry (
src/registries.rs):
Tool {
name: "fibonacci",
description: "Calculate Fibonacci number",
},
- Add the handler in
src/mcp.rs(handle_tool_callfunction):
"fibonacci" => {
let n = arguments.get("n").and_then(|v| v.as_u64()).unwrap_or(0) as u32;
let result = crate::tools::my_tools::calculate_fibonacci(n);
Ok(serde_json::json!({
"content": [{
"type": "text",
"text": format!("Fibonacci({}) = {}", n, result)
}]
}))
}
- Add the schema in
get_tool_schemafunction:
"fibonacci" => serde_json::json!({
"type": "object",
"properties": {
"n": {
"type": "integer",
"description": "The position in Fibonacci sequence",
"minimum": 0
}
},
"required": ["n"]
}),
Adding New Resources
- Register the resource (
src/registries.rs):
Resource {
uri: "system://health",
name: "System Health",
description: "Current system health metrics",
mime_type: "application/json",
},
- Add the handler in
handle_resource_readfunction (src/mcp.rs):
"system://health" => {
let health_data = serde_json::json!({
"status": "healthy",
"uptime": "2h 30m",
"memory_usage": "45%"
});
Ok(serde_json::json!({
"contents": [{
"uri": uri,
"mimeType": resource.mime_type,
"text": serde_json::to_string_pretty(&health_data).unwrap()
}]
}))
}
Adding New Prompts
- Register the prompt (
src/registries.rs):
Prompt {
name: "write_tests",
description: "Generate unit tests for code",
arguments: vec![
PromptArgument {
name: "code",
description: "The code to test",
required: true,
},
PromptArgument {
name: "framework",
description: "Testing framework",
required: false,
},
],
},
- Add the handler in
handle_prompt_getfunction (src/mcp.rs):
"write_tests" => {
let code = arguments.and_then(|args| args.get("code"))
.and_then(|v| v.as_str()).unwrap_or("// No code provided");
let framework = arguments.and_then(|args| args.get("framework"))
.and_then(|v| v.as_str()).unwrap_or("jest");
Ok(serde_json::json!({
"messages": [{
"role": "user",
"content": {
"type": "text",
"text": format!("Write {} unit tests for this code:\n\n{}", framework, code)
}
}]
}))
}
📁 Project Structure
src/
├── main.rs # Application entry point and routing
├── auth/ # Authentication system
│ ├── mod.rs # Module exports
│ ├── handlers.rs # OAuth and session handlers
│ ├── middleware.rs # Authentication middleware and helpers
│ └── models.rs # User and auth data models
├── database.rs # Database initialization and migrations
├── mcp.rs # MCP JSON-RPC protocol implementation
├── registries.rs # Central registries for tools, resources, and prompts
└── tools/ # Tool implementations
├── mod.rs # Tool module exports
├── ai.rs # OpenAI integration tools
├── db.rs # Database query tools
├── text.rs # Text processing utilities
└── utils.rs # General utility tools
migrations/ # Database migration files
📚 Learn More
- Model Context Protocol Documentation
- Shuttle Documentation
- Auth0 Documentation
- Axum Web Framework
- OpenAI API Documentation
📝 License
This project is licensed under the MIT License - see the file for details.