README.mdā¢15.1 kB
# Weather MCP Server with GitHub OAuth & Location Management
This project demonstrates an advanced Model Context Protocol (MCP) server with GitHub OAuth authentication, personalized location management, and weather data retrieval using Open-Meteo's free API.
## Features
- **š GitHub OAuth 2.0 Authentication**: Secure authentication using GitHub Apps
- **š Personal Location Management**: Save and manage custom location labels (e.g., "home", "office")
- **š¤ļø Smart Weather Queries**: Check weather using saved labels or direct location names
- **š¾ SQLite Database**: Persistent storage for users and their locations
- **š Free Weather API**: Uses Open-Meteo API - no API key required!
- **š Streamable HTTP Transport**: Modern HTTP transport with MCP SDK
- **š ļø Multiple Tools**: Weather lookup, location management (add, list, delete), user info
- **š¤ User Profiles**: Automatic user creation from GitHub profile data with profile retrieval
## Prerequisites
- Node.js (v18 or higher recommended)
- GitHub Account
- GitHub OAuth App (instructions below)
- OpenAI API Key (optional, for the client example)
## Setup
### 1. Install dependencies:
```bash
npm install
```
### 2. Create GitHub OAuth App:
1. Go to [GitHub Developer Settings](https://github.com/settings/developers)
2. Click **"New OAuth App"**
3. Fill in the application details:
- **Application name**: Weather MCP Server (or your preferred name)
- **Homepage URL**: `http://localhost:3000`
- **Authorization callback URL**: `http://localhost:3000/oauth/callback`
4. Click **"Register application"**
5. Copy your **Client ID**
6. Click **"Generate a new client secret"** and copy it
### 3. Configure Environment Variables:
```bash
cp .env.example .env
```
Edit `.env` and add your GitHub OAuth credentials:
```bash
GITHUB_CLIENT_ID=your_github_client_id_here
GITHUB_CLIENT_SECRET=your_github_client_secret_here
GITHUB_REDIRECT_URI=http://localhost:3000/oauth/callback
PORT=3000
```
### 4. Start the MCP server:
```bash
node server.js
```
The server will start on `http://127.0.0.1:3000`
### 5. Authenticate with GitHub:
1. Open your browser and visit: `http://localhost:3000/oauth/login`
2. Click **"Authorize"** to connect with GitHub
3. Copy the **access token** displayed on the success page
4. Use this token in the Authorization header: `Bearer <your-token>`
### 6. Configure Claude Desktop
Add the configuration to your Claude Desktop config file:
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
**Option A: Automatic OAuth (Recommended)**
```json
{
"mcpServers": {
"weather-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:3000/mcp"
]
}
}
}
```
Claude Desktop will automatically discover the OAuth endpoints and open your browser for authentication. Just authorize with GitHub when prompted!
**Option B: Manual Token**
```json
{
"mcpServers": {
"weather-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:3000/mcp",
"--header",
"Authorization: Bearer YOUR_GITHUB_ACCESS_TOKEN",
"--no-auth"
]
}
}
}
```
First get your token by visiting `http://localhost:3000/oauth/login`, then replace `YOUR_GITHUB_ACCESS_TOKEN` with your token.
## Usage Examples
Once connected via Claude Desktop, you can:
### Basic Weather Queries
- "What is the weather like in San Francisco?"
- "Tell me the current weather in Tokyo"
- "How's the weather in Paris?"
### Save Personal Locations
- "Save my home location as New York"
- "Add my office location as San Francisco"
- "Save the gym location as 123 Main Street, Boston"
### Query Using Saved Labels
- "What's the weather at home?"
- "How's the weather at the office?"
- "Check the weather at the gym"
### Manage Locations
- "List all my saved locations"
- "Show my locations"
- "Delete my home location"
### User Profile
- "Who am I?"
- "Show my profile"
- "What's my GitHub username?"
## How It Works
1. **OAuth Flow**: User authenticates via GitHub OAuth 2.0
2. **Token Exchange**: Server exchanges authorization code for access token
3. **User Creation**: Server creates or updates user profile from GitHub data
4. **Authentication**: Client sends Bearer token in Authorization header
5. **Token Validation**: Server validates token against SQLite database
6. **Session Creation**: Server creates authenticated session with user context
7. **Tool Discovery**: Client discovers available MCP tools from server
8. **Tool Execution**:
- Weather queries resolve location labels to actual addresses
- Location management stores data per-user in database
- All operations are scoped to the authenticated user
9. **Weather Data**: Server fetches real-time weather from Open-Meteo API
10. **Response**: Results returned to client with user-specific context
## Architecture
```
User Browser
ā
ā 1. Visit /oauth/login
ā¼
GitHub OAuth Server
ā
ā 2. Authorization
ā¼
/oauth/callback
ā
ā 3. Access Token
ā¼
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Claude Desktop / MCP Client ā
ā (with Authorization: Bearer token) ā
āāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Streamable HTTP + Auth
ā¼
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā server.js (MCP Server) ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā OAuth Authentication (auth.js) ā ā
ā ā ā ā ā
ā ā Token Validation Middleware ā ā
ā ā ā ā ā
ā ā Session Management (per-user) ā ā
ā ā ā ā ā
ā ā MCP Tools: ā ā
ā ā - get_current_weather ā ā
ā ā - add_location ā ā
ā ā - list_locations ā ā
ā ā - delete_location ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā SQLite Database (weather.db) ā ā
ā ā - users (with GitHub data) ā ā
ā ā - locations ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
ā¼
Open-Meteo Weather API
```
## MCP Tools
### 1. `get_current_weather`
Fetches real-time weather data for any location or saved label.
- **Parameters**:
- `location` (string): Location name or saved label (e.g., "New York", "home")
- `unit` (enum): Temperature unit - "celsius" or "fahrenheit" (default: celsius)
- **Returns**: Temperature, condition, humidity, wind speed, pressure, cloud cover
- **Special**: Automatically resolves saved location labels to addresses
### 2. `add_location`
Save a location with a custom label for quick access.
- **Parameters**:
- `label` (string): Custom label (e.g., "home", "office", "gym")
- `location` (string): Actual location name or address
- **Returns**: Confirmation message
- **Note**: Replaces existing label if it already exists
### 3. `list_locations`
Display all saved locations for the authenticated user.
- **Parameters**: None
- **Returns**: List of all saved locations with their labels
### 4. `delete_location`
Remove a saved location by its label.
- **Parameters**:
- `label` (string): Label of the location to delete
- **Returns**: Confirmation or error message
### 5. `get_user_info`
Get information about the currently logged-in user.
- **Parameters**: None
- **Returns**: User profile with GitHub username, name, email, avatar URL, and user ID
## Project Structure
```
komunite-bootcamp-mcp/
āāā server.js # MCP HTTP server with OAuth
āāā database.js # SQLite database operations
āāā auth.js # GitHub OAuth authentication
āāā index.js # OpenAI function calling example (legacy)
āāā .env.example # Environment variables template
āāā .env # Your environment variables (create this)
āāā package.json # Dependencies and scripts
āāā weather.db # SQLite database (created on first run)
āāā README.md # This file
```
## Database Schema
### Users Table
```sql
CREATE TABLE users (
id TEXT PRIMARY KEY,
github_id TEXT UNIQUE,
github_username TEXT,
github_email TEXT,
name TEXT,
avatar_url TEXT,
access_token TEXT,
refresh_token TEXT,
token_expires_at DATETIME,
auth_token TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
```
### Locations Table
```sql
CREATE TABLE locations (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
label TEXT NOT NULL,
location_name TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE(user_id, label)
)
```
## Security Features
- **GitHub OAuth 2.0**: Industry-standard OAuth authentication flow
- **PKCE (RFC 7636)**: Proof Key for Code Exchange with S256 for public clients
- **Dynamic Client Registration (RFC 7591)**: Automatic client registration
- **State Parameter**: CSRF protection with state verification
- **Bearer Token Authentication**: All MCP endpoints require valid authentication
- **Token Validation**: Access tokens validated against database
- **User Isolation**: Each user can only access their own locations
- **Session Management**: Secure session handling with user context
- **Database Constraints**: Foreign key constraints ensure data integrity
- **Automatic Token Expiration**: Token expiry tracking for enhanced security
## Customization
### Adding Custom MCP Tools
1. Open `server.js`
2. Register a new tool after existing tools:
```javascript
sessionServer.tool(
'your_tool_name',
'Tool description',
{
param1: z.string().describe('Parameter description'),
},
async ({ param1 }) => {
const userId = sessionUsers[transport.sessionId]?.id;
// Your tool logic here
return {
content: [{ type: 'text', text: 'Result' }],
};
}
);
```
3. The tool will automatically be discovered by clients
## API Endpoints
### OAuth Discovery Endpoints (RFC 8414 & RFC 9728)
- **GET /.well-known/oauth-authorization-server** - OAuth 2.0 Authorization Server Metadata
- **GET /.well-known/oauth-protected-resource** - OAuth 2.0 Protected Resource Metadata
### OAuth Endpoints (Standards-Compliant)
- **POST /oauth/register** - Dynamic Client Registration (RFC 7591)
- **GET /oauth/authorize** - OAuth 2.0 Authorization Endpoint
- **POST /oauth/token** - OAuth 2.0 Token Endpoint
- **POST /oauth/revoke** - OAuth 2.0 Token Revocation (RFC 7009)
- **GET /oauth/login** - Manual OAuth flow (browser-based)
- **GET /oauth/callback** - OAuth callback handler
- **GET /oauth/me** - Returns current user info (requires authentication)
### MCP Endpoints
- **POST /mcp** - Main MCP endpoint for tool calls
- **GET /mcp** - Server-Sent Events for notifications
- **DELETE /mcp** - Session termination
### Utility Endpoints
- **GET /health** - Health check endpoint
## Notes
- Based on the **Model Context Protocol (MCP)** specification
- Uses **@modelcontextprotocol/sdk** for MCP server implementation
- **Streamable HTTP transport**: Modern HTTP transport with session management
- **SQLite Database**: Lightweight, file-based database with better-sqlite3
- **GitHub OAuth 2.0**: Secure authentication via GitHub Apps
- Uses **Open-Meteo API** - free and open-source weather API
- No API key required for weather data!
- Per-user location management with database isolation
- Automatic label resolution for convenient weather queries
- User profiles automatically created from GitHub data
## Logout / Revoke Access
To logout from OAuth when using Claude Desktop:
### Option 1: Clear mcp-remote Cache
```bash
rm -rf ~/.cache/mcp-remote/auth/
```
### Option 2: Manual Token Revocation
```bash
curl -X POST http://localhost:3000/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=YOUR_ACCESS_TOKEN"
```
Then clear the cache and restart Claude Desktop.
## Troubleshooting
### Token Expired
If you get authentication errors, your GitHub token may have expired:
1. Visit `http://localhost:3000/oauth/login` again
2. Get a new access token
3. Update your Claude Desktop configuration with the new token
## Testing with cURL
You can test the API directly with cURL:
```bash
# Check OAuth server metadata:
curl http://localhost:3000/.well-known/oauth-authorization-server
# Check protected resource metadata:
curl http://localhost:3000/.well-known/oauth-protected-resource
# Get your access token first by visiting:
open http://localhost:3000/oauth/login
# Then test the authenticated endpoint:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
http://localhost:3000/oauth/me
```
## References
- [Model Context Protocol Documentation](https://modelcontextprotocol.io/)
- [MCP Authorization Specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization)
- [OAuth 2.1 Draft Specification](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13)
- [RFC 7009: OAuth 2.0 Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009)
- [RFC 7591: OAuth 2.0 Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591)
- [RFC 7636: PKCE - Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636)
- [RFC 8414: OAuth 2.0 Authorization Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414)
- [RFC 9728: OAuth 2.0 Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728)
- [GitHub OAuth Documentation](https://docs.github.com/en/developers/apps/building-oauth-apps)
- [Open-Meteo Weather API](https://open-meteo.com/)