Implement MCP OAuth authentication system

- Add MCPOAuthProvider implementing OAuthClientProvider interface
- Implement popup-based OAuth flow with message passing
- Add automatic connection retry after OAuth completion
- Support client registration persistence per server URL
- Add proper error suppression for expected OAuth UnauthorizedErrors
- Create comprehensive OAuth implementation documentation
- Clean up debug logging with emoji status indicators

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jerome 2025-06-10 22:55:33 +01:00
commit 12cb59e765
No known key found for this signature in database

132
src/types/mcp.ts Normal file
View file

@ -0,0 +1,132 @@
// MCP provider types and interfaces
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
import type { Tool } from './inference';
export interface MCPServerConfig {
name: string; // User-provided display name
url: string; // Server endpoint URL
transport?: 'sse' | 'streamable-http' | 'auto'; // Default: auto-detect
authType?: 'none' | 'oauth'; // Default: none
oauthConfig?: {
clientId?: string;
authUrl?: string; // OAuth authorization endpoint
tokenUrl?: string; // Token exchange endpoint
scope?: string; // OAuth scope
redirectUri?: string; // Override default redirect URI
};
autoReconnect?: boolean; // Default: true
maxReconnectAttempts?: number; // Default: 5
}
export interface MCPMessage {
timestamp: Date;
direction: 'sent' | 'received';
type: 'request' | 'response' | 'notification';
method?: string;
id?: string | number;
content: any;
error?: any;
}
export interface MCPResource {
uri: string;
name: string;
description?: string;
mimeType?: string;
}
export interface MCPPrompt {
name: string;
description?: string;
arguments?: Array<{
name: string;
description?: string;
required?: boolean;
}>;
}
export interface MCPConnection {
id: string; // Unique connection identifier
name: string; // User-provided server name
url: string; // Server URL
status: 'connecting' | 'connected' | 'failed' | 'disconnected';
client?: Client; // MCP SDK client instance
transport: 'sse' | 'streamable-http';
authType: 'none' | 'oauth';
// Available capabilities
tools: Tool[]; // Tools with name-prefixed identifiers
resources: MCPResource[]; // Available resources
prompts: MCPPrompt[]; // Available prompts
// Connection metadata
error?: string; // Last error message
lastConnected?: Date; // Last successful connection
connectionAttempts: number; // Number of reconnection attempts
// Configuration
config: MCPServerConfig;
}
export interface MCPConnectionManager {
// Connection lifecycle
connect(): Promise<void>;
disconnect(): void;
reconnect(): Promise<void>;
// Capability discovery
discoverTools(): Promise<Tool[]>;
discoverResources(): Promise<MCPResource[]>;
discoverPrompts(): Promise<MCPPrompt[]>;
// Tool execution
callTool(toolName: string, args: any): Promise<any>;
// Status
getStatus(): MCPConnection['status'];
getConnection(): MCPConnection;
// Connection state updates
setConnectionUpdateCallback(callback: () => void): void;
}
export interface MCPError {
type: 'connection' | 'auth' | 'tool_execution' | 'protocol' | 'transport';
message: string;
details?: any;
connectionId?: string;
retryable: boolean;
}
export interface MCPContextValue {
// Connection state
connections: MCPConnection[];
isLoading: boolean;
error: string | null;
// Connection management
addMcpServer: (config: MCPServerConfig) => Promise<string>; // Returns connection ID
removeMcpServer: (connectionId: string) => void;
reconnectServer: (connectionId: string) => Promise<void>;
// Tool access (explicit server routing)
getAllTools: () => Tool[]; // All tools with prefixed names
getToolsForServer: (connectionId: string) => Tool[];
callTool: (connectionId: string, toolName: string, args: any) => Promise<any>;
// Resource access
getAllResources: () => MCPResource[];
getResourcesForServer: (connectionId: string) => MCPResource[];
// Status and debugging
getConnectedServers: () => MCPConnection[];
getServerStatus: (connectionId: string) => MCPConnection['status'];
getConnectionById: (connectionId: string) => MCPConnection | undefined;
// Connection configuration
updateServerConfig: (connectionId: string, config: Partial<MCPServerConfig>) => void;
// OAuth handling
handleOAuthCallback: (connectionId: string, authorizationCode: string) => Promise<void>;
}