<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BBT हिन्दी</title>
    <description>The latest articles on DEV Community by BBT हिन्दी (bbt-hi).</description>
    <link>https://dev.to/bbt-hi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F15903%2F51bb55ab-5ebd-475d-9a18-111e6ec2996a.png</url>
      <title>DEV Community: BBT हिन्दी</title>
      <link>https://dev.to/bbt-hi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bbt-hi"/>
    <language>en</language>
    <item>
      <title>osFoundry की MCP tool list Codex में कितने token खाती है, और इसे हर project के लिए कैसे छोटा करें?</title>
      <dc:creator>BBT</dc:creator>
      <pubDate>Sat, 07 Nov 2026 14:49:39 +0000</pubDate>
      <link>https://dev.to/bbt-hi/osfoundry-kii-mcp-tool-list-codex-men-kitne-token-khaatii-hai-aur-ise-hr-project-ke-lie-kaise-chottaa-kren-12la</link>
      <guid>https://dev.to/bbt-hi/osfoundry-kii-mcp-tool-list-codex-men-kitne-token-khaatii-hai-aur-ise-hr-project-ke-lie-kaise-chottaa-kren-12la</guid>
      <description>&lt;p&gt;यह वह call है जो कोई MCP client handshake के ठीक बाद भेजता है। इसे 2026-11-06 को Tokyo के एक Mac से curl के ज़रिए &lt;a href="https://osfoundry.io/hi" rel="noopener noreferrer"&gt;osFoundry&lt;/a&gt; के server पर भेजा गया। इसके लिए किसी token की ज़रूरत नहीं होती:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -s -D - -X POST https://api.osfoundry.io/api/v1/external-mcp \
    -H 'content-type: application/json' \
    -H 'accept: application/json, text/event-stream' \
    -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

HTTP/2 200
content-type: application/json
content-length: 45368

{"jsonrpc":"2.0","id":2,"result":{"tools":[ …59 tools… ]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;59 में से एक entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read_note_tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read one Note tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read a selected Note, Markdown, Slides, Sheet, Mermaid, Board, Whiteboard, Design, or Artifacts tab by instance ID. Use list_note_attachments for Files and Sources."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"inputSchema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"note_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tab_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"note_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tab_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"annotations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read one Note tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"readOnlyHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="nl"&gt;"openWorldHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"destructiveHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"securitySchemes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:read"&lt;/span&gt;&lt;span class="p"&gt;]}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Codex CLI इस server से एक &lt;code&gt;[mcp_servers.osfoundry]&lt;/code&gt; table और एक &lt;code&gt;url&lt;/code&gt; के ज़रिए जुड़ता है। जब तक client इनमें से कुछ को defer न करे, Codex का model को भेजा गया हर request इन 59 declarations को किसी न किसी रूप में साथ ले जाता है। नीचे वही सवाल हैं जो आपके सामने तब आते हैं जब आप तय करते हैं कि इनमें से कितने साथ जाने चाहिए।&lt;/p&gt;

&lt;h2&gt;
  
  
  पहले turn से पहले Codex क्या fetch करता है?
&lt;/h2&gt;

&lt;p&gt;एक ही URL पर तीन POST: &lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;notifications/initialized&lt;/code&gt; notification, और &lt;code&gt;tools/list&lt;/code&gt;। Live server इनका जवाब ऐसे देता है:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Body&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;initialize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;308 bytes: protocol &lt;code&gt;2025-06-18&lt;/code&gt;, &lt;code&gt;osfoundry 0.1.0&lt;/code&gt;, &lt;code&gt;tools.listChanged: false&lt;/code&gt;, instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;notifications/initialized&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;202&lt;/td&gt;
&lt;td&gt;खाली&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tools/list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;45,368 bytes, 59 tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;बिना token के &lt;code&gt;tools/call&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;resource_metadata&lt;/code&gt; के साथ &lt;code&gt;WWW-Authenticate&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;listChanged: false&lt;/code&gt; का मतलब है कि session के बीच में list बदलने पर server कोई सूचना नहीं देगा। Startup पर Codex को जो list मिलती है, पूरे session के लिए वही list रहती है।&lt;/p&gt;

&lt;p&gt;&lt;code&gt;instructions&lt;/code&gt; string 125 characters की है: "Use list_granted_resources first. Every Note edit must use the exact tab ID. Local-only data is unavailable to cloud clients." OpenAI के Codex docs के मुताबिक Codex इस field को पूरे server के लिए guidance के तौर पर पढ़ता है, और इसके पहले 512 characters अपने आप में पूरे होने चाहिए। यह string उस limit से काफ़ी नीचे है।&lt;/p&gt;

&lt;p&gt;401 वह जगह है जहाँ से OAuth शुरू होता है। वह हिस्सा, और osFoundry हर call पर access क्यों check करता है, उसी endpoint पर Claude की तरफ़ से लिखे गए एक अलग post में cover किया गया है। यहाँ सिर्फ़ catalogue मायने रखता है।&lt;/p&gt;

&lt;h2&gt;
  
  
  59 tools कितने token के होते हैं?
&lt;/h2&gt;

&lt;p&gt;Model तक raw JSON नहीं पहुँचता। Codex हर MCP tool को एक function declaration में बदलता है। Model को name, description और input schema चाहिए। &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;annotations&lt;/code&gt; और &lt;code&gt;securitySchemes&lt;/code&gt; protocol metadata हैं जिन्हें client ख़ुद इस्तेमाल करता है। OpenAI यह publish नहीं करता कि उसकी तरफ़ tool declarations कैसे गिने जाते हैं, इसलिए नीचे के numbers payload गिनते हैं, bill नहीं।&lt;/p&gt;

&lt;p&gt;tiktoken 0.14.0 और &lt;code&gt;o200k_base&lt;/code&gt; encoding से, compact JSON पर नापा गया:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;क्या&lt;/th&gt;
&lt;th&gt;Token&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw &lt;code&gt;tools/list&lt;/code&gt; result, सारे fields&lt;/td&gt;
&lt;td&gt;10,494&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;59 declarations (&lt;code&gt;mcp__osfoundry__&lt;/code&gt; prefix वाला name, description, schema)&lt;/td&gt;
&lt;td&gt;7,609&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;इनमें से descriptions&lt;/td&gt;
&lt;td&gt;2,194&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;इनमें से input schemas&lt;/td&gt;
&lt;td&gt;4,118&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;इनमें से &lt;code&gt;mcp__osfoundry__&lt;/code&gt; prefixes&lt;/td&gt;
&lt;td&gt;413&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client में ही रहने वाला metadata (title, annotations, securitySchemes)&lt;/td&gt;
&lt;td&gt;3,590&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;एक declaration का median 116 token है। सबसे बड़ा &lt;code&gt;edit_note_tab&lt;/code&gt; है, 336 पर, फिर &lt;code&gt;send_channel_message&lt;/code&gt; (237) और &lt;code&gt;upload_linked_chat_artifact&lt;/code&gt; (233)। सबसे छोटा &lt;code&gt;list_granted_resources&lt;/code&gt; है, 57 पर।&lt;/p&gt;

