
Company News
Socket Partners with Replit to Block Malicious Packages in AI-Powered Development
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.
mcpresso-oauth-server
Advanced tools
Production-ready OAuth 2.1 server implementation for Model Context Protocol (MCP) with PKCE support
A production-ready OAuth 2.1 server implementation designed specifically for Model Context Protocol (MCP) servers. Provides seamless authentication integration with mcpresso servers.
npm install mcpresso-oauth-server
# or
bun add mcpresso-oauth-server
import {
MCPOAuthServer,
MemoryStorage
} from 'mcpresso-oauth-server'
// Initialize storage with demo data
const storage = new MemoryStorage()
await storage.createClient({
id: 'demo-client',
secret: 'demo-secret',
name: 'Demo Client',
type: 'confidential',
redirectUris: ['http://localhost:4000/callback'],
scopes: ['read', 'write'],
grantTypes: ['authorization_code']
})
// Create OAuth server with custom authentication
const oauthServer = new MCPOAuthServer({
issuer: 'http://localhost:4000',
serverUrl: 'http://localhost:4000',
jwtSecret: 'your-secret-key',
auth: {
authenticateUser: async (credentials, context) => {
// Your login logic here
const user = users.find(u => u.username === credentials.username)
return user && validatePassword(credentials.password, user.password) ? user : null
},
getCurrentUser: async (sessionData, context) => {
// Check if user is already logged in via session/cookies
return null // Force login for this example
},
renderLoginPage: async (context, error) => {
// Optional: Customize login page
return `<html>...custom login form...</html>`
}
}
}, storage)
Run OAuth and MCP server together:
import { createMCPServer } from 'mcpresso'
import { MCPOAuthServer } from 'mcpresso-oauth-server'
// Create OAuth server
const oauthServer = new MCPOAuthServer({...}, storage)
// Create MCP server with integrated OAuth
const app = createMCPServer({
name: "integrated_server",
resources: [userResource],
auth: {
oauth: oauthServer, // Integrate OAuth server
userLookup: async (jwtPayload) => {
// Fetch full user profiles from your database
return await db.users.findById(jwtPayload.sub)
}
}
})
app.listen(4000) // Both OAuth and MCP on port 4000
Architecture:
┌─────────────────────────────────┐
│ Integrated Server │
│ (Port 4000) │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │OAuth Service│ │ MCP Service │ │
│ │• /authorize │ │• MCP API │ │
│ │• /token │ │• Resources │ │
│ │• Login UI │ │• Tools │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────┘
Run OAuth and MCP on different ports:
// OAuth Server (Port 4001)
const oauthApp = express()
oauthApp.use(cors()) // Important for cross-origin requests
registerOAuthEndpoints(oauthApp, oauthServer)
oauthApp.listen(4001)
// MCP Server (Port 4000)
const mcpApp = createMCPServer({
name: "api_server",
resources: [userResource],
auth: {
issuer: "http://localhost:4001", // OAuth server URL
serverUrl: "http://localhost:4000", // This MCP server URL
jwtSecret: "shared-secret", // Same secret as OAuth server
userLookup: async (jwtPayload) => {
return await db.users.findById(jwtPayload.sub)
}
}
})
mcpApp.listen(4000)
Architecture:
┌─────────────────┐ ┌──────────────────┐
│ OAuth Server │ │ MCP Server │
│ (Port 4001) │ │ (Port 4000) │
│ │ │ │
│ • /authorize │ │ • MCP API │
│ • /token │ │ • Token Validation│
│ • Login UI │ │ • Resources │
└─────────────────┘ └──────────────────┘
Implement your own user authentication logic:
const oauthServer = new MCPOAuthServer({
// ... other config
auth: {
// Required: Validate user credentials
authenticateUser: async (credentials, context) => {
const { username, password } = credentials
// Example with database lookup
const user = await db.users.findByEmail(username)
if (!user) return null
// Verify password (use bcrypt in production)
const isValid = await bcrypt.compare(password, user.hashedPassword)
if (!isValid) return null
// Return user object
return {
id: user.id,
username: user.email,
email: user.email,
scopes: user.permissions // e.g., ['read', 'write', 'admin']
}
},
// Optional: Check existing sessions
getCurrentUser: async (sessionData, context) => {
if (sessionData?.userId) {
return await db.users.findById(sessionData.userId)
}
return null
},
// Optional: Custom login page
renderLoginPage: async (context, error) => {
return `
<!DOCTYPE html>
<html>
<head><title>Login - ${context.clientId}</title></head>
<body>
<h2>Login to ${context.clientId}</h2>
${error ? `<p style="color:red">${error}</p>` : ''}
<form method="POST" action="/authorize">
<!-- Hidden OAuth parameters -->
<input type="hidden" name="response_type" value="code">
<input type="hidden" name="client_id" value="${context.clientId}">
<input type="hidden" name="redirect_uri" value="${context.redirectUri}">
<input type="hidden" name="scope" value="${context.scope || ''}">
<!-- Login form -->
<div>
<label>Email:</label>
<input type="email" name="username" required>
</div>
<div>
<label>Password:</label>
<input type="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
</body>
</html>
`
}
}
}, storage)
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(url, key)
const oauthServer = new MCPOAuthServer({
auth: {
authenticateUser: async ({ username, password }) => {
const { data, error } = await supabase.auth.signInWithPassword({
email: username,
password: password
})
if (error || !data.user) return null
return {
id: data.user.id,
username: data.user.email,
email: data.user.email,
scopes: data.user.user_metadata?.scopes || ['read']
}
}
}
})
import { signInWithEmailAndPassword } from 'firebase/auth'
const oauthServer = new MCPOAuthServer({
auth: {
authenticateUser: async ({ username, password }) => {
try {
const userCredential = await signInWithEmailAndPassword(auth, username, password)
const user = userCredential.user
return {
id: user.uid,
username: user.email,
email: user.email,
scopes: user.customClaims?.scopes || ['read']
}
} catch (error) {
return null
}
}
}
})
Configure the server using environment variables:
# Server configuration
OAUTH_ISSUER=https://auth.yourdomain.com
OAUTH_SERVER_URL=https://auth.yourdomain.com
OAUTH_JWT_SECRET=your-super-secret-jwt-key
# CORS configuration (for separate server deployment)
CORS_ORIGIN=https://yourdomain.com,https://api.yourdomain.com
TRUST_PROXY=true
# Server port
PORT=4001
The server includes production-ready security features:
const oauthServer = new MCPOAuthServer({
// ... OAuth config
http: {
cors: {
origin: ['https://yourdomain.com'],
credentials: true,
methods: ['GET', 'POST', 'OPTIONS']
},
enableHelmet: true,
enableRateLimit: true,
rateLimitConfig: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // requests per window
}
}
})
GET /authorize - Authorization endpoint (shows login page)POST /authorize - Authorization endpoint (processes login)POST /token - Token endpointPOST /introspect - Token introspectionPOST /revoke - Token revocationGET /userinfo - User info endpointPOST /register - Dynamic client registrationGET /.well-known/oauth-authorization-server - OAuth metadata (RFC 8414)GET /.well-known/jwks.json - JSON Web Key SetGET /.well-known/oauth-protected-resource - MCP protected resource metadataGET /health - Health checkGET /admin/clients - List clientsGET /admin/users - List usersGET /admin/stats - Server statisticsThe package includes an in-memory storage implementation for development. For production, implement the MCPOAuthStorage interface:
import type { MCPOAuthStorage } from 'mcpresso-oauth-server'
class DatabaseStorage implements MCPOAuthStorage {
async createClient(client: OAuthClient): Promise<void> {
// Store client in your database
}
async getClient(clientId: string): Promise<OAuthClient | null> {
// Fetch client from your database
}
// ... implement all required methods
}
See complete working examples:
mcpresso/examples/oauth2-simple-demo.tsmcpresso/examples/separate-servers-demo.ts# Open in browser or use curl
curl "http://localhost:4001/authorize?response_type=code&client_id=demo-client&redirect_uri=http://localhost:4001/callback&scope=read&resource=http://localhost:4000"
curl -X POST "http://localhost:4001/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&client_id=demo-client&client_secret=demo-secret&code=YOUR_CODE&redirect_uri=http://localhost:4001/callback&resource=http://localhost:4000"
curl -X POST "http://localhost:4000" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami_user","arguments":{}}}'
# Install dependencies
bun install
# Build the package
bun run build
# Run tests
bun test
# Start development server
bun run dev
For production deployments:
MIT - See LICENSE file for details.
FAQs
Production-ready OAuth 2.1 server implementation for Model Context Protocol (MCP) with PKCE support
The npm package mcpresso-oauth-server receives a total of 19 weekly downloads. As such, mcpresso-oauth-server popularity was classified as not popular.
We found that mcpresso-oauth-server demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.