We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/durvester/mcp-scheduler-bot'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
# OAuth Token Persistence Fix - Implementation Summary
## ✅ **ISSUE RESOLVED**: OAuth Flow Triggering on Every Tool Call
### **Problem Description**
After the initial OAuth flow fix, the system was still initiating a **new OAuth handshake for every tool call** instead of reusing tokens. This caused:
- Browser opening for OAuth on every API operation
- No token persistence between different tools
- Poor user experience with repeated authentication
### **Root Cause Analysis**
#### **Multiple Auth Instances Problem**
Each tool handler was creating its own separate `Auth` instance:
- `PatientToolHandler` → Auth Instance #1
- `CalendarToolHandler` → Auth Instance #2
- `UserFacilityToolHandler` → Auth Instance #3
- `PayerToolHandler` → Auth Instance #4
#### **Token Isolation Issue**
When OAuth completed and stored a token in one Auth instance, other Auth instances had no access to that token:
```
Tool Call Flow (BROKEN):
1. get_users → PatientToolHandler → Auth Instance #1 → OAuth flow → Token stored in #1
2. get_facilities → UserFacilityToolHandler → Auth Instance #3 → No token → OAuth flow again!
```
### **Solution Implemented: Shared Auth Instance**
#### **Single Auth Instance Architecture**
Created a **single shared Auth instance** that all tool handlers use:
```
Tool Call Flow (FIXED):
1. get_users → Shared Auth Instance → OAuth flow → Token stored
2. get_facilities → Same Shared Auth Instance → Token available → No OAuth needed!
3. Token expires → Same Shared Auth Instance → Refresh token automatically
```
#### **Implementation Details**
### **1. Modified ToolHandlerNew.ts**
```typescript
export class ToolHandler {
private sharedAuth: Auth; // Single shared instance
constructor(authConfig: AuthConfig, baseUrl: string) {
// Create ONE Auth instance for ALL handlers
this.sharedAuth = new Auth(authConfig);
// Pass shared Auth to all specialized handlers
const patientHandler = new PatientToolHandler(authConfig, baseUrl, this.sharedAuth);
const calendarHandler = new CalendarToolHandler(authConfig, baseUrl, this.sharedAuth);
// ... etc
}
}
```
### **2. Updated BaseToolHandler.ts**
```typescript
export abstract class BaseToolHandler {
protected auth: Auth; // Direct reference to shared instance
constructor(authConfig: AuthConfig, baseUrl: string, componentName: string, sharedAuth: Auth) {
this.auth = sharedAuth; // Use provided shared instance
// Removed: Auth creation logic
}
protected async executeWithAuth<T>(operation: () => Promise<T>): Promise<T> {
return this.auth.executeWithAuth(operation); // Use shared instance
}
}
```
### **3. Updated All Specialized Handlers**
- **PatientToolHandler.ts** ✅
- **CalendarToolHandler.ts** ✅
- **UserFacilityToolHandler.ts** ✅
- **PayerToolHandler.ts** ✅
**Changes Applied:**
- Added `sharedAuth: Auth` parameter to constructors
- Removed `initializeAuth()` calls
- Updated client initialization to use `this.auth` directly
#### **Token Flow Behavior (Now Correct)**
### **First Tool Call (No Token)**
1. User calls any tool (e.g., `get_users`)
2. Shared Auth instance detects no token
3. **Browser opens once** for OAuth authentication
4. Token stored in shared Auth instance
5. Tool executes successfully
### **Subsequent Tool Calls (Token Available)**
1. User calls different tool (e.g., `get_facilities`)
2. **Same shared Auth instance** checks token
3. Token is available → **No OAuth needed**
4. Tool executes immediately with existing token
### **Token Refresh (Expired Token)**
1. Any tool call detects expired token
2. **Shared Auth instance** automatically refreshes using refresh token
3. **No OAuth flow needed** - uses refresh token
4. All subsequent tools use refreshed token
### **Server Startup Logs (Verification)**
```
2025-07-27T01:44:19.571Z INFO [ToolHandler] Created shared Auth instance for token persistence
2025-07-27T01:44:19.572Z INFO [ToolHandler] ToolHandler initialized with specialized handlers
```
The log message confirms the shared Auth instance is being created properly.
### **Expected User Experience**
#### **✅ Correct Flow:**
1. **First use**: Browser opens **once** for OAuth
2. **All subsequent tools**: Work immediately with stored token
3. **Token expires**: Automatic refresh with refresh token (no browser)
4. **Cross-tool usage**: Seamless token sharing between different tool types
#### **❌ Previous Broken Flow:**
1. **Every tool call**: Browser opened for OAuth
2. **No token reuse**: Each handler isolated
3. **Poor UX**: Constant re-authentication required
### **Technical Benefits**
#### **1. Performance**
- **No repeated OAuth flows** - significant time savings
- **Token reuse** across all API operations
- **Automatic refresh** without user intervention
#### **2. User Experience**
- **Single authentication** per session
- **Seamless tool switching** without re-auth
- **Background token management** - invisible to user
#### **3. Security**
- **Token stored once** in memory only
- **Proper token lifecycle** management
- **Secure refresh token** handling
#### **4. Architecture**
- **Clean separation** of concerns maintained
- **Shared state** managed properly
- **Modular design** preserved
### **Testing the Fix**
#### **Test Scenario:**
1. Start server: `npm run inspector`
2. Open inspector: `http://localhost:5173`
3. Call first tool: `get_users` → **Browser opens for OAuth**
4. Complete authentication
5. Call second tool: `get_facilities` → **No OAuth, immediate execution**
6. Call third tool: `search_patients` → **No OAuth, immediate execution**
#### **Expected Results:**
- ✅ **OAuth only on first call**
- ✅ **Immediate execution for subsequent calls**
- ✅ **Token shared across all tool types**
- ✅ **Automatic refresh when token expires**
## **✅ RESULT: Proper OAuth Token Persistence**
The Practice Fusion MCP Server now maintains proper OAuth token lifecycle:
- **Single authentication** per session
- **Token persistence** across all tool handlers
- **Automatic refresh** using refresh tokens
- **Seamless user experience** without repeated OAuth flows
Users can now authenticate once and use all tools seamlessly, just as expected in a production OAuth2 implementation.