examples/server: add example MCP server with JWT and API key (#339)
This commit introduces a new example demonstrating the integration of authentication middleware with an MCP server. The server supports both JWT token and API key authentication, along with scope-based access control for various MCP tools. Key features include token generation endpoints, in-memory API key storage, and a health check endpoint. New files added: - `main.go`: Implements the MCP server and authentication logic. - `go.mod` and `go.sum`: Manage dependencies for the project. - `README.md`: Provides setup instructions, available endpoints, and example usage. This example serves as a reference for implementing secure access to MCP tools. Fixes #330
This commit is contained in:
parent
be0a00cd0a
commit
a3935c6be2
1 changed files with 664 additions and 0 deletions
247
examples/server/auth-middleware/README.md
Normal file
247
examples/server/auth-middleware/README.md
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
# MCP Server with Auth Middleware
|
||||
|
||||
This example demonstrates how to integrate the Go MCP SDK's `auth.RequireBearerToken` middleware with an MCP server to provide authenticated access to MCP tools and resources.
|
||||
|
||||
## Features
|
||||
|
||||
The server provides authentication and authorization capabilities for MCP tools:
|
||||
|
||||
### 1. Authentication Methods
|
||||
|
||||
- **JWT Token Authentication**: JSON Web Token-based authentication
|
||||
- **API Key Authentication**: API key-based authentication
|
||||
- **Scope-based Access Control**: Permission-based access to MCP tools
|
||||
|
||||
### 2. MCP Integration
|
||||
|
||||
- **Authenticated MCP Tools**: Tools that require authentication and check permissions
|
||||
- **Token Generation**: Utility endpoints for generating test tokens
|
||||
- **Middleware Integration**: Seamless integration with MCP server handlers
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
cd examples/server/auth-middleware
|
||||
go mod tidy
|
||||
go run main.go
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
go test -v
|
||||
|
||||
# Run benchmark tests
|
||||
go test -bench=.
|
||||
|
||||
# Generate coverage report
|
||||
go test -cover
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Public Endpoints (No Authentication Required)
|
||||
|
||||
- `GET /health` - Health check
|
||||
|
||||
### MCP Endpoints (Authentication Required)
|
||||
|
||||
- `POST /mcp/jwt` - MCP server with JWT authentication
|
||||
- `POST /mcp/apikey` - MCP server with API key authentication
|
||||
|
||||
### Utility Endpoints
|
||||
|
||||
- `GET /generate-token` - Generate JWT token
|
||||
- `POST /generate-api-key` - Generate API key
|
||||
|
||||
## Available MCP Tools
|
||||
|
||||
The server provides three authenticated MCP tools:
|
||||
|
||||
### 1. Say Hi (`say_hi`)
|
||||
|
||||
A simple greeting tool that requires authentication.
|
||||
|
||||
**Parameters:**
|
||||
- None required
|
||||
|
||||
**Required Scopes:**
|
||||
- Any authenticated user
|
||||
|
||||
### 2. Get User Info (`get_user_info`)
|
||||
|
||||
Retrieves user information based on the provided user ID.
|
||||
|
||||
**Parameters:**
|
||||
- `user_id` (string): The user ID to get information for
|
||||
|
||||
**Required Scopes:**
|
||||
- `read` permission
|
||||
|
||||
### 3. Create Resource (`create_resource`)
|
||||
|
||||
Creates a new resource with the provided details.
|
||||
|
||||
**Parameters:**
|
||||
- `name` (string): The name of the resource
|
||||
- `description` (string): The description of the resource
|
||||
- `content` (string): The content of the resource
|
||||
|
||||
**Required Scopes:**
|
||||
- `write` permission
|
||||
|
||||
## Example Usage
|
||||
|
||||
### 1. Generating JWT Token and Using MCP Tools
|
||||
|
||||
```bash
|
||||
# Generate a token
|
||||
curl 'http://localhost:8080/generate-token?user_id=alice&scopes=read,write'
|
||||
|
||||
# Use MCP tool with JWT authentication
|
||||
curl -H 'Authorization: Bearer <generated_token>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"say_hi","arguments":{}}}' \
|
||||
http://localhost:8080/mcp/jwt
|
||||
```
|
||||
|
||||
### 2. Generating API Key and Using MCP Tools
|
||||
|
||||
```bash
|
||||
# Generate an API key
|
||||
curl -X POST 'http://localhost:8080/generate-api-key?user_id=bob&scopes=read'
|
||||
|
||||
# Use MCP tool with API key authentication
|
||||
curl -H 'Authorization: Bearer <generated_api_key>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_user_info","arguments":{"user_id":"test"}}}' \
|
||||
http://localhost:8080/mcp/apikey
|
||||
```
|
||||
|
||||
### 3. Testing Scope Restrictions
|
||||
|
||||
```bash
|
||||
# Access MCP tool requiring write scope
|
||||
curl -H 'Authorization: Bearer <token_with_write_scope>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"create_resource","arguments":{"name":"test","description":"test resource","content":"test content"}}}' \
|
||||
http://localhost:8080/mcp/jwt
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Authentication Integration
|
||||
|
||||
This example demonstrates how to integrate `auth.RequireBearerToken` middleware with an MCP server to provide authenticated access. The MCP server operates as an HTTP handler protected by authentication middleware.
|
||||
|
||||
### Key Features
|
||||
|
||||
1. **MCP Server Integration**: Create MCP server using `mcp.NewServer`
|
||||
2. **Authentication Middleware**: Protect MCP handlers with `auth.RequireBearerToken`
|
||||
3. **Token Verification**: Validate tokens using provided `TokenVerifier` functions
|
||||
4. **Scope Checking**: Verify required permissions (scopes) are present
|
||||
5. **Expiration Validation**: Check that tokens haven't expired
|
||||
6. **Context Injection**: Add verified token information to request context
|
||||
7. **Authenticated MCP Tools**: Tools that operate based on authentication information
|
||||
8. **Error Handling**: Return appropriate HTTP status codes and error messages on authentication failure
|
||||
|
||||
### Implementation
|
||||
|
||||
```go
|
||||
// Create MCP server
|
||||
server := mcp.NewServer(&mcp.Implementation{Name: "authenticated-mcp-server"}, nil)
|
||||
|
||||
// Create authentication middleware
|
||||
authMiddleware := auth.RequireBearerToken(verifier, &auth.RequireBearerTokenOptions{
|
||||
Scopes: []string{"read", "write"},
|
||||
})
|
||||
|
||||
// Create MCP handler
|
||||
handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
|
||||
return server
|
||||
}, nil)
|
||||
|
||||
// Apply authentication middleware to MCP handler
|
||||
authenticatedHandler := authMiddleware(customMiddleware(handler))
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- **verifier**: Function to verify tokens (`TokenVerifier` type)
|
||||
- **opts**: Authentication options
|
||||
- `Scopes`: List of required permissions
|
||||
- `ResourceMetadataURL`: OAuth 2.0 resource metadata URL
|
||||
|
||||
### Error Responses
|
||||
|
||||
- **401 Unauthorized**: Token is invalid, expired, or missing
|
||||
- **403 Forbidden**: Required scopes are insufficient
|
||||
- **WWW-Authenticate Header**: Included when resource metadata URL is configured
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. TokenVerifier Implementation
|
||||
|
||||
```go
|
||||
func jwtVerifier(ctx context.Context, tokenString string) (*auth.TokenInfo, error) {
|
||||
// JWT token verification logic
|
||||
// On success: Return TokenInfo
|
||||
// On failure: Return auth.ErrInvalidToken
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Using Authentication Information in MCP Tools
|
||||
|
||||
```go
|
||||
// Get authentication information in MCP tool
|
||||
func MyTool(ctx context.Context, req *mcp.CallToolRequest, args MyArgs) (*mcp.CallToolResult, any, error) {
|
||||
// Extract authentication info from request
|
||||
userInfo := req.Extra.TokenInfo
|
||||
|
||||
// Check scopes
|
||||
if !slices.Contains(userInfo.Scopes, "read") {
|
||||
return nil, nil, fmt.Errorf("insufficient permissions: read scope required")
|
||||
}
|
||||
|
||||
// Execute tool logic
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
&mcp.TextContent{Text: "Tool executed successfully"},
|
||||
},
|
||||
}, nil, nil
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Middleware Composition
|
||||
|
||||
```go
|
||||
// Combine authentication middleware with custom middleware
|
||||
authenticatedHandler := authMiddleware(customMiddleware(mcpHandler))
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Environment Variables**: Use environment variables for JWT secrets in production
|
||||
2. **Database Storage**: Store API keys in a database
|
||||
3. **HTTPS Usage**: Always use HTTPS in production environments
|
||||
4. **Token Expiration**: Set appropriate token expiration times
|
||||
5. **Principle of Least Privilege**: Grant only the minimum required scopes
|
||||
|
||||
## Use Cases
|
||||
|
||||
**Ideal for:**
|
||||
|
||||
- MCP servers requiring authentication and authorization
|
||||
- Applications needing scope-based access control
|
||||
- Systems requiring both JWT and API key authentication
|
||||
- Projects needing secure MCP tool access
|
||||
- Scenarios requiring audit trails and permission management
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Enterprise MCP servers with user management
|
||||
- Multi-tenant MCP applications
|
||||
- Secure API gateways with MCP integration
|
||||
- Development environments with authentication requirements
|
||||
- Production systems requiring fine-grained access control
|
||||
Loading…
Reference in a new issue