मुख्य सामग्री पर जाएं
ऐसे MCP सर्वरों के लिए OAuth का उपयोग करें जिन्हें उपयोगकर्ता की सहमति की आवश्यकता होती है, जैसे Gmail, Google Calendar, या अन्य सेवाएँ जिनमें प्रतिनिधिकृत एक्सेस होता है।

OAuth फ्लो

OAuth फ्लो तब ट्रिगर होता है जब आप किसी MCP सर्वर को कॉल करते हैं, जिसमें यूज़र ऑथेंटिकेशन आवश्यक होता है।
1

Request Without Token

SDK MCP सर्वर को कॉल करता है। यदि कोई वैध टोकन मौजूद नहीं है, तो सर्वर WWW-Authenticate हेडर के साथ 401 रिटर्न करता है।
2

Protected Resource Discovery

SDK ऑथराइज़ेशन सर्वर और सपोर्टेड स्कोप्स खोजने के लिए /.well-known/oauth-protected-resource (RFC 9728) फ़ेच करता है।
3

AuthenticationError

SDK AuthenticationError रेज़ करता है, जिसमें connect_url — पूरा OAuth ऑथराइज़ेशन URL — शामिल होता है।
4

Browser Interaction

आपका ऐप यूज़र का ब्राउज़र connect_url पर खोलता है। यूज़र लॉगिन करता है और रिक्वेस्टेड स्कोप्स को अनुमति (या अस्वीकार) देता है।
5

Token Exchange

स्वीकृति के बाद, ऑथराइज़ेशन सर्वर PKCE का उपयोग करके ऑथराइज़ेशन कोड के बदले टोकन जारी करता है। DAuth सर्वर-साइड पर इन टोकनों को स्टोर करता है।
6

Retry Request

यूज़र आपके ऐप पर वापस आता है और रिट्राई ट्रिगर करता है। SDK रिक्वेस्ट को दोबारा भेजता है, इस बार वैध क्रेडेंशियल्स के साथ।
7

Authenticated Requests

आगे की रिक्वेस्ट्स, जो MCP सर्वर को भेजी जाती हैं, में एक्सेस टोकन अपने आप शामिल कर दिया जाता है।
8

Token Refresh

अगर एक्सेस टोकन एक्सपायर हो जाता है, तो DAuth अपने आप रिफ्रेश टोकन का उपयोग करके नया एक्सेस टोकन प्राप्त कर लेता है।

यह कैसे कार्य करता है

OAuth Retry Helper

रीट्राई हेल्पर के साथ OAuth फ़्लो को संभालें:
import webbrowser
from collections.abc import Awaitable, Callable
from typing import TypeVar

from dedalus_labs import AuthenticationError

T = TypeVar("T")

async def with_oauth_retry(fn: Callable[[], Awaitable[T]]) -> T:
    """आवश्यकता होने पर OAuth ब्राउज़र फ़्लो को संभालते हुए async फ़ंक्शन चलाएं।"""
    try:
        return await fn()
    except AuthenticationError as e:
        body = e.body if isinstance(e.body, dict) else {}
        url = body.get("connect_url") or body.get("detail", {}).get("connect_url")
        if not url:
            raise

        print("\nOAuth के लिए ब्राउज़र खोल रहे हैं...")
        print("यदि ब्राउज़र नहीं खुलता है, तो इस पर जाएं:\n")
        print(url)

        webbrowser.open(url)
        input("\nOAuth पूर्ण होने के बाद Enter दबाएं...")

        return await fn()

पूर्ण उदाहरण: DedalusRunner

import asyncio
import webbrowser
from collections.abc import Awaitable, Callable
from typing import TypeVar

from dotenv import load_dotenv

load_dotenv()

from dedalus_labs import AsyncDedalus, AuthenticationError, DedalusRunner

T = TypeVar("T")

async def with_oauth_retry(fn: Callable[[], Awaitable[T]]) -> T:
    try:
        return await fn()
    except AuthenticationError as e:
        body = e.body if isinstance(e.body, dict) else {}
        url = body.get("connect_url") or body.get("detail", {}).get("connect_url")
        if not url:
            raise
        webbrowser.open(url)
        input("\nOAuth पूरा करने के बाद Enter दबाएं...")
        return await fn()

async def main():
    client = AsyncDedalus()
    runner = DedalusRunner(client)

    result = await with_oauth_retry(
        lambda: runner.run(
            input="मेरे हाल के ईमेल की सूची बनाएं और उनका सारांश दें",
            model="openai/gpt-4.1",
            mcp_servers=["anny_personal/gmail-mcp"],
        )
    )

    print(result.output)

    if result.mcp_results:
        for r in result.mcp_results:
            print(f"{r.tool_name} ({r.duration_ms}ms): {r.result}")

asyncio.run(main())

पूरा उदाहरण: Raw Client

ऐसी एकल रिक्वेस्ट के लिए, जहाँ आप API (एप्लिकेशन प्रोग्रामिंग इंटरफ़ेस) के रिस्पॉन्स पर पूरा नियंत्रण रखना चाहते हैं:
import asyncio
import webbrowser
from collections.abc import Awaitable, Callable
from typing import TypeVar

from dotenv import load_dotenv

load_dotenv()

from dedalus_labs import AsyncDedalus, AuthenticationError

T = TypeVar("T")

async def with_oauth_retry(fn: Callable[[], Awaitable[T]]) -> T:
    try:
        return await fn()
    except AuthenticationError as e:
        body = e.body if isinstance(e.body, dict) else {}
        url = body.get("connect_url") or body.get("detail", {}).get("connect_url")
        if not url:
            raise
        webbrowser.open(url)
        input("\nOAuth पूरा करने के बाद Enter दबाएं...")
        return await fn()

async def main():
    client = AsyncDedalus()

    async def do_request():
        return await client.chat.completions.create(
            model="openai/gpt-4.1",
            messages=[
                {
                    "role": "user",
                    "content": "मेरे हाल के ईमेल की सूची बनाएं और उनका सारांश दें",
                }
            ],
            mcp_servers=["anny_personal/gmail-mcp"],
        )

    resp = await with_oauth_retry(do_request)

    print(resp.choices[0].message.content)

    if resp.mcp_tool_results:
        for r in resp.mcp_tool_results:
            print(f"{r.tool_name} ({r.duration_ms}ms): {r.result}")

asyncio.run(main())

परिवेश

# .env
DEDALUS_API_KEY=dsk-live-...
DEDALUS_API_URL=https://api.dedaluslabs.ai
DEDALUS_AS_URL=https://as.dedaluslabs.ai
क्लाइंट-साइड पर किसी भी OAuth क्रेडेंशियल्स की ज़रूरत नहीं होती। MCP सर्वर OAuth कॉन्फ़िगरेशन संभालता है, और DAuth टोकन स्टोरेज का प्रबंधन करता है।

कब उपयोग करें

OAuth इन स्थितियों के लिए उपयुक्त है:
  • यूज़र-फेसिंग एप्लिकेशन
  • डेलीगेटेड ऐक्सेस (यूज़र की ओर से कार्य करना)
  • Gmail, Google Calendar, Linear, GitHub जैसी सेवाएँ
इन स्थितियों में इसके बजाय Bearer Auth का उपयोग करें:
  • API कुंजियाँ और सर्विस टोकन
  • बिना यूज़र कॉन्टेक्स्ट वाले बैकएंड इंटीग्रेशन
  • सर्विस-टू-सर्विस कॉल