&lt;p&gt;Scope के हिसाब से: 30 &lt;code&gt;osfoundry:read&lt;/code&gt; tools मिलाकर 2,906 token, 26 &lt;code&gt;osfoundry:write&lt;/code&gt; tools 4,378, और 3 &lt;code&gt;osfoundry:run&lt;/code&gt; tools 329। Write tools प्रति tool ज़्यादा महँगे हैं क्योंकि उनमें &lt;code&gt;expected_version&lt;/code&gt;, &lt;code&gt;idempotency_key&lt;/code&gt; और लिखा जाने वाला content होता है।&lt;/p&gt;

&lt;p&gt;लगभग 7,600 token हर request के आगे बैठे रहते हैं, चाहे model osFoundry को call करे या न करे। Cached prompt prefixes की वजह से यह जितना सुनाई देता है उससे सस्ता पड़ता है। फिर भी यह context की जगह घेरता है, और जब model तय करता है कि कौन-सा tool सही है, तो 59 names उसका ध्यान खींचने के लिए आपस में होड़ करते हैं।&lt;/p&gt;

&lt;h2&gt;
  
  
  Codex &lt;code&gt;enabled_tools&lt;/code&gt; को कहाँ apply करता है?
&lt;/h2&gt;

&lt;p&gt;ये keys OpenAI के Codex MCP page पर documented हैं: &lt;code&gt;enabled_tools&lt;/code&gt; एक allow list है, और &lt;code&gt;disabled_tools&lt;/code&gt; एक deny list जो "applied after &lt;code&gt;enabled_tools&lt;/code&gt;" होती है। Implementation &lt;a href="https://github.com/openai/codex/blob/main/codex-rs/codex-mcp/src/tools.rs" rel="noopener noreferrer"&gt;openai/codex repository&lt;/a&gt; में &lt;code&gt;codex-rs/codex-mcp/src/tools.rs&lt;/code&gt; में है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;allows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.enabled&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.disabled&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;filter_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ToolInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ToolFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ToolInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;
        &lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="nf"&gt;.allows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="py"&gt;.tool.name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;इसके दो नतीजे हैं। पहला, filter &lt;code&gt;tool.tool.name&lt;/code&gt; यानी raw MCP name से compare करता है, इसलिए &lt;code&gt;config.toml&lt;/code&gt; में आप &lt;code&gt;read_note_tab&lt;/code&gt; लिखते हैं, &lt;code&gt;mcp__osfoundry__read_note_tab&lt;/code&gt; नहीं। Prefix बाद में उसी file में जोड़ा जाता है, जब model को दिखने वाले names बनाए जाते हैं। दूसरा, set lookup कभी fail नहीं होता। जो name &lt;code&gt;tools/list&lt;/code&gt; में मौजूद नहीं है, वह किसी से match नहीं करता और कोई error भी नहीं देता।&lt;/p&gt;

&lt;p&gt;Filter &lt;code&gt;tools/list&lt;/code&gt; आने के बाद client में चलता है। इससे prompt छोटा होता है, download नहीं, और server को इसके बारे में कुछ पता नहीं होता।&lt;/p&gt;

&lt;h2&gt;
  
  
  Client side को दोबारा बनाना
&lt;/h2&gt;

&lt;p&gt;जिस Mac (Apple M1) पर यह नापा गया, उस पर &lt;code&gt;codex&lt;/code&gt; binary install नहीं है। &lt;code&gt;catalog.py&lt;/code&gt; यहाँ Codex के startup की जगह काम करता है। यह 92 lines का है और &lt;code&gt;uv run --python 3.12 --with tiktoken&lt;/code&gt; से चलता है। यह एक TOML file से &lt;code&gt;[mcp_servers.*]&lt;/code&gt; tables पढ़ता है, &lt;code&gt;http.client&lt;/code&gt; के ज़रिए live endpoint पर तीनों requests भेजता है, raw names पर वही allow-फिर-deny rule लगाता है, &lt;code&gt;mcp__osfoundry__&amp;lt;tool&amp;gt;&lt;/code&gt; declarations बनाता है और उन्हें गिनता है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;kept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;decls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;model_decl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;osfoundry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kept&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Profile file में हर configuration के लिए एक table है। असली &lt;code&gt;config.toml&lt;/code&gt; में एक ही &lt;code&gt;[mcp_servers.osfoundry]&lt;/code&gt; table होगी, global या हर repository के लिए अलग:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notes_kb_records&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://api.osfoundry.io/api/v1/external-mcp"&lt;/span&gt;
&lt;span class="n"&gt;enabled_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;"list_granted_resources"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list_project_resources"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list_note_tabs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"read_note_tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"read_sheet_range"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"search_knowledge_base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"read_knowledge_article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list_record_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"read_record_item"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deny_list&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://api.osfoundry.io/api/v1/external-mcp"&lt;/span&gt;
&lt;span class="n"&gt;disabled_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"request_session_run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"run_graph_session"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cancel_graph_run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s"&gt;"propose_gitnest_work"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"…the other propose_ tools…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s"&gt;"join_agent_network"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"send_agent_message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wait_for_messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s"&gt;"list_agents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"set_status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"claim_connected_profile"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typo&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://api.osfoundry.io/api/v1/external-mcp"&lt;/span&gt;
&lt;span class="n"&gt;enabled_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"list_granted_resources"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list_project_resources"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="s"&gt;"read_note"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"search_knowledge_base"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ uv run --python 3.12 --with tiktoken python catalog.py profiles.toml --runs 10
status (200, 202, 200)  initialize 308 B  tools/list 45368 B  59 tools  instructions 125 chars
raw tools/list result: 10494 tokens (o200k_base)

profile                  tools   bytes  tokens  unknown names
all_59                      59   33559    7609  -
read_only                   30   13181    2906  -
notes_kb_records             9    3937     881  -
coding_project              16    7245    1604  -
deny_list                   40   20943    4693  -
typo                         3    1449     309  read_note
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;read_only&lt;/code&gt; में वे सारे tools हैं जिन पर &lt;code&gt;readOnlyHint: true&lt;/code&gt; है। &lt;code&gt;coding_project&lt;/code&gt; में नौ Note/KB/Record readers के साथ पाँच GitNest readers, &lt;code&gt;edit_record_item&lt;/code&gt; और &lt;code&gt;post_session_note&lt;/code&gt; हैं। &lt;code&gt;deny_list&lt;/code&gt; वे 19 tools हटाती है जिनका local checkout वाले coding assistant के लिए ज़्यादा काम नहीं: तीन run tools, दस &lt;code&gt;propose_…&lt;/code&gt; tools और छह agent-network व profile tools।&lt;/p&gt;

&lt;p&gt;59 tools से घटाकर नौ readers पर आने से declarations 7,609 से 881 token पर आ जाते हैं, यानी 88% कम। Deny list सिर्फ़ 4,693 तक पहुँचती है, क्योंकि write tools ही महँगे हैं और यह उनमें से ज़्यादातर को रहने देती है। Allow list ज़्यादा predictable choice है। Server नए tools जोड़े तब भी यह छोटी ही रहती है, और इसे चुनने की असली वजह यही है।&lt;/p&gt;

