Skip to content

andrhamm/strider-mcp

Repository files navigation

Strider MCP Server

A Model Context Protocol (MCP) server implementation with OAuth2 authentication.

OAuth2 Authentication

This server implements OAuth2 with the Authorization Code flow. The following endpoints are available:

Authentication Endpoints

Register a new user

POST /oauth/register
Content-Type: application/json

{
  "username": "string",
  "password": "string"
}

Response:

{
  "message": "Registration successful",
  "userId": "string"
}

Login

POST /oauth/login
Content-Type: application/json

{
  "username": "string",
  "password": "string"
}

Response:

{
  "message": "Login successful"
}

OAuth2 Flow

1. Authorization Request

GET /oauth/authorize?client_id=client1&redirect_uri=http://localhost:3000/callback&response_type=code&state=random_state

Required parameters:

  • client_id: The client identifier (currently only "client1" is supported)
  • redirect_uri: The callback URL where the user will be redirected after authorization
  • response_type: Must be "code"
  • state: (Optional) A random string to prevent CSRF attacks

The server will redirect to the redirect_uri with an authorization code:

http://localhost:3000/callback?code=AUTHORIZATION_CODE&state=random_state

2. Token Exchange

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=http://localhost:3000/callback&
client_id=client1&
client_secret=secret1

Response:

{
  "access_token": "string",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "string"
}

3. Access Protected Resources

GET /oauth/userinfo
Authorization: Bearer ACCESS_TOKEN

Response:

{
  "id": "string",
  "username": "string"
}

Command-Line Client Implementation

For command-line applications, you can implement the OAuth2 flow using manual code entry. Here's how:

  1. Open the authorization URL in the user's browser
  2. Let the user copy the authorization code from the callback URL
  3. Exchange the code for tokens
  4. Store the tokens securely

Example implementation in TypeScript:

import open from 'open'
import { randomBytes } from 'crypto'
import { config } from 'dotenv'
import readline from 'readline'

// Load environment variables
config()

const CLIENT_ID = 'client1'
const CLIENT_SECRET = 'secret1'
const REDIRECT_URI = 'http://localhost:3000/callback'
const AUTH_SERVER = 'http://localhost:3000'

async function authenticate() {
  // Generate random state for CSRF protection
  const state = randomBytes(16).toString('hex')

  // Create readline interface for user input
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  })

  // Open browser for authorization
  const authUrl = new URL('/oauth/authorize', AUTH_SERVER)
  authUrl.searchParams.set('client_id', CLIENT_ID)
  authUrl.searchParams.set('redirect_uri', REDIRECT_URI)
  authUrl.searchParams.set('response_type', 'code')
  authUrl.searchParams.set('state', state)

  console.log('Opening browser for authorization...')
  await open(authUrl.toString())

  // Wait for user to enter the authorization code
  const code = await new Promise<string>(resolve => {
    rl.question('Please enter the authorization code from the callback URL: ', resolve)
  })

  rl.close()

  // Exchange code for tokens
  const tokenResponse = await fetch(`${AUTH_SERVER}/oauth/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      redirect_uri: REDIRECT_URI,
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET
    })
  })

  const tokens = await tokenResponse.json()
  return tokens
}

// Usage
async function main() {
  try {
    const tokens = await authenticate()
    console.log('Access Token:', tokens.access_token)
    console.log('Refresh Token:', tokens.refresh_token)

    // Store tokens securely (e.g., in keychain or encrypted file)
    // ...
  } catch (error) {
    console.error('Authentication failed:', error)
  }
}

main()

To use this in your command-line application:

  1. Install dependencies:
npm install open dotenv
  1. Create a .env file:
CLIENT_ID=client1
CLIENT_SECRET=secret1
AUTH_SERVER=http://localhost:3000
  1. Run the authentication:
ts-node auth.ts

The script will:

  1. Open the user's browser to the authorization page
  2. Prompt the user to copy and paste the authorization code from the callback URL
  3. Exchange the code for access and refresh tokens
  4. Store the tokens securely

For subsequent API calls, use the access token:

async function makeApiCall(accessToken: string) {
  const response = await fetch('http://localhost:3000/oauth/userinfo', {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  })
  return response.json()
}

Example Flow

  1. Register a new user:
curl -X POST http://localhost:3000/oauth/register \
  -H "Content-Type: application/json" \
  -d '{"username": "testuser", "password": "password123"}'
  1. Login:
curl -X POST http://localhost:3000/oauth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "testuser", "password": "password123"}'
  1. Start the OAuth flow by redirecting to:
http://localhost:3000/oauth/authorize?client_id=client1&redirect_uri=http://localhost:3000/callback&response_type=code
  1. Exchange the authorization code for tokens:
curl -X POST http://localhost:3000/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=http://localhost:3000/callback&client_id=client1&client_secret=secret1"
  1. Access protected resources:
curl http://localhost:3000/oauth/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"

Development

Prerequisites

  • Node.js 18+
  • Bun

Installation

bun install

Running the server

bun run server.ts

The server will start on http://localhost:3000

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published