Skip to main content
Glama
ARCHITECTURE.md22.2 kB
# 🏗️ DhanHQ MCP Server Architecture ## System Overview ``` ┌─────────────────────────────────────────────────────────────────────┐ │ MCP Inspector (Browser) │ │ Interactive Tool Testing UI │ └──────────────────────────────┬──────────────────────────────────────┘ │ Stdio Communication │ ┌──────────────────────────────▼──────────────────────────────────────┐ │ MCP Server (Node.js) │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Tool Handlers (index.ts) │ │ │ │ ├─ start_authentication │ │ │ │ ├─ get_login_instructions │ │ │ │ ├─ complete_authentication │ │ │ │ ├─ check_auth_status │ │ │ │ └─ reset_authentication │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Authentication Module (authentication.ts) │ │ │ │ ├─ generateConsent() → Step 1 │ │ │ │ ├─ getStep2Instructions() → Step 2 Info │ │ │ │ ├─ consumeConsent() → Step 3 │ │ │ │ ├─ getAccessToken() │ │ │ │ └─ isTokenValid() │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Config & State Management (config.ts, types.ts) │ │ │ │ ├─ Environment Variables (.env) │ │ │ │ ├─ In-Memory Auth State │ │ │ │ └─ Type Definitions │ │ │ └────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────┬───────────────────────────────────────┘ │ HTTPS / REST API (Axios HTTP Client) │ ┌──────────────────────┴──────────────────────┐ │ │ ┌───────▼────────────────┐ ┌───────────▼─────────┐ │ DhanHQ OAuth Endpoints │ │ User's Browser │ ├────────────────────────┤ ├─────────────────────┤ │ Step 1: │ ────────> │ Step 2: User Login │ │ generate-consent │ │ & 2FA Verification │ │ │ │ │ │ Step 3: │ <──────── │ Step 2: Redirect │ │ consumeApp-consent │ tokenId │ with tokenId │ └────────────────────────┘ └─────────────────────┘ ``` ## Authentication Flow Sequence ``` ┌─────────────┐ │ User │ └──────┬──────┘ │ │ 1. Call start_authentication ▼ ┌──────────────────────┐ │ MCP Inspector UI │ └──────┬───────────────┘ │ │ 2. MCP Request ▼ ┌──────────────────────────────────────┐ │ MCP Server (index.ts) │ │ - Receives start_authentication │ │ - Routes to authentication.ts │ └──────┬───────────────────────────────┘ │ │ 3. HTTP POST with API key/secret ▼ ┌──────────────────────────────────────┐ │ DhanHQ: generate-consent API │ │ POST /app/generate-consent │ └──────┬───────────────────────────────┘ │ │ 4. Returns consentAppId ▼ ┌──────────────────────────────────────┐ │ MCP Server (authentication.ts) │ │ - Stores consentAppId in memory │ │ - Generates login URL │ └──────┬───────────────────────────────┘ │ │ 5. Response to Inspector ▼ ┌──────────────────────────────────────┐ │ MCP Inspector Shows: │ │ - loginUrl │ │ - consentAppId │ │ - Instructions │ └──────┬───────────────────────────────┘ │ │ 6. User opens loginUrl in browser (MANUAL STEP) ▼ ┌──────────────────────────────────────┐ │ DhanHQ Login Page │ │ - User enters credentials │ │ - Completes 2FA │ │ - Redirected to callback URL │ └──────┬───────────────────────────────┘ │ │ 7. Redirect: callback?tokenId=xyz ▼ ┌──────────────────────────────────────┐ │ User's Browser │ │ - Extracts tokenId from URL │ │ - Copies tokenId │ └──────┬───────────────────────────────┘ │ │ 8. Call complete_authentication with tokenId ▼ ┌──────────────────────────────────────┐ │ MCP Inspector UI │ │ - Input: { tokenId: "xyz..." } │ └──────┬───────────────────────────────┘ │ │ 9. MCP Request ▼ ┌──────────────────────────────────────┐ │ MCP Server (index.ts) │ │ - Receives complete_authentication │ │ - Routes to authentication.ts │ └──────┬───────────────────────────────┘ │ │ 10. HTTP GET with API key/secret ▼ ┌──────────────────────────────────────┐ │ DhanHQ: consumeApp-consent API │ │ GET /app/consumeApp-consent?tokenId │ └──────┬───────────────────────────────┘ │ │ 11. Returns JWT access token ▼ ┌──────────────────────────────────────┐ │ MCP Server (authentication.ts) │ │ - Stores accessToken in memory │ │ - Stores client details │ │ - Validates expiry time │ └──────┬───────────────────────────────┘ │ │ 12. Response to Inspector ▼ ┌──────────────────────────────────────┐ │ MCP Inspector Shows: │ │ - success: true │ │ - authToken { │ │ accessToken, │ │ dhanClientId, │ │ dhanClientName, │ │ expiryTime, │ │ ... │ │ } │ └──────────────────────────────────────┘ ✅ Authentication Complete! Ready for API requests. ``` ## Component Relationships ``` ┌─────────────────────────────────────────────────────────────┐ │ │ │ index.ts (Entry Point) │ │ - Creates MCP Server │ │ - Registers tool handlers │ │ - Validates config │ │ - Connects stdio transport │ │ │ │ ┌────────────────────────────────────────────────────────┤ │ │ │ │ │ Tool Handlers (switch statement) │ │ │ - Parse incoming requests │ │ │ - Call authentication functions │ │ │ - Format responses │ │ │ - Handle errors │ │ │ │ │ │ ┌───────────────────────────────────────────────────┤ │ │ │ │ │ │ │ authentication.ts (Business Logic) │ │ │ │ - HTTP calls to DhanHQ │ │ │ │ - Token management │ │ │ │ - State persistence │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────┤ │ │ │ │ │ │ │ │ │ config.ts (Configuration) │ │ │ │ │ - Load .env variables │ │ │ │ │ - Validate credentials │ │ │ │ │ │ │ │ │ │ types.ts (Type Definitions) │ │ │ │ │ - AuthState interface │ │ │ │ │ - DhanAuthToken interface │ │ │ │ │ - API response types │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────┤ │ │ │ │ │ │ └──────────────────────────────────────────────────┤ │ │ │ │ └────────────────────────────────────────────────────┤ │ │ └─────────────────────────────────────────────────────┘ ``` ## State Management ``` In-Memory Auth State (authState object) ┌─────────────────────────────────────────────────────┐ │ Authentication State Structure │ ├─────────────────────────────────────────────────────┤ │ │ │ authState = { │ │ consentAppId: string | undefined, │ │ consentAppStatus: string | undefined, │ │ tokenId: string | undefined, │ │ authToken: { │ │ accessToken: string, │ │ dhanClientId: string, │ │ dhanClientName: string, │ │ dhanClientUcc: string, │ │ expiryTime: ISO 8601 string, │ │ givenPowerOfAttorney: boolean, │ │ generatedAt: ISO 8601 string │ │ } | undefined │ │ } │ │ │ └─────────────────────────────────────────────────────┘ ⚠️ Note: Stored in-memory only - Lost on server restart - Not persistent - Suitable for development/testing 🔄 Production Upgrade Path: - Migrate to database (MongoDB/PostgreSQL) - Add token refresh mechanism - Implement secure session storage ``` ## Error Handling Flow ``` ┌──────────────────────────┐ │ Tool Handler in index.ts│ └──────────┬───────────────┘ │ ▼ try-catch block │ ┌──────┴──────┐ │ │ ▼ ▼ Success Error │ │ │ ├─ Parse error message │ │ │ ├─ Log to console │ │ │ └─ Return error response │ to MCP Inspector │ └─ Format response └─ Return to MCP Inspector ``` ## Data Flow for Each Tool ### start_authentication ``` User Input → Tool Handler ↓ validateConfig() ↓ axios.post (generate-consent API) ↓ Store consentAppId in-memory ↓ Generate loginUrl ↓ Format Response ↓ Return to Inspector ``` ### complete_authentication ``` User Input (tokenId) → Tool Handler ↓ Get tokenId from args ↓ axios.get (consumeApp-consent API) ↓ Extract accessToken & details ↓ Store authToken in-memory ↓ Return Response ↓ Return to Inspector ``` ### check_auth_status ``` User Input → Tool Handler ↓ Get authState from memory ↓ Validate token expiry ↓ Redact sensitive data ↓ Build status object ↓ Return to Inspector ``` ## Security Layers ``` ┌─────────────────────────────────────────────────────┐ │ Layer 1: Input Validation │ │ - Check tokenId exists │ │ - Validate required parameters │ └────────────────┬────────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────┐ │ Layer 2: Configuration Security │ │ - Environment variables for credentials │ │ - NOT hardcoded │ │ - Validated on startup │ └────────────────┬────────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────┐ │ Layer 3: API Communication │ │ - HTTPS to DhanHQ APIs │ │ - API Key/Secret in headers │ │ - OAuth token obtained securely │ └────────────────┬────────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────┐ │ Layer 4: Data Redaction │ │ - Tokens redacted in responses │ │ - Sensitive data marked as ***REDACTED*** │ │ - Console logs don't expose tokens │ └─────────────────────────────────────────────────────┘ ``` ## Deployment Architecture (Future) ``` ┌─────────────────────────────────────────────────┐ │ React Frontend │ │ (User Interface & UX) │ └──────────────┬──────────────────────────────────┘ │ HTTP/WebSocket ▼ ┌─────────────────────────────────────────────────┐ │ Backend API Gateway │ │ (Node.js Express or similar) │ └──────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ MCP Server (DhanHQ) │ │ (This project - authentication layer) │ └──────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ PostgreSQL Database │ │ (Token storage, user sessions) │ └─────────────────────────────────────────────────┘ ``` --- This architecture is designed for: - ✅ Local development with MCP Inspector - ✅ Gradual expansion with new trading tools - ✅ Easy migration to production - ✅ Type-safe TypeScript throughout - ✅ Clear separation of concerns

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harshitdynamite/DhanMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server