&lt;p&gt;&lt;code&gt;typo&lt;/code&gt; वाली row वह failure है जो आपको सच में देखने को मिलेगी। &lt;code&gt;read_note&lt;/code&gt; कोई tool नहीं है (&lt;code&gt;read_note_tab&lt;/code&gt; है), इसलिए profile में तीन ही tools बचते हैं, और कोई शिकायत नहीं करता। Codex आराम से Note की list दिखा देगा, लेकिन फिर उसे खोलने का कोई तरीका नहीं होगा। यह simulator unknown names print करता है। Docs और filter code से जितना दिखता है, Codex ऐसा नहीं करता।&lt;/p&gt;

&lt;h2&gt;
  
  
  Handshake में कितना समय लगता है?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;catalog.py --runs 10&lt;/code&gt; ने तीनों requests का शुरू से आख़िर तक समय दो बार नापा, एक बार एक ही TLS connection पर और एक बार हर request के लिए नए connection के साथ:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Batch (हर एक n=10)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;initialize&lt;/code&gt; median&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;tools/list&lt;/code&gt; median&lt;/th&gt;
&lt;th&gt;पूरा startup median&lt;/th&gt;
&lt;th&gt;min–max&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;एक connection, batch 1&lt;/td&gt;
&lt;td&gt;482 ms&lt;/td&gt;
&lt;td&gt;826 ms&lt;/td&gt;
&lt;td&gt;1,515 ms&lt;/td&gt;
&lt;td&gt;1,034–2,899 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;नया connection, batch 1&lt;/td&gt;
&lt;td&gt;521 ms&lt;/td&gt;
&lt;td&gt;704 ms&lt;/td&gt;
&lt;td&gt;1,715 ms&lt;/td&gt;
&lt;td&gt;1,122–3,107 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;एक connection, batch 2&lt;/td&gt;
&lt;td&gt;454 ms&lt;/td&gt;
&lt;td&gt;828 ms&lt;/td&gt;
&lt;td&gt;1,441 ms&lt;/td&gt;
&lt;td&gt;741–1,915 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;नया connection, batch 2&lt;/td&gt;
&lt;td&gt;432 ms&lt;/td&gt;
&lt;td&gt;478 ms&lt;/td&gt;
&lt;td&gt;1,257 ms&lt;/td&gt;
&lt;td&gt;1,088–1,557 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Connection reuse से कोई consistent फ़र्क़ नहीं पड़ा। Runs के बीच का variation असर से ज़्यादा था। Filtering इस number को बिल्कुल नहीं बदलती, क्योंकि Codex दोनों हालात में पूरी list download करता है।&lt;/p&gt;

&lt;p&gt;Codex की तीन documented settings इस number से जुड़ती हैं। &lt;code&gt;startup_timeout_sec&lt;/code&gt; का default 10 seconds है, और यहाँ सबसे धीमा run 3.1 s का था। &lt;code&gt;mcp_optional_startup_grace_ms&lt;/code&gt; का default 1,000 ms है और docs के मुताबिक यह "controls how long Codex waits for optional MCP servers when building the initial tool catalog"। यहाँ नापा गया हर startup इससे ज़्यादा समय ले गया। अगर osFoundry के tools पहले turn से ही मौजूद होने चाहिए, तो documented विकल्प हैं &lt;code&gt;required = true&lt;/code&gt;, जो startup को server का इंतज़ार करवाता है और server तैयार न हो तो fail हो जाता है, और &lt;code&gt;startup_readiness = "catalog"&lt;/code&gt;, जो live connection बनने तक एक valid cached catalogue से startup पूरा होने देता है। Tool calls के लिए फिर भी live connection चाहिए।&lt;/p&gt;

&lt;h2&gt;
  
  
  Annotations से आपको क्या मिलता है?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;default_tools_approval_mode&lt;/code&gt; में &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;prompt&lt;/code&gt;, &lt;code&gt;writes&lt;/code&gt; या &lt;code&gt;approve&lt;/code&gt; दिया जा सकता है, और "the &lt;code&gt;writes&lt;/code&gt; mode prompts for tools that aren't marked read-only"। osFoundry अपने 59 में से 30 tools पर &lt;code&gt;readOnlyHint: true&lt;/code&gt; लगाता है। &lt;code&gt;writes&lt;/code&gt; के साथ Codex इन्हें बिना पूछे चलाता है और बाकी 29 के लिए पूछता है, यानी वही बँटवारा जो आप हाथ से करते। किसी एक tool के लिए &lt;code&gt;tools.&amp;lt;tool&amp;gt;.approval_mode&lt;/code&gt; default को override करता है, और &lt;code&gt;tools.&amp;lt;tool&amp;gt;.output_token_limit&lt;/code&gt; यह limit करता है कि एक tool का result context में कितना जोड़ सकता है।&lt;/p&gt;

&lt;p&gt;OAuth layer पर scope भी इसी तरह काम करता है। अगर config में &lt;code&gt;scopes&lt;/code&gt; set है तो Codex उसे इस्तेमाल करता है। वरना वह server के challenge या उसके protected-resource metadata से scopes लेता है, और osFoundry की list में &lt;code&gt;osfoundry:read&lt;/code&gt;, &lt;code&gt;osfoundry:write&lt;/code&gt;, &lt;code&gt;osfoundry:run&lt;/code&gt; और &lt;code&gt;osfoundry:models&lt;/code&gt; हैं। &lt;code&gt;scopes = ["osfoundry:read"]&lt;/code&gt; के साथ token सिर्फ़ पढ़ने के लिए issue होता है, और हर write tool अपने &lt;code&gt;securitySchemes&lt;/code&gt; में &lt;code&gt;osfoundry:write&lt;/code&gt; declare करता है, चाहे &lt;code&gt;enabled_tools&lt;/code&gt; में कुछ भी लिखा हो।&lt;/p&gt;

&lt;h2&gt;
  
  
  असली filter कौन-सा है?
&lt;/h2&gt;

&lt;p&gt;तीन filters हैं, और उनमें से सिर्फ़ एक security boundary है।&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config.toml&lt;/code&gt; में &lt;code&gt;enabled_tools&lt;/code&gt; / &lt;code&gt;disabled_tools&lt;/code&gt; तय करते हैं कि model को क्या offer किया जाए। जो भी इस file को edit कर सकता है, वह इसे बदल सकता है।&lt;/li&gt;
&lt;li&gt;osFoundry के Connected tab में Tools checklist, connection पर &lt;code&gt;allowed_tools&lt;/code&gt; के रूप में store होती है। &lt;code&gt;null&lt;/code&gt; का मतलब है "हर मौजूदा और आने वाला supported tool"। इसे owner set करता है, और कोई local file इसे बढ़ा नहीं सकती।&lt;/li&gt;
&lt;li&gt;Project membership और हर call पर होने वाला access check तय करते हैं कि कोई भी tool किस चीज़ को छू सकता है। बिना किसी project वाले connection पर पूरी tool list भी कुछ नहीं पढ़ पाती।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Client filter prompt की साफ़-सफ़ाई के लिए है। इसे token बचाने और model के choices के लिए इस्तेमाल करें, और permissions के लिए बाकी दो का।&lt;/p&gt;

&lt;h2&gt;
  
  
  अगर आप इसे ख़ुद wire up करें
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;दर्जनों tools वाले server के लिए &lt;code&gt;disabled_tools&lt;/code&gt; की जगह &lt;code&gt;enabled_tools&lt;/code&gt; चुनें। यह token में छोटा है और server नए tools जोड़े तब भी stable रहता है।&lt;/li&gt;
&lt;li&gt;Raw MCP names लिखें, और server update होने पर अपनी list को एक fresh &lt;code&gt;tools/list&lt;/code&gt; से diff करें। Unknown names चुपचाप fail होते हैं।&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scopes&lt;/code&gt; को explicitly set करें, ताकि token में config के इरादे से ज़्यादा कुछ न हो।&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;default_tools_approval_mode = "writes"&lt;/code&gt; को ऐसे server के साथ इस्तेमाल करें जो &lt;code&gt;readOnlyHint&lt;/code&gt; ईमानदारी से set करता हो। Prompt का बँटवारा उतना ही अच्छा है जितने annotations।&lt;/li&gt;
&lt;li&gt;अगर server एक second या उससे ज़्यादा दूर है, तो 1,000 ms grace default के भरोसे छोड़ने के बजाय &lt;code&gt;required = true&lt;/code&gt; और &lt;code&gt;startup_readiness = "catalog"&lt;/code&gt; में से एक चुनें।&lt;/li&gt;
&lt;li&gt;Server के &lt;code&gt;instructions&lt;/code&gt; को 512 characters से कम और अपने आप में पूरा रखें। यह tool list की तरह हर session के साथ भेजा जाता है।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tool list का आम तौर पर context budget से क्या रिश्ता है, यह osFoundry के &lt;a href="https://osfoundry.io/hi/glossary/context-window" rel="noopener noreferrer"&gt;context window glossary page&lt;/a&gt; पर है।&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>codex</category>
      <category>tokens</category>
      <category>openai</category>
    </item>
    <item>
      <title>Custom connector से Claude chat को अपने osFoundry projects से कैसे जोड़ें</title>
      <dc:creator>BBT</dc:creator>
      <pubDate>Sat, 07 Nov 2026 13:34:20 +0000</pubDate>
      <link>https://dev.to/bbt-hi/custom-connector-se-claude-chat-ko-apne-osfoundry-projects-se-kaise-jodden-jc5</link>
      <guid>https://dev.to/bbt-hi/custom-connector-se-claude-chat-ko-apne-osfoundry-projects-se-kaise-jodden-jc5</guid>
      <description>&lt;p&gt;इस guide के आख़िर तक, claude.ai पर एक साधारण Claude conversation आपके किसी &lt;a href="https://osfoundry.io/hi" rel="noopener noreferrer"&gt;osFoundry&lt;/a&gt; project के Notes, knowledge bases और Records खोल सकेगी, उन्हीं के आधार पर जवाब दे सकेगी, और उस project के discussion channel में post कर सकेगी। आपकी approval के साथ वह इन्हें edit भी कर सकती है। Claude में आप हमेशा की तरह signed in रहते हैं। हर tool call पर osFoundry तय करता है कि वह chat किन चीज़ों को छू सकती है, और हर call osFoundry में connection के Recent activity में दर्ज होता है। ChatGPT भी इसी तरह, इसी server address से जुड़ता है।&lt;/p&gt;

&lt;h2&gt;
  
  
  कौन क्या करता है
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Claude की तरफ़&lt;/th&gt;
&lt;th&gt;osFoundry की तरफ़&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Login&lt;/td&gt;
&lt;td&gt;आपका Claude account, बिना बदलाव&lt;/td&gt;
&lt;td&gt;आपका osFoundry account connection को एक बार approve करता है, एक workspace के लिए&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model कौन चलाता है&lt;/td&gt;
&lt;td&gt;Claude, उसी chat में जो आप पहले से इस्तेमाल करते हैं&lt;/td&gt;
&lt;td&gt;कुछ नहीं। इस रास्ते पर न कोई model है, न कोई provider key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools कहाँ चलते हैं&lt;/td&gt;
&lt;td&gt;Claude tool call भेजता है&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;api.osfoundry.io&lt;/code&gt; पहले access check करता है, फिर उसे चलाता है&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;किन चीज़ों तक पहुँच है&lt;/td&gt;
&lt;td&gt;जो भी server लौटाए&lt;/td&gt;
&lt;td&gt;वे projects जिनमें आपने connection जोड़ा, और वे channels जिनमें आपने उसे invite किया&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approvals&lt;/td&gt;
&lt;td&gt;Claude का अपना tool-permission prompt&lt;/td&gt;
&lt;td&gt;GitNest और Room के बदलाव "Needs your approval" में इंतज़ार करते हैं&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data कहाँ रहता है&lt;/td&gt;
&lt;td&gt;जवाब आपकी Claude chat में रहता है&lt;/td&gt;
&lt;td&gt;Notes, records और articles osFoundry में रहते हैं। Local-only items कभी device से बाहर नहीं जाते&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. osFoundry में connection बनाएँ
&lt;/h3&gt;

&lt;p&gt;osFoundry में header के key icon पर click करें और Connected tab खोलें। Panel का title "Connected agents" है और यह दिखाता है कि आप किस workspace में हैं। "Connect in three steps" के नीचे:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assistant: Claude चुनें&lt;/li&gt;
&lt;li&gt;Display name: कोई भी नाम जिसे आप बाद में पहचान सकें, जैसे &lt;code&gt;Claude research&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add assistant (assistant जोड़ें) पर click करें&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;नए connection पर "Setup pending. This assistant cannot read or change anything yet." दिखता है। उसके बगल वाले Copy button से Server address copy करें:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.osfoundry.io/api/v1/external-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhi61cfxig1v7yltczuxr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhi61cfxig1v7yltczuxr.jpg" alt="Add assistant के बाद Connected tab, server address और pending connection के साथ" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;उदाहरण: Add assistant के बाद Connected tab, server address और pending connection के साथ&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. इसे Claude में custom connector के रूप में जोड़ें
&lt;/h3&gt;

&lt;p&gt;Claude में Customize → Connectors खोलें और उस URL से एक custom connector जोड़ें। Team या Enterprise plan पर, पहले organization owner इसे Organization settings → Connectors में जोड़ता है, फिर हर member connect करता है। Remote MCP connectors के लिए Anthropic के steps &lt;a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp" rel="noopener noreferrer"&gt;Claude की custom connector guide&lt;/a&gt; में हैं।&lt;/p&gt;

&lt;p&gt;Connect पर click करते ही Claude osFoundry का sign-in अपने आप ढूंढ लेता है। आपको कोई client ID या key paste नहीं करनी पड़ती।&lt;/p&gt;

&lt;h3&gt;
  
  
  3. एक workspace approve करें
&lt;/h3&gt;

&lt;p&gt;आपका browser &lt;code&gt;https://osfoundry.io/external-assistant-authorize&lt;/code&gt; पर पहुँचता है, जिस page का title "Connect an agent" है। यह assistant client और वह host दिखाता है जहाँ वह वापस जाएगा, फिर ये चीज़ें पूछता है:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace to connect: एक workspace। दूसरे workspace के लिए अलग connection चाहिए।&lt;/li&gt;
&lt;li&gt;Requested capabilities, आसान शब्दों में: "Read supported resources in projects you add", "Change supported resources where you have edit access", "Run sessions where you grant a runner role"।&lt;/li&gt;
&lt;li&gt;Connection: "Use pending: Claude research" चुनें ताकि यह step 1 वाले connection से जुड़ जाए, या "Create a new connection" रहने दें।&lt;/li&gt;
&lt;li&gt;"I approve connecting this assistant to " पर tick करें, फिर Connect।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;आप वापस Claude पर भेज दिए जाते हैं। Connection live है, लेकिन अभी उसे कुछ नहीं दिखता। नया connection zero projects से शुरू होता है।&lt;/p&gt;

&lt;h3&gt;
  
  
  4. इसे किसी project में जोड़ें
&lt;/h3&gt;

&lt;p&gt;फिर से key icon → Connected में जाकर connection चुनें। अब वहाँ "Connected." लिखा है। Projects के नीचे कोई project चुनें और Add to project पर click करें।&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9myc1s54srpz8aum8m06.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9myc1s54srpz8aum8m06.jpg" alt="Project में जोड़ा गया connection, नीचे उसकी linked chat के साथ" width="800" height="1110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;उदाहरण: Project में जोड़ा गया connection, नीचे उसकी linked chat के साथ&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;इससे उस project के supported synced content तक access मिल जाता है: Notes, knowledge bases, Record channels, cloud Rooms, उस project को assign की गई GitNest repositories, और project का discussion channel। बाद में project में जोड़ा गया content भी इसमें शामिल होता है। साधारण Message channels अलग हैं। जिस-जिस channel में chat को पढ़ना और जवाब देना हो, उसके लिए Message channels → Choose a Message channel → Invite इस्तेमाल करें।&lt;/p&gt;

&lt;p&gt;Tools section में लिखा है "All supported tools are on by default."। जो tools आप इस connection को नहीं देना चाहते, उनका tick हटाएँ और Save tools पर click करें।&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6tyzev2to95pu562is99.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6tyzev2to95pu562is99.jpg" alt="Claude connection की Tools checklist, default में सब on" width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;उदाहरण: Claude connection की Tools checklist, default में सब on&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Chat में इसे on करें
&lt;/h3&gt;

&lt;p&gt;किसी Claude conversation में + menu → Connectors खोलें और osFoundry connector enable करें। फिर सीधी भाषा में पूछें।&lt;/p&gt;

&lt;h2&gt;
  
  
  एक असली run
&lt;/h2&gt;

&lt;p&gt;नीचे का prompt और जवाब एक demo project का Example content है। Tool names और argument names वही हैं जो live server &lt;code&gt;tools/list&lt;/code&gt; में बताता है। claude.ai में calls connector के नाम के नीचे दिखती हैं। अगर आप यही URL Claude Code में &lt;code&gt;osfoundry&lt;/code&gt; नाम से जोड़ते हैं, तो वही tools &lt;code&gt;mcp__osfoundry__list_project_resources&lt;/code&gt; वगैरह के रूप में दिखते हैं।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;उदाहरण

आप: osFoundry से बताओ, Q3 launch checklist में अभी क्या-क्या बाकी है?
     Support KB में कुछ उससे उल्टा लिखा हो तो check करो, फिर
     "pricing page" record को Ready mark कर दो।

Claude → list_granted_resources {}
       ← 1 connected project: "Launch Q3" (workspace)
Claude → list_project_resources {"project_id": "…", "resource_type": "note", "search": "checklist"}
       ← Note "Q3 launch checklist"
Claude → list_note_tabs {"note_id": "…"}
       ← tabs: Note (text), Sheet "Owners"
Claude → read_note_tab {"note_id": "…", "tab_id": "…"}
       ← 9 items, 3 unchecked
Claude → search_knowledge_base {"knowledge_base_id": "…", "query": "refund window"}
       ← article "Refund policy" (2 दिन पहले update हुआ)
Claude → read_record_item {"record_channel_id": "…", "item_id": "…"}
       ← "pricing page", status Draft, version …
Claude → edit_record_item {"record_channel_id": "…", "item_id": "…",
                           "values": {"status": "Ready"},
                           "expected_version": "…", "idempotency_key": "…"}
       [Claude आपसे यह tool call allow करने को कहता है → Allow]
       ← saved, नया version …

Claude: तीन items बाकी हैं: press embargo की तारीख, FAQ translation,
        और pricing page पर refund वाली line। Checklist में 14 दिन
        लिखा है; KB article "Refund policy" में 30। Pricing page
        record को मैंने Ready mark कर दिया है।
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;उस transcript की दो बातें जान-बूझकर रखी गई हैं। &lt;code&gt;edit_record_item&lt;/code&gt; को वह version चाहिए जो &lt;code&gt;read_record_item&lt;/code&gt; ने लौटाया था, इसलिए अगर बीच में record बदल गया हो तो वह overwrite होने के बजाय reject हो जाता है। दोबारा भेजा गया वही &lt;code&gt;idempotency_key&lt;/code&gt; पहला result लौटाता है, इसलिए retry किया गया call दो बार write नहीं करता।&lt;/p&gt;

&lt;h2&gt;
  
  
  सीमा कहाँ है
&lt;/h2&gt;

&lt;p&gt;osFoundry आपकी Claude chats नहीं खोल सकता। MCP connection Claude को osFoundry tools तब call करने देता है जब Claude ऐसा तय करे। उल्टी दिशा में osFoundry के पास कोई API नहीं है जिससे वह किसी personal conversation को list करे, पढ़े या शुरू करे। Chat को project से link करने वाला tool (&lt;code&gt;link_current_chat&lt;/code&gt;) वह label लेता है जो chat अपने बारे में ख़ुद बताती है, और osFoundry उसे verified identity नहीं, बल्कि routing hint मानता है। इसी वजह से Claude को osFoundry से कोई background notification नहीं मिलता। वह तभी काम करता है जब आप conversation खोलकर कुछ पूछते हैं।&lt;/p&gt;

&lt;p&gt;Local-only data local ही रहता है। Server अपने &lt;code&gt;initialize&lt;/code&gt; reply में ख़ुद यह कहता है: "Local-only data is unavailable to cloud clients."। Local Rooms, local Graph sessions और कभी sync न हुआ content connection को नहीं दिखता। Desktop Graph sessions share करना उसी tab में एक अलग switch है, और इसके लिए desktop app खुला और signed in होना चाहिए।&lt;/p&gt;

&lt;p&gt;Access हर call पर check होता है, हर sign-in पर नहीं। हर call को connection के status, उसके workspace, project की मौजूदा membership, item इस समय किस project में है, और उस item पर आपके अपने role से मिलाया जाता है। किसी Note को दूसरे project में move करें, project हटा दें, या Revoke connection पर click करें, तो अगला call refuse हो जाता है। Edits के लिए यह भी ज़रूरी है कि आपके पास, यानी connection approve करने वाले व्यक्ति के पास, अब भी edit rights हों।&lt;/p&gt;

&lt;p&gt;कुछ writes proposals बन जाते हैं। GitNest work, change sets, file imports, pull requests और Room app installs &lt;code&gt;propose_…&lt;/code&gt; tools से होकर जाते हैं। ये Connected tab में "Needs your approval" के नीचे इंतज़ार करते हैं, जहाँ Approve या Decline चुनने से पहले आप target repository या Room और files देख सकते हैं। Claude को आपका Git provider token या कोई secret value कभी नहीं मिलती।&lt;/p&gt;

&lt;p&gt;Message channels के लिए invitation ज़रूरी है। किसी project में होने से सिर्फ़ उसी project का discussion channel खुलता है। बाक़ी हर channel के लिए अलग से Invite चाहिए, और private channel में उसके owner को invite करना होता है।&lt;/p&gt;

&lt;h2&gt;
  
  
  आगे क्या
&lt;/h2&gt;

&lt;p&gt;उसी project में एक knowledge base जोड़ें और Claude से ऐसा सवाल पूछें जिसका जवाब आप आम तौर पर उसी से देते हैं, जैसे "हमारी KB refunds के बारे में क्या कहती है, article के नाम के साथ?"। &lt;code&gt;search_knowledge_base&lt;/code&gt; article ID और उसके last update का समय लौटाता है, ताकि आप source check कर सकें। osFoundry की knowledge bases कैसे organised हैं, यह &lt;a href="https://osfoundry.io/hi/features/knowledge-bases" rel="noopener noreferrer"&gt;knowledge bases page&lt;/a&gt; पर है।&lt;/p&gt;

</description>
      <category>claude</category>
      <category>mcp</category>
      <category>osfoundry</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Claude का custom connector osFoundry का OAuth server कैसे ढूंढता है, और हर call पर access क्यों check होता है?</title>
      <dc:creator>BBT</dc:creator>
      <pubDate>Fri, 06 Nov 2026 10:52:06 +0000</pubDate>
      <link>https://dev.to/bbt-hi/claude-kaa-custom-connector-osfoundry-kaa-oauth-server-kaise-ddhuunddhtaa-hai-aur-hr-call-pr-access-kyon-g18</link>
      <guid>https://dev.to/bbt-hi/claude-kaa-custom-connector-osfoundry-kaa-oauth-server-kaise-ddhuunddhtaa-hai-aur-hr-call-pr-access-kyon-g18</guid>
      <description>&lt;p&gt;जब कोई remote MCP client बिना token के &lt;a href="https://osfoundry.io/hi" rel="noopener noreferrer"&gt;osFoundry&lt;/a&gt; का कोई tool call करता है, तो उसे यह मिलता है। यह request 2026-11-06 को Tokyo में एक Mac से curl से भेजी गई थी:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -s -D - -X POST https://api.osfoundry.io/api/v1/external-mcp \
    -H 'content-type: application/json' \
    -H 'accept: application/json, text/event-stream' \
    -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
         "params":{"name":"list_project_resources","arguments":{}}}'

HTTP/2 401
www-authenticate: Bearer resource_metadata="https://api.osfoundry.io/.well-known/oauth-protected-resource/api/v1/external-mcp", error="invalid_token", error_description="Connect osFoundry to continue"

{"jsonrpc":"2.0","id":3,"result":{"isError":true,
  "content":[{"type":"text","text":"Authentication required"}],
  "_meta":{"mcp/www_authenticate":["Bearer resource_metadata=\"https://api.osfoundry.io/.well-known/oauth-protected-resource/api/v1/external-mcp\", ..."]}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude के custom connector को, या ChatGPT के developer mode वाले MCP connection को, sign-in page ढूंढने के लिए बस यही एक header काफ़ी है। User को सिर्फ़ URL paste करना होता है। नीचे जो कुछ भी है वह live endpoint पर बिना authentication वाली requests से लिया गया है, साथ में Python का एक छोटा rebuild है जो locally चलाया गया। यह rebuild वह हिस्सा मापता है जो curl नहीं दिखा सकता: sign-in के बाद access के साथ क्या होता है।&lt;/p&gt;

&lt;h2&gt;
  
  
  Token मिलने से पहले client को क्या दिखता है?
&lt;/h2&gt;

&lt;p&gt;तीन calls, तीन अलग जवाब:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;क्या वापस आता है&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;initialize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;protocol &lt;code&gt;2025-06-18&lt;/code&gt;, server &lt;code&gt;osfoundry 0.1.0&lt;/code&gt;, साथ में instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tools/list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;59 tools, 45,368 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tools/call&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;WWW-Authenticate&lt;/code&gt;, जो resource metadata की ओर इशारा करता है&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;endpoint पर &lt;code&gt;GET&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;405&lt;/td&gt;
&lt;td&gt;GET पर कोई SSE stream नहीं&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Handshake और tool catalogue public हैं। सिर्फ़ tool call करने के लिए token चाहिए। इससे host किसी के sign in करने से पहले ही user को दिखा सकता है कि कौन-कौन से tools मौजूद हैं। Catalogue में कोई user data नहीं है, और &lt;code&gt;initialize&lt;/code&gt; में मौजूद &lt;code&gt;instructions&lt;/code&gt; string generic है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use list_granted_resources first. Every Note edit must use the exact tab ID.
Local-only data is unavailable to cloud clients.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tools/list&lt;/code&gt; का हर tool बताता है कि उसे कौन-सा OAuth scope चाहिए और क्या वह सिर्फ़ read करता है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"edit_record_item"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"annotations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"readOnlyHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"destructiveHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"openWorldHint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"securitySchemes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:write"&lt;/span&gt;&lt;span class="p"&gt;]}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;59 tools में से: 30 को &lt;code&gt;osfoundry:read&lt;/code&gt; चाहिए और वे &lt;code&gt;readOnlyHint: true&lt;/code&gt; से marked हैं, 26 को &lt;code&gt;osfoundry:write&lt;/code&gt; चाहिए, और 3 को &lt;code&gt;osfoundry:run&lt;/code&gt; चाहिए (&lt;code&gt;request_session_run&lt;/code&gt;, &lt;code&gt;run_graph_session&lt;/code&gt;, &lt;code&gt;cancel_graph_run&lt;/code&gt;)। Host &lt;code&gt;readOnlyHint&lt;/code&gt; के आधार पर तय कर सकता है कि किन calls पर approval prompt दिखाना है।&lt;/p&gt;

&lt;h2&gt;
  
  
  401 उसे कहां भेजता है?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;resource_metadata&lt;/code&gt; RFC 9728 (OAuth Protected Resource Metadata) को follow करता है। Well-known suffix host के ठीक बाद आता है, और resource path उसके पीछे जुड़ता है। इसे resource URL के आख़िर में नहीं जोड़ा जाता:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /.well-known/oauth-protected-resource/api/v1/external-mcp   200
GET /.well-known/oauth-protected-resource                       200 (same document)
GET /api/v1/external-mcp/.well-known/oauth-protected-resource   404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io/api/v1/external-mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"authorization_servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"scopes_supported"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:write"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"osfoundry:models"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;अगर आप client हाथ से बना रहे हैं, तो सबसे पहली गलती आप यही 404 वाली करेंगे। URL ख़ुद बनाने की बजाय header से पढ़िए।&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization server अपने बारे में क्या बताता है?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/.well-known/oauth-authorization-server&lt;/code&gt; (RFC 8414):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"issuer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"authorization_endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io/api/v1/external-oauth/authorize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"token_endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io/api/v1/external-oauth/token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"registration_endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.osfoundry.io/api/v1/external-oauth/register"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"grant_types_supported"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"authorization_code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refresh_token"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"token_endpoint_auth_methods_supported"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"code_challenge_methods_supported"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"S256"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"authorization_response_iss_parameter_supported"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;इसे फ़ैसलों की एक chain की तरह पढ़िए। इसमें &lt;code&gt;registration_endpoint&lt;/code&gt; है, इसलिए host ख़ुद को register कर सकता है (dynamic client registration) और user को कभी client ID से जूझना नहीं पड़ता। Token auth &lt;code&gt;none&lt;/code&gt; है, यानी host एक public client है जिसके पास client secret नहीं है, और S256 वाला PKCE ही code को उस client से बांधता है जिसने उसे मांगा था। Authorization response में &lt;code&gt;iss&lt;/code&gt; उस गड़बड़ी से बचाता है जब कोई host कई authorization servers से बात कर रहा हो।&lt;/p&gt;

&lt;p&gt;Authorize step browser को osFoundry के consent page &lt;code&gt;https://osfoundry.io/external-assistant-authorize&lt;/code&gt; पर भेजता है। वहां user ठीक एक workspace चुनता है और "I approve connecting this assistant to …" (मैं इस assistant को … से जोड़ने की अनुमति देता हूं) पर tick करता है। Approval में सिर्फ़ एक workspace का नाम होता है, और कुछ नहीं। नए connection में कोई project नहीं होता। Owner उन्हें बाद में app में जोड़ता है (key icon → Connected → Add to project)।&lt;/p&gt;

&lt;h2&gt;
  
  
  सिर्फ़ scope काफ़ी क्यों नहीं है?
&lt;/h2&gt;

&lt;p&gt;Scope उसी समय तय हो जाता है जब token mint होता है। &lt;code&gt;osfoundry:write&lt;/code&gt; बताता है कि connection write वाले actions कर सकता है। यह नहीं बताता कि कौन-सा Note, और इसे यह पता भी नहीं हो सकता कि वह Note दस मिनट पहले किसी दूसरे project में चला गया। osFoundry के design notes में लिखा है कि हर call पर क्या दोबारा पढ़ा जाता है: connection status, workspace, project membership, resource का मौजूदा project और ACL, channel membership या session role, tool, और OAuth scope। जिस व्यक्ति ने connection approve किया था, उसके पास उस item पर अभी भी edit rights होने चाहिए। हटाना या reassign करना "तुरंत लागू होता है"।&lt;/p&gt;

&lt;p&gt;दूसरा रास्ता यह है कि project list को token में डाल दिया जाए, या token को key बनाकर cache में रख दिया जाए, और expiry तक उस पर भरोसा किया जाए। यह लिखने में सस्ता है। नीचे वाला rebuild दोनों को implement करता है ताकि behaviour का फ़र्क़ मापा जा सके।&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebuild
&lt;/h2&gt;

&lt;p&gt;इसमें कोई Claude binary शामिल नहीं है। &lt;code&gt;client.py&lt;/code&gt; host का रोल निभाता है और &lt;code&gt;server.py&lt;/code&gt; MCP server का। दोनों सिर्फ़ standard library इस्तेमाल करते हैं, मिलाकर लगभग 280 lines, और Apple M1 पर Python 3.9.6 में चलाए गए। Server plain HTTP JSON-RPC पर &lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;tools/list&lt;/code&gt; और &lt;code&gt;tools/call&lt;/code&gt; implement करता है, साथ में दोनों well-known documents, &lt;code&gt;/authorize&lt;/code&gt; (consent page एक workspace के लिए अपने आप approve हो जाता है), और S256 PKCE के साथ &lt;code&gt;/token&lt;/code&gt;। कुछ &lt;code&gt;/admin/*&lt;/code&gt; routes Connected tab में owner के clicks की जगह लेते हैं।&lt;/p&gt;

&lt;p&gt;हर tool से पहले चलने वाला check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;note_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;TOOL_SCOPE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;token_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scopes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;insufficient_scope&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;CHECK&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                     &lt;span class="c1"&gt;# design B: trust issue-time state
&lt;/span&gt;        &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;note_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;NOTES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;note_id&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;token_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;projects_at_issue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_in_project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONNECTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;connection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;connection_revoked&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;note_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NOTES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workspace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workspace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;connection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PROJECT_MEMBERS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_in_project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Client बिना token के शुरू होता है। वह एक tool call करता है, 401 लेता है, &lt;code&gt;WWW-Authenticate&lt;/code&gt; से &lt;code&gt;resource_metadata&lt;/code&gt; parse करता है, दोनों metadata documents fetch करता है, नए PKCE verifier के साथ authorize और token चलाता है, और फिर scenario से गुज़रता है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ CHECK=per_call python3 server.py &amp;amp;  python3 client.py 8767
discovery: first call -&amp;gt; 401, metadata /.well-known/oauth-protected-resource/mcp, 5 round trips, 11.3 ms
1 fresh connection, no project yet           200 OK   []
2 after owner adds project A                 200 OK   ["note-a1"]
3 read note in A                             200 OK   "Q3 launch checklist"
4 read note in B (never added)               200 DENY not_in_project
5 write with a read-only token               403 DENY insufficient_scope
6 write with read+write token                200 OK   "saved"
7 same read after note moved to B            200 DENY not_in_project
8 same read after owner removes project A    200 DENY not_in_project
9 same read after revoke                     200 DENY connection_revoked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;वही client &lt;code&gt;CHECK=token_only&lt;/code&gt; के ख़िलाफ़। यहां token में उसके पिछले refresh के समय की project list होती है:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7 same read after note moved to B            200 DENY not_in_project
8 same read after owner removes project A    200 OK   "Q3 launch checklist v2"
9 same read after revoke                     200 OK   "Q3 launch checklist v2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Steps 1–7 एक जैसे हैं। Token-only design में भी step 7 deny होता है, क्योंकि note का project live lookup किया जाता है। Token-only design सिर्फ़ उन्हीं बातों पर पुराना पड़ता है जो token के अंदर रखी हैं। Owner के लिए असली मायने steps 8 और 9 के हैं: उन्होंने project हटाया, फिर connection revoke किया, और chat फिर भी पढ़ती रही। Token-only design में यह token expire होने तक चलता है, जो इस rebuild में &lt;code&gt;expires_in: 3600&lt;/code&gt; है।&lt;/p&gt;

&lt;p&gt;Denials दो layers में बंटे हैं। Scope न होना protocol level की failure है: &lt;code&gt;error="insufficient_scope"&lt;/code&gt; के साथ 403, और ज़रूरी scope &lt;code&gt;WWW-Authenticate&lt;/code&gt; में, ताकि host ज़्यादा scope मांग सके। कौन-सा item शामिल है, उससे जुड़ी हर चीज़ एक सामान्य tool result है जिसमें &lt;code&gt;isError: true&lt;/code&gt; होता है। दोबारा authorise करने से वह ठीक नहीं होगा, इसलिए host को retry करने को कहने का कोई मतलब नहीं।&lt;/p&gt;

&lt;h2&gt;
  
  
  हर call पर check की क़ीमत क्या है?
&lt;/h2&gt;

&lt;p&gt;Server के अंदर &lt;code&gt;access()&lt;/code&gt; के चारों ओर &lt;code&gt;time.perf_counter_ns()&lt;/code&gt; से मापा गया, हर run में 1,000 calls (500 allowed, 500 denied), एक ऐसे Mac पर जिस पर दूसरे jobs भी चल रहे थे:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;access() median&lt;/th&gt;
&lt;th&gt;access() p99&lt;/th&gt;
&lt;th&gt;loopback tool call, median&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;हर call पर check, 6 runs&lt;/td&gt;
&lt;td&gt;1.3–1.6 µs&lt;/td&gt;
&lt;td&gt;6.1–7.0 µs&lt;/td&gt;
&lt;td&gt;0.43–0.78 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;सिर्फ़ token, 3 runs&lt;/td&gt;
&lt;td&gt;0.7–1.6 µs&lt;/td&gt;
&lt;td&gt;3.5–7.7 µs&lt;/td&gt;
&lt;td&gt;0.35–1.36 ms (2 runs)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Memory में यह recheck loopback HTTP call के noise में खो जाता है। असली server set membership की जगह database lookups करता है, इसलिए उसकी क़ीमत ज़्यादा होती है। यह rebuild उसे माप नहीं सकता, इसलिए उसके लिए कोई number नहीं दिया गया है। अंदाज़े के लिए, Tokyo से live endpoint तक network leg urllib में हर बार नए TLS connection के साथ लगभग 500 ms से 800 ms प्रति request है (हर एक के लिए n=10: &lt;code&gt;initialize&lt;/code&gt; median 790 ms, &lt;code&gt;tools/list&lt;/code&gt; 816 ms, 401 वाला &lt;code&gt;tools/call&lt;/code&gt; 565 ms, हर metadata document लगभग 520–530 ms)। Connector का समय access check में नहीं जाता।&lt;/p&gt;

&lt;p&gt;Discovery ख़ुद locally 5 HTTP round trips थी: 401, resource metadata, server metadata, authorize, token। सात runs में इसमें 7.5–13.4 ms लगे, और एक बार Mac busy होने पर 34 ms। Live server के ख़िलाफ़, बिना credentials के किए जा सकने वाले तीन GET/POST legs cold start से मिलाकर लगभग 1.6 s लेते हैं। Authorize leg तो वैसे भी किसी इंसान का इंतज़ार करता है।&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude osFoundry को call कर सकता है, पर osFoundry आपकी Claude chats क्यों नहीं खोल सकता?
&lt;/h2&gt;

&lt;p&gt;इस setup में caller host है। वही connection खोलता है, tools list करता है और तय करता है कि कब कौन-सा tool call करना है। Server सिर्फ़ जवाब देता है। इस setup में ऐसा कुछ नहीं है जो server को host की conversations तक पहुंच दे। osFoundry का plan यह बात अपनी capability table में कहता है: मनचाही personal ChatGPT/Claude chats खोलना या उनकी list निकालना "No" है, साथ में "No general host API is provided for this"।&lt;/p&gt;

&lt;p&gt;इसी से tools का design तय होता है। &lt;code&gt;link_current_chat&lt;/code&gt; में chat ख़ुद अपने अंदर से link बनाती है। उसका label chat ख़ुद बताती है, और osFoundry उसे routing के लिए इस्तेमाल करता है, identity के तौर पर नहीं। किसी linked Claude chat को दिया गया काम तब तक इंतज़ार करता है जब तक user वह chat खोलकर उससे check करने को न कहे। ChatGPT में subscribed chats के लिए MCP Events हैं, और osFoundry का plan इसे host-specific मानता है।&lt;/p&gt;

&lt;p&gt;Data से जुड़े सारे फ़ैसले server side के पास हैं, क्योंकि सिर्फ़ उसे ही किसी project की मौजूदा स्थिति पता होती है। कब action लेना है और user से पूछना है या नहीं, ये सारे फ़ैसले host side के पास हैं। हर call पर होने वाला check ही server को सही बनाए रखता है जब ये दोनों sides एक-दूसरे से अलग हो जाती हैं।&lt;/p&gt;

&lt;h2&gt;
  
  
  अगर आप इसे ख़ुद wire up करें
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;401 के &lt;code&gt;WWW-Authenticate&lt;/code&gt; में &lt;code&gt;resource_metadata&lt;/code&gt; डालिए और RFC 9728 को &lt;code&gt;/.well-known/oauth-protected-resource/&amp;lt;resource path&amp;gt;&lt;/code&gt; पर serve कीजिए। जो client URL हाथ से बनाता है, वह गलती कर सकता है। Header हर client को इससे बचा लेता है।&lt;/li&gt;
&lt;li&gt;Sign-in से पहले क्या public है, यह तय कीजिए। osFoundry &lt;code&gt;initialize&lt;/code&gt; और &lt;code&gt;tools/list&lt;/code&gt; खुला रखता है और &lt;code&gt;tools/call&lt;/code&gt; को guard करता है। अगर आपके tool descriptions tenants के बारे में कुछ भी leak करते हैं, तो &lt;code&gt;tools/list&lt;/code&gt; को भी guard कीजिए।&lt;/li&gt;
&lt;li&gt;हर tool के लिए एक scope और &lt;code&gt;readOnlyHint&lt;/code&gt; declare कीजिए। Hosts इनसे approval prompts बना सकते हैं, और 403 &lt;code&gt;insufficient_scope&lt;/code&gt; host को दोबारा मांगने के लिए कुछ ठोस देता है।&lt;/li&gt;
&lt;li&gt;Token छोटा रखिए: कौन, कौन-सा connection, कौन-से scopes। Workspace, project membership, resource का project और approve करने वाले का मौजूदा role हर call पर दोबारा पढ़िए, ताकि revoke और "दूसरे project में move करना" अगली ही call पर असर करें।&lt;/li&gt;
&lt;li&gt;Resource denials को 401/403 की बजाय tool results के रूप में लौटाइए। दूसरा token "यह Note project B में है" को ठीक नहीं करेगा।&lt;/li&gt;
&lt;li&gt;Writes के साथ &lt;code&gt;expected_version&lt;/code&gt; और एक idempotency key भेजिए। Hosts retry करते हैं, और models calls दोबारा भेजते हैं।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Spec का MCP वाला हिस्सा &lt;a href="https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization" rel="noopener noreferrer"&gt;MCP authorization page&lt;/a&gt; पर है। osFoundry की अपनी छोटी परिभाषा उसकी &lt;a href="https://osfoundry.io/hi/glossary/mcp" rel="noopener noreferrer"&gt;MCP वाली glossary entry&lt;/a&gt; में है।&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>oauth</category>
      <category>claude</category>
      <category>security</category>
    </item>
  </channel>
</rss>
