<?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/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Elaichi blog</title>
    <link>https://elaichi.ai/blog/</link>
    <atom:link href="https://elaichi.ai/feed.xml" rel="self" type="application/rss+xml"/>
    <description>Elaichi is a governed MCP control plane and hosted MCP gateway. Claude, ChatGPT, Cursor or any MCP client signs into one org-wide MCP endpoint over OAuth, and the Elaichi Agent works inside the app. Both reach a catalog of 600+ connectors: ones Elaichi authors and runs itself, and vendors&apos; own MCP servers that Elaichi governs under the same rules. Every agent stays inside the permissions the person it acts for already has, and every call is checked, and logged when it runs.</description>
    <language>en</language>
    <lastBuildDate>Fri, 09 Oct 2026 00:00:00 GMT</lastBuildDate>
    <image>
      <url>https://elaichi.ai/brand/elaichi-full-light.svg</url>
      <title>Elaichi blog</title>
      <link>https://elaichi.ai/blog/</link>
    </image>
    <item>
      <title>AI consultant for small business: what to expect</title>
      <link>https://elaichi.ai/blog/ai-consultant-for-small-business/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/ai-consultant-for-small-business/</guid>
      <description>A good AI consultant for small business learns your work, sets AI up in your own apps, tests it with your team and hands it over in writing.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A useful AI consultant for a small or mid-size business picks one repetitive job that lives in apps you already use, writes a one-page plan you approve, sets it up in your real apps, tests it with the people who do the work, and hands over a written guide. Before you hire, ask who owns what is built, where your data is stored, and what happens after handover. Elaichi Services does this work with forward deployed engineers, and you own everything they set up.</aside>
<p>The owner of a small business hears about AI every week. The sales lead wants it for follow-ups. The office manager wants it for invoices. Somebody suggests hiring an AI consultant. The hard part is telling a consultant who will change how the week runs from one who will deliver a slide deck and leave.</p>
<h2 id="what-should-an-ai-consultant-for-small-business-actually-do">What should an AI consultant for small business actually do?</h2>
<p>Some AI consultants stop at a plan. A useful AI consultant for small business goes further: it learns how your team works, picks one job for AI, sets it up in the apps you already use, and stays until your team uses it. The deliverable is a working setup in your own accounts, not a report.</p>
<p>Most small firms are still at the start. The U.S. Census Bureau found that <a href="https://www.census.gov/library/stories/2026/05/ai-use-businesses.html">less than 20% of firms with four or fewer employees reported using AI</a>, against 37% of firms with at least 250 employees. One likely reason is capacity. Large firms often have people whose job is to connect new tools to old systems. A small firm usually has an owner, an ops lead and a few team leads, all busy with the real work.</p>
<p>So a consultant for a small or mid-size business has a different job from one who advises a large enterprise. Strategy matters less. Setup, testing and handover matter more. Judge the consultant by the jobs that AI does for your team three months later.</p>
<h2 id="how-do-you-pick-the-first-job-for-ai">How do you pick the first job for AI?</h2>
<p>Pick a job that repeats every week, lives in apps you already use, and is easy to check. A good first job saves hours, and a person can see in one glance if the AI got it right.</p>
<p>Use three tests:</p>
<ul>
<li><strong>It repeats.</strong> The same steps happen every day or every week, such as copying data from one app to another.</li>
<li><strong>It lives in your apps.</strong> The facts the AI needs are already in your CRM (the app that holds your customer records), your accounting software, your support desk or your HR app.</li>
<li><strong>It is easy to check.</strong> A person can review the result quickly before it goes anywhere important.</li>
</ul>
<p>Good first jobs look different by team. Sales can get a short brief before each call, built from the CRM and past emails. Support can get a draft reply that a person checks before it is sent. Finance can match invoices to orders and flag what is overdue. Operations can track orders and suppliers across apps and flag late ones. HR can answer common questions from the HR app and set up new hires across tools.</p>
<p>The industry changes the apps, not the method. A distributor might start with dealer questions about stock. A law or accounting firm might start with time tracking and client updates. An online store might start with returns and order questions. Leave payroll changes and payments for later, when your team trusts the setup.</p>
<h2 id="what-should-you-prepare-before-the-first-call">What should you prepare before the first call?</h2>
<p>Prepare a short list of the jobs that eat the week, the apps each job touches, and the names of two people. One person does the work every day. The other is an admin who can connect your apps and approve a plan.</p>
<p>For each job, write down three things. How often does it happen? How long does it take? What goes wrong when it is late or wrong? Rough numbers are fine. They help the consultant rank the jobs, and they give you a baseline to measure against later.</p>
<p>List every app the job touches, including spreadsheets and shared inboxes. Note who has admin access to each app. Many projects slow down in week one because nobody can approve an app connection.</p>
<p>Also note the AI assistant your company already pays for, if any. A setup that ignores it means a second subscription and a second place for people to work.</p>
<h2 id="what-does-a-good-first-engagement-look-like">What does a good first engagement look like?</h2>
<p>A good first engagement has five steps: learn the work, write a one-page plan, set it up in your real apps, test it with the people who do the work, and hand over with a written guide. Each step has something you can see and approve.</p>
<ol>
<li><strong>Learn the work.</strong> The consultant talks to the people who do the job, not only the owner. They ask what takes the most time and what an error costs.</li>
<li><strong>Write a one-page plan.</strong> The plan says which jobs the AI takes over, which apps it needs, who can use it, and how you will know it works. You approve it before any setup starts.</li>
<li><strong>Set it up in your real apps.</strong> The consultant connects your actual CRM, support desk or accounting software, not a copy or a demo account. The AI gets only the access the plan names.</li>
<li><strong>Test with the people who do the work.</strong> Your team runs real tasks and reports what is wrong. The consultant fixes it and tests again.</li>
<li><strong>Hand over with a written guide.</strong> The guide covers how to add people and apps, change who can do what, and check what the AI did.</li>
</ol>
<p>The plan in step 2 protects you. It turns a vague goal into a scope you can check. If a consultant wants to skip it, the scope will drift and so will the cost.</p>
<h2 id="which-questions-should-you-ask-an-ai-consultant">Which questions should you ask an AI consultant?</h2>
<p>Ask four questions, and expect clear written answers. Who owns what is built? Where is our data stored? Does it work with the AI assistant we already pay for? What happens after handover?</p>
<p><strong>Who owns what is built?</strong> The instructions, the app connections and the results should live in accounts you control. If they live in the consultant's own tools, you rent your own process.</p>
<p><strong>Where is our data stored, and who can see it?</strong> Ask which region holds your data and which companies process it for the consultant. When a consultant handles personal data for you, it is usually a processor under data protection law. The UK regulator's guidance lists what a <a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/accountability-and-governance/contracts-and-liabilities-between-controllers-and-processors-multi/what-needs-to-be-included-in-the-contract/">controller and processor contract must include</a>, such as acting only on your documented instructions and deleting or returning the data when the contract ends. Ask for those terms in writing.</p>
<p><strong>Does it work with the AI assistant we already pay for?</strong> Many AI assistants can connect to other apps. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A setup built on that open standard keeps working if you change assistants later.</p>
<p><strong>What happens after handover?</strong> Your admins should be able to add a person, remove a person and check the activity log without a call to the consultant. Ask to see the written guide from a past project.</p>
<h2 id="what-are-the-red-flags-in-an-ai-consultant">What are the red flags in an AI consultant?</h2>
<p>The main red flags are a plan with no named job, a demo built on sample data, and a setup that only the consultant can run. Any one of these means the AI is unlikely to reach daily use.</p>
<p>Watch for these signs:</p>
<ul>
<li>The proposal talks about "AI strategy" for pages and names no job, no app and no person.</li>
<li>The demo uses made-up data, and the consultant avoids a test in your real apps.</li>
<li>The AI gets admin access to every app, when the job needs only one or two.</li>
<li>Nobody can tell you what the AI did last Tuesday, because nothing is logged.</li>
<li>The work lives in the consultant's accounts, and leaving means starting over.</li>
<li>The handover is a meeting, not a document.</li>
</ul>
<p>Unapproved AI use is a related risk. A <a href="https://www.federalreserve.gov/econres/notes/feds-notes/monitoring-ai-adoption-in-the-u-s-economy-20260403.html">Federal Reserve note</a> says "shadow AI", meaning use without approval, may still be a substantive problem for organizations. A consultant who sets up approved access with clear limits gives your team a safe path instead of a workaround.</p>
<h2 id="when-do-you-not-need-an-ai-consultant">When do you not need an AI consultant?</h2>
<p>You may not need an AI consultant if the job is small, one person does it, and that person is comfortable setting up tools. Many AI assistants can already draft emails or summarize documents with no setup at all.</p>
<p>A consultant also fits poorly if you only want a strategy report. In that case, a strategy consultant is the better choice, and you can decide on setup later. The comparison of <a href="/blog/ai-consultant-vs-automation-agency/">AI consultants and automation agencies</a> covers which option fits which need.</p>
<p>Bring in help when the job crosses several apps, touches customer or employee data, or needs to keep running after the person who set it up moves on. That is where most do-it-yourself pilots stall.</p>
<h2 id="where-does-elaichi-services-fit">Where does Elaichi Services fit?</h2>
<p>Elaichi Services is AI consulting, automation and integration delivered by Elaichi's forward deployed engineers, who work directly with your team instead of from a distance. They follow the same steps and hand over a setup that you own.</p>
<p>The engineers connect AI to the apps you already use, from a catalog of 700+ apps covering CRM, accounting, support, HR and project tools. If you use an app Elaichi does not support, they add it. The setup works with any AI assistant that supports MCP, so you keep the assistant you already pay for. Elaichi never sees your conversations with the AI.</p>
<p>The AI can only use the apps and actions you allow for each person. The actions it runs are recorded in your activity log. When you sign up, you pick EU, US or APAC for your company's Elaichi data, and for EU and US the data store stays in that region, and the <a href="/security/">security page</a> explains what is stored where. The setup, the instructions written for your AI, and everything it produces live in your own Elaichi account and apps. After handover, you remove the engineers' access.</p>
<p>To see example jobs by team before a call, browse the <a href="/use-cases/">use cases</a> or check your apps in the <a href="/connectors/">connector catalog</a>. The full plan is on the page about <a href="/services/">AI consulting and automation services</a>, and you can read why <a href="/blog/why-ai-pilots-fail/">AI pilots stall after the demo</a>.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Tell us which jobs eat your team's week. We will tell you what we would set up first, in the apps you already use.</p><a href="/services/" class="cta-button">Talk to our engineers</a></aside>
<h2>FAQ</h2><dl><dt><strong>What does an AI consultant do for a small business?</strong></dt><dd>A good AI consultant for a small business finds one repetitive job, such as copying orders between apps or answering the same customer questions, and sets up AI to do it inside the apps the business already uses. The consultant then tests it with the people who do that job and hands over a written guide, so the business can run it without the consultant.</dd><dt><strong>How do I choose the first task to automate with AI?</strong></dt><dd>Choose a task that repeats every week, lives in apps you already use, and has a result a person can check in a minute. Examples are drafting replies to common support tickets, flagging overdue invoices, or writing a short brief before a sales call. Avoid a first task where one mistake is costly or hard to spot.</dd><dt><strong>What questions should I ask an AI consultant before hiring one?</strong></dt><dd>Ask four things. Who owns what you build? Where is our data stored, and who can see it? Will it work with the AI assistant we already pay for? What happens after you hand over? Clear, written answers to all four are a good sign. Vague answers to any of them are a reason to keep looking.</dd><dt><strong>Who owns the AI setup that a consultant builds?</strong></dt><dd>The business should own it. The instructions, the app connections and everything the AI produces should live in accounts the business controls, not in the consultant's own tools. With Elaichi Services, the setup lives in the customer's own Elaichi account and apps, and the customer owns it.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai-adoption</category>
    </item>
    <item>
      <title>AI consultant vs AI automation agency: who to hire</title>
      <link>https://elaichi.ai/blog/ai-consultant-vs-automation-agency/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/ai-consultant-vs-automation-agency/</guid>
      <description>AI consultant vs AI automation agency: one gives you a plan, the other builds automations. Forward deployed engineers do both, in your apps.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Hire an AI consultant when you still need a strategy, an AI automation agency when you want a few one-off automations done fast, and automation software when your own technical staff have time to build and maintain it. Forward deployed engineers, such as Elaichi Services, fit when you want AI doing ongoing work inside the apps you already use without hiring an AI team. If all you need is a strategy report, a consultant is the better hire.</aside>
<h2 id="ai-consultant-vs-ai-automation-agency-what-is-the-difference">AI consultant vs AI automation agency: what is the difference?</h2>
<p>An AI consultant tells you what AI should do in your business, and an AI automation agency builds specific automations for you. That is the short answer to AI consultant vs AI automation agency, but most business owners actually face four choices, not two.</p>
<p>Picture the situation. Your team copies data from one app to another by hand. The same customer questions arrive every week. Someone rebuilds the same report every Monday. You want AI to take that work off their plate, and you are not sure who to call.</p>
<p>The four options are an AI consultant, an AI automation agency, automation software your own staff set up, and forward deployed engineers. A forward deployed engineer (FDE) is an engineer who works directly with your team and builds inside the apps you already use. Each option fits a different need, and each one has a weak spot.</p>
<h2 id="what-does-each-option-actually-give-you">What does each option actually give you?</h2>
<p>Each option leaves you with something different at the end: a plan, a set of automations, a tool, or a working setup. The table compares them on the questions a business owner usually asks first.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>AI consultant</th>
<th>AI automation agency</th>
<th>Automation software you build on</th>
<th>Forward deployed engineers</th>
</tr>
</thead>
<tbody>
<tr>
<td>What you end up with</td>
<td>A strategy and a written plan</td>
<td>Automations the agency built</td>
<td>A tool your staff configure</td>
<td>A working setup in your own apps</td>
</tr>
<tr>
<td>Who does the building</td>
<td>Someone else, later</td>
<td>The agency</td>
<td>Your own people</td>
<td>The engineers, with your team</td>
</tr>
<tr>
<td>Where the work lives</td>
<td>In a document</td>
<td>Sometimes in the agency's accounts</td>
<td>In your accounts</td>
<td>In your accounts and apps</td>
</tr>
<tr>
<td>Who keeps it running</td>
<td>Not part of the job</td>
<td>Often the agency, under a new agreement</td>
<td>Your own people</td>
<td>Your admins, after handover</td>
</tr>
<tr>
<td>Best fit</td>
<td>You need a strategy before deciding</td>
<td>A few clear, one-off tasks</td>
<td>Technical staff with spare time</td>
<td>Ongoing work across several apps, with no AI team</td>
</tr>
</tbody>
</table>
<p>Costs vary by scope for all four. Compare them on what you hold at the end, not only on the first quote.</p>
<h2 id="when-does-hiring-an-ai-consultant-make-sense">When does hiring an AI consultant make sense?</h2>
<p>An AI consultant is the right hire when you do not yet know what AI should do in your business. A good consultant talks to your leaders, looks across the company, and writes a plan: which jobs to start with, which risks to manage, and what to measure.</p>
<p>That plan has real value when the stakes are high or the leaders disagree. A board asking for an AI strategy, or a merger that changes every system, needs thinking before building.</p>
<p>The weak spot is what happens next. A plan does not answer a customer or close a ticket. Someone still has to build what it describes, connect it to your apps, and get your team to use it. Ask any consultant who will do that work, and when it starts.</p>
<h2 id="when-does-an-ai-automation-agency-make-sense">When does an AI automation agency make sense?</h2>
<p>An AI automation agency fits when you already know the tasks you want automated and want them done quickly. The agency builds each automation, tests it, and hands it back, usually as a short project.</p>
<p>This works well for a few clear, separate tasks. Think of a web form that should create a record in your CRM, or a weekly report that should build itself.</p>
<p>Watch three things. First, where each automation lives. Some agencies build on their own accounts and tools, so the work can leave with them. Second, what happens when one of your apps changes and an automation breaks. Third, who can see and change what each automation does. Ask for the work to sit in accounts your company owns, and for a list of every app login the agency used.</p>
<h2 id="when-should-you-buy-automation-software-and-build-it-yourself">When should you buy automation software and build it yourself?</h2>
<p>Building it yourself makes sense when you have technical people with real time to spare. Automation software gives your team the building blocks. Your staff connect the apps, design each step, and fix things when they break.</p>
<p>The benefit is control. Nothing depends on an outside firm, and your own people learn the tools.</p>
<p>The cost is time, and it does not stop after launch. Apps change, people leave, and someone has to own every automation. Building alone is also harder than it looks. MIT's NANDA initiative found that buying from specialized vendors and partners succeeded about 67% of the time, while internal builds succeeded about one-third as often (<a href="https://fortune.com/2025/08/18/mit-report-95-percent-generative-ai-pilots-at-companies-failing-cfo/">Fortune</a>).</p>
<h2 id="when-do-forward-deployed-engineers-make-sense">When do forward deployed engineers make sense?</h2>
<p>Forward deployed engineers fit when you want advice and a working result together, and you do not want to hire an AI team. They learn the work with your people, then build inside your real apps.</p>
<p>The role comes from software companies with complex products. Palantir describes its forward deployed software engineer as someone who "embeds directly with our customers" (<a href="https://blog.palantir.com/a-day-in-the-life-of-a-palantir-forward-deployed-software-engineer-45ef2de257b1">Palantir</a>). In a 2025 essay, the venture firm a16z said forward deployed teams exist "to operationalize the model into a real-world solution" (<a href="https://a16z.com/services-led-growth/">a16z</a>). In plain words, they turn AI into something your team uses every day.</p>
<p><a href="/services/">Elaichi Services</a> works this way. Elaichi's engineers start with a call with the people who do the work. They write a one-page plan, and you approve it before they start. Then they connect your apps, teach the AI how your team does each job, and decide who can use what. Elaichi connects to 700+ apps, and if you use one it does not support, the engineers add it. Your team tests the setup on real work, the engineers fix what is off, and your admins get a written guide.</p>
<p>The setup works with whichever AI assistant your company has chosen. If you switch assistants later, the work comes with you.</p>
<p>The weak spot is your time. Someone who does the work every day has to join the calls, and an admin has to connect your apps and approve the plan.</p>
<h2 id="why-do-so-many-ai-projects-stall-after-the-demo">Why do so many AI projects stall after the demo?</h2>
<p>Most AI projects stall because the AI never gets into the daily work, not because the model is weak. The numbers are blunt.</p>
<p>Gartner predicted that at least 30% of generative AI projects would be abandoned after proof of concept by the end of 2025 (<a href="https://www.gartner.com/en/newsroom/press-releases/2024-07-29-gartner-predicts-30-percent-of-generative-ai-projects-will-be-abandoned-after-proof-of-concept-by-end-of-2025">Gartner</a>). Gartner named poor data quality, weak risk controls, rising costs and unclear business value as the causes.</p>
<p>This matters for your choice. A plan alone does not close that gap, and neither does an automation nobody looks after. Whoever you hire, ask three questions. How will the AI reach the apps where the work happens? Why will your team trust it with company data? Who looks after it once the demo is over? The longer answer is in <a href="/blog/why-ai-pilots-fail/">why AI pilots stall before daily use</a>.</p>
<h2 id="what-should-you-check-before-you-hire-anyone">What should you check before you hire anyone?</h2>
<p>Four checks protect you whichever option you pick: ownership, access, records and handover. Ask about each one in the first meeting.</p>
<ul>
<li><strong>Ownership.</strong> What gets built should live in your accounts and your apps, not the provider's.</li>
<li><strong>Access.</strong> The AI should use only the apps and actions you allow for each person.</li>
<li><strong>Records.</strong> Every action the AI takes should land in an activity log, a record of who did what and when, that you can read later.</li>
<li><strong>Handover.</strong> When the project ends, you should be able to remove the provider's access and keep running.</li>
</ul>
<p>Elaichi Services answers each check the same way. The customer owns the setup, the instructions written for its AI, and everything the AI produces. The AI can only use the apps and actions you allow for each person. The actions it runs are recorded in the activity log, including the engineers' own work, and you remove their access at handover. Pick EU, US or APAC when you sign up. For EU and US, Elaichi's data store for your company stays in that region. The <a href="/security/">security page</a> has the details.</p>
<h2 id="how-do-you-decide-in-five-minutes">How do you decide in five minutes?</h2>
<p>Answer three questions in order, and stop at the first yes. Each yes points to one option.</p>
<ol>
<li>Do you still need to decide what AI should do across the company? Hire an AI consultant.</li>
<li>Do you have technical people with time to build and maintain automations? Buy automation software and build it yourself.</li>
<li>Do you want a few clear, one-off automations, built once? An AI automation agency fits.</li>
</ol>
<p>If all three answers are no, you want AI doing ongoing work in several apps, without an AI team of your own. That is the case forward deployed engineers are built for. A small business weighing this for the first time can also read <a href="/blog/ai-consultant-for-small-business/">what an AI consultant does for a small business</a>.</p>
<h2 id="when-is-elaichi-services-not-the-right-choice">When is Elaichi Services not the right choice?</h2>
<p>Elaichi Services is the wrong choice when you only want a strategy report. If the thing you need is a document for your board, hire a consultant. Elaichi's engineers set up working AI in your apps, so a plan on its own is not what they deliver.</p>
<p>Elaichi Services is also a poor fit when nobody can give the project time. The engineers need someone who does the work every day and an admin who can connect your apps. If neither person is free, wait until one is.</p>
<p>Two more cases point elsewhere. If your own technical team has time and wants to own every step, automation software may suit you better. If your work does not live in apps at all, AI in your apps will not help much.</p>
<p>When the work does live in apps, start with the jobs teams already hand to AI on the <a href="/use-cases/">use cases page</a>, check your apps in the <a href="/connectors/">connector catalog</a>, and see how a CRM fits in <a href="/blog/connect-ai-to-crm/">connecting AI to your CRM</a>.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Bring the work that eats your team's week. Elaichi's engineers learn how it is done, then set up AI that does the repetitive parts in your own apps.</p><a href="/services/" class="cta-button">Talk to our engineers</a></aside>
<h2>FAQ</h2><dl><dt><strong>What is the difference between an AI consultant and an AI automation agency?</strong></dt><dd>An AI consultant gives you advice and a written plan for where AI fits in your business, and usually stops there. An AI automation agency builds specific automations for you, often as a short project. Pick a consultant when you do not yet know what AI should do. Pick an agency when you already know the tasks and want them built quickly.</dd><dt><strong>What is a forward deployed engineer (FDE)?</strong></dt><dd>A forward deployed engineer is an engineer who works directly with a customer's team instead of from a distance. The engineer learns how the work is done, builds the solution inside the customer's own apps, tests it on real work, and stays until the team uses it. The role started at software companies with complex products and is now common in AI work.</dd><dt><strong>Should a small business build AI automations itself?</strong></dt><dd>Only if it has technical people with real time to spare. Automation software gives a team the building blocks, but the team has to connect the apps, design each step, and fix things when an app changes. A small business without that capacity usually gets further by bringing in outside help that builds in its own accounts and then hands over.</dd><dt><strong>Who should own the automations an outside firm builds?</strong></dt><dd>Your company should. Ask for every automation to live in accounts and apps your company controls, for a list of every app login the firm used, and for a written guide at handover. Then remove the firm's access when the project ends. Work that lives in a provider's own accounts can leave when the provider does.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai-adoption</category>
      <category>comparisons</category>
    </item>
    <item>
      <title>AI gateway vs MCP gateway: which one do you need?</title>
      <link>https://elaichi.ai/blog/ai-gateway-vs-mcp-gateway/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/ai-gateway-vs-mcp-gateway/</guid>
      <description>AI gateway vs MCP gateway: one governs your apps&apos; calls to models, the other which tools each person&apos;s AI client may call, and on whose account.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An AI gateway sits between your applications and model providers: it routes prompts, caches, rate-limits, tracks token spend and logs prompts. An MCP gateway sits between AI clients and the tools they call, and decides which apps each person's agent may reach, on whose account, with a record of each call that runs. Elaichi, a governed MCP control plane and hosted MCP gateway, is not a model router, so it runs beside an AI gateway rather than replacing one.</aside>
<p>Your platform team put an AI gateway in front of OpenAI and Anthropic last quarter. Every model call from the company's own apps now passes through it, with a budget per team and a log of each prompt. Then support asks for Claude with access to Zendesk, and finance asks for ChatGPT with access to Xero. The first thought is that the gateway already handles AI traffic. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>The AI gateway vs MCP gateway question comes down to which traffic each one sees. An AI gateway sees prompts on their way to a model. An MCP gateway sees tool calls on their way to an app. A company that builds on models and also rolls out AI clients to staff has both kinds of traffic, and each gateway answers a different question about it.</p>
<h2 id="ai-gateway-vs-mcp-gateway-what-is-the-difference">AI gateway vs MCP gateway: what is the difference?</h2>
<p>An AI gateway sits between your applications and the model providers they call. An MCP gateway sits between AI clients, such as Claude, ChatGPT and Cursor, and the tools those clients call in other apps. One governs the request for an answer. The other governs the action taken after it.</p>
<p>An AI gateway, also called an LLM gateway (LLM is short for large language model), answers questions about models. Which model got this prompt, what did it cost, and is the team over budget? An MCP gateway answers questions about people and tools. Which apps may this person's agent reach, whose account does a call run on, and what did each call touch? An agent here is an AI client acting for a person.</p>
<h2 id="what-does-an-ai-gateway-control">What does an AI gateway control?</h2>
<p>An AI gateway controls traffic from your code to model providers: routing, caching, rate limits, spend and logs. Its user is usually a developer whose application sends prompts.</p>
<p>Cloudflare's <a href="https://developers.cloudflare.com/ai-gateway/">AI Gateway overview</a> (checked October 2026) describes visibility and control over AI apps. It lists caching, rate limiting, request retries and model fallback, and its analytics count requests, tokens and cost. Cloudflare's <a href="https://developers.cloudflare.com/ai-gateway/observability/logging/">logging page</a> says each log can include the prompt, the response, token usage and cost.</p>
<p>Other products share the shape. The <a href="https://docs.litellm.ai/docs/simple_proxy">LiteLLM AI Gateway</a> is a self-hosted server that gives applications one OpenAI-compatible endpoint across model providers. Each user, team or project gets a virtual key with its own models, budgets and rate limits, and the gateway records the cost of each request. Portkey's <a href="https://portkey.ai/docs/product/ai-gateway">AI Gateway docs</a>, which carry the name Prisma AIRS AI Gateway as of October 2026, list budget limits on cost or tokens, rate limits on requests or tokens, caching, and fallbacks between providers. Both pages were checked October 2026.</p>
<p>Look at what all of them key on: an application, a key, a model and a token count. The caller is code you wrote, holding a key you issued.</p>
<h2 id="what-does-an-mcp-gateway-control">What does an MCP gateway control?</h2>
<p>An MCP gateway controls what an AI client may do in other apps once the model decides to act. It signs each person in, decides which tools that person may reach, attaches the right account's credential, and records the call.</p>
<p>The traffic is different in kind. Under the <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a>, a client runs a tool with a <code>tools/call</code> request, the MCP message that runs one tool, which carries the tool's name and its arguments. There is no model choice to route, no prompt to cache and no token bill to count. What there is to govern is a person, a tool and an account.</p>
<p>That gives an MCP gateway three questions to answer on every call:</p>
<ol>
<li>Which apps and tools may this person's agent reach?</li>
<li>Whose credentials does the call run on: the person's own account, or one shared with them?</li>
<li>What is the record afterwards: who called which tool, on which account, and did it work?</li>
</ol>
<p>Products answer those three in different ways, and <a href="/blog/what-is-an-mcp-gateway/">the four shapes of MCP gateway</a> sorts them by who runs the servers and who writes the connectors.</p>
<h2 id="what-does-each-gateway-see-control-and-record">What does each gateway see, control and record?</h2>
<p>Each gateway sees one kind of request, and its controls and records follow from that. The AI gateway column follows <a href="https://developers.cloudflare.com/ai-gateway/">Cloudflare's AI Gateway docs</a> and <a href="https://docs.litellm.ai/docs/simple_proxy">LiteLLM's docs</a>, checked October 2026.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>AI gateway (LLM gateway)</th>
<th>MCP gateway</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sits between</td>
<td>Your applications and model providers</td>
<td>AI clients and the apps they act in</td>
</tr>
<tr>
<td>What passes through</td>
<td>Prompts and model responses</td>
<td>Tool calls: a tool name and its arguments</td>
</tr>
<tr>
<td>Who the caller is</td>
<td>Your code, holding a key you issued</td>
<td>A named person, through their AI client</td>
</tr>
<tr>
<td>Main controls</td>
<td>Routing, fallback, caching, rate limits, budgets</td>
<td>Which apps and tools each person may reach, and on which account</td>
</tr>
<tr>
<td>What it records</td>
<td>Prompt, response, tokens, cost</td>
<td>Person, tool, account reached, outcome</td>
</tr>
<tr>
<td>The question it answers</td>
<td>Which model ran this, and what did it cost?</td>
<td>Who did what, in which app, on whose account?</td>
</tr>
</tbody>
</table>
<p>Read the last row as the test. If the question after an incident is about a model bill, it is an AI gateway question. If it is about a changed record in Salesforce, it is an MCP gateway question.</p>
<h2 id="why-can-an-ai-gateway-not-see-an-employees-tool-calls">Why can an AI gateway not see an employee's tool calls?</h2>
<p>Because the tool call does not pass through it. An AI gateway sees the model requests pointed at it. A tool call is a separate request, and it goes to an MCP server, not to a model provider.</p>
<p>Claude is a clear case. Anthropic's <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">custom connector guide</a> (checked October 2026) says Claude connects to a remote MCP server from Anthropic's cloud, on every Claude client, the desktop and mobile apps included. That request leaves Anthropic and lands at the MCP server. A model gateway in front of your own apps is not on that path.</p>
<p>The blind spot runs the other way too. An MCP gateway never sees the person's prompt, because a <code>tools/call</code> request does not carry it. Elaichi's MCP endpoint, for example, reads only a tool name and arguments from each call. Prompt logging and spend tracking belong on the model side. Each gateway is blind to the other's traffic, so one does not replace the other.</p>
<h2 id="can-one-product-be-both-an-ai-gateway-and-an-mcp-gateway">Can one product be both an AI gateway and an MCP gateway?</h2>
<p>Yes. Several products cover both kinds of traffic, but they still answer two separate sets of questions. Buying one product does not merge the jobs.</p>
<p>Kong's <a href="https://developer.konghq.com/ai-gateway/">AI Gateway documentation</a> (checked October 2026) describes one control plane for LLM, MCP and agent-to-agent traffic, with a single endpoint you can define for any of the three. The <a href="https://docs.litellm.ai/docs/simple_proxy">LiteLLM AI Gateway</a> also gives access to MCP tools, with the same keys and spend records as model calls. Portkey documents a separate <a href="https://portkey.ai/docs/product/mcp-gateway">MCP Gateway</a> that proxies between MCP clients and MCP servers, and handles authentication, access control and logging. Both of those pages were checked October 2026.</p>
<p>A combined product suits a platform team that already runs it for model traffic and wants one system to operate. Before you count it as your MCP gateway, put the three tool questions to it. Who writes and maintains the tools for each SaaS app? Does a call carry a named person, or a key? Which account at the app did the call actually reach? <a href="/blog/kong-cloudflare-mcp-gateway-vs-managed-connectors/">The Kong and Cloudflare comparison</a> works through those answers for two vendors. For gateways that put MCP on top of existing APIs, read <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">API gateways with MCP against MCP-native servers</a>.</p>
<h2 id="where-does-elaichi-fit-ai-gateway-or-mcp-gateway">Where does Elaichi fit: AI gateway or MCP gateway?</h2>
<p>Elaichi is an MCP gateway, not an AI gateway. It is a governed MCP control plane and hosted MCP gateway. Every call from an AI client passes through it and is checked against the caller's access, and every call that reaches execution is written to the audit log. It does not sit between your code and a model provider, and its endpoint receives tool calls, never the person's prompt.</p>
<p>Claude, ChatGPT, Cursor or any MCP client signs in to one endpoint, <code>https://api.elaichi.ai/mcp</code>. An endpoint is the one address every client points at, and Elaichi's is the same for every organization. Each person approves their own OAuth grant, the sign-in record that lets a client act as one named person. Every call then acts as that person. Behind the address sit 600+ connectors. Elaichi authors and runs most of them, governs vendors' own MCP servers for the rest, and lets a team bring its own remote MCP server under the same rules.</p>
<p>Elaichi's answers to the three tool questions are specific. Restrictions, rules set on a role or on one member, decide which connectors and which individual tools a target may reach. A call runs on one connection: the person's own account, or a shared one, which runs on its owner's account. Credentials sit in a separate credential service, and the AI client holds only an Elaichi token. Each call that reaches execution is written to the <a href="/blog/what-an-ai-audit-log-must-capture/">audit log</a>, the append-only record of calls. The entry names the person, the tool, the connector, the account the call actually reached, the MCP client and the outcome.</p>
<p>Changes in Elaichi land on a known schedule. A role or restriction change takes about two minutes to apply. Removal is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the person's AI clients fail on the next call.</p>
<h2 id="when-does-a-company-only-need-an-ai-gateway">When does a company only need an AI gateway?</h2>
<p>When AI at the company means your own software calling models, and no one's AI client acts in company apps. In that case an MCP gateway has no traffic to govern.</p>
<p>Picture a product team that ships a summary feature and a support chatbot inside its own app. The code calls OpenAI and Anthropic. The tools the model uses are functions in the same codebase, called by the team's own code. Staff do not connect Claude or ChatGPT to Salesforce or Zendesk. That team needs routing, fallback, budgets and prompt logs. An AI gateway covers all of it, and Elaichi would add nothing.</p>
<p>The answer changes when staff start connecting AI clients to company apps. A second client arrives, two people share one app account, or someone leaves while their AI client still holds access. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When an MCP gateway is premature</a> lists those signals in full.</p>
<h2 id="when-do-you-need-both-and-how-do-you-split-them">When do you need both, and how do you split them?</h2>
<p>You need both when you build on models and also give staff AI clients that act in company apps. Split by traffic, not by team: model calls go through the AI gateway, and tool calls go through the MCP gateway.</p>
<p>Here is a common split. Jake Morgan's platform team keeps an AI gateway in front of the models its product calls, with a budget per team. Emily Carter in IT rolls out Claude and ChatGPT to support and finance through an MCP gateway. Each person signs in with their own grant, and each app call is recorded. Neither gateway needs to know about the other.</p>
<p>Keep each control in one place. Spend caps live on the model side. Which apps a person may reach lives on the tool side. A rule set in both places drifts, and the copy that gets updated is the one somebody remembers. To see which apps the tool side already covers, browse the <a href="/connectors/">connector catalog</a> or the <a href="/use-cases/">team rollouts</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is the difference between an AI gateway and an MCP gateway?</strong></dt><dd>An AI gateway, also called an LLM gateway, sits between applications and model providers. It routes prompts to models, caches responses, rate-limits requests, tracks token spend and logs prompts. An MCP gateway sits between AI clients such as Claude, ChatGPT and Cursor and the apps they act in. It decides which tools each person may reach and which account a call runs on, and it records each tool call. A company that builds on models and also gives staff AI clients needs both.</dd><dt><strong>Can an AI gateway control which tools an AI agent can use?</strong></dt><dd>Only for traffic that passes through it. An AI gateway sees the model requests pointed at it. When an employee's Claude or ChatGPT calls a tool in Salesforce or Zendesk, that call goes to an MCP server, not to a model provider. Some products, such as Kong AI Gateway (https://developer.konghq.com/ai-gateway/), LiteLLM (https://docs.litellm.ai/docs/simple_proxy) and Portkey (https://portkey.ai/docs/product/mcp-gateway), also handle MCP traffic (vendor docs checked October 2026). Ask each one which person and which app account a tool call runs as.</dd><dt><strong>Is Elaichi an AI gateway or an MCP gateway?</strong></dt><dd>Elaichi is a governed MCP control plane and hosted MCP gateway, not an AI gateway. Claude, ChatGPT, Cursor or any MCP client signs in to one address, https://api.elaichi.ai/mcp, and each call acts as the person who approved the grant. Elaichi serves 600+ connectors, checks each call against the person's access, and writes each executed call to an audit log that names the account it reached. It receives tool calls, never the person's prompt.</dd><dt><strong>Do we need an MCP gateway if we already run an AI gateway?</strong></dt><dd>Only if staff connect AI clients to company apps. If AI at your company is your own code calling models, an AI gateway covers routing, budgets and logs, and an MCP gateway has nothing to govern. Once people use Claude, ChatGPT or Cursor to act in apps such as Salesforce or Zendesk, the questions become which tools each person may reach and on whose account. A model gateway does not answer those.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>comparisons</category>
    </item>
    <item>
      <title>Composio vs Zapier MCP for company use</title>
      <link>https://elaichi.ai/blog/composio-vs-zapier-mcp/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/composio-vs-zapier-mcp/</guid>
      <description>Composio vs Zapier MCP: Composio bills per tool call, Zapier MCP uses two tasks per call, and Elaichi bills per seat at one shared address.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Composio vs Zapier MCP is a choice between an agent tool platform billed per tool call, with a gateway endpoint plus one per team, and an extension of a Zapier account, where each successful call uses two tasks from the plan. Both suit a company that already builds on them. Elaichi is a third shape for a company-wide rollout: one address, https://api.elaichi.ai/mcp, the same for every organization, that Claude, ChatGPT, Cursor or any MCP client signs in to, with one grant per person per client, restrictions per role or per member, one audit log, and a price per seat.</aside>
<h2 id="composio-vs-zapier-mcp-what-is-the-real-difference">Composio vs Zapier MCP: what is the real difference?</h2>
<p>Composio vs Zapier MCP comes down to what each product extends. Composio extends an agent platform with a gateway that companies can put in front of their staff. Zapier MCP extends a person's Zapier account into their AI client. The two differ on the billing unit, on who holds the app credentials, and on what one person's access looks like.</p>
<p>An IT lead is asked to let sales, support and finance use Claude and ChatGPT with the company's apps. Two names come up first. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Both Composio and Zapier MCP speak it, so the question is how each one fits a company rollout, and where a different design fits.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Composio</th>
<th>Zapier MCP</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Built for</td>
<td>Developers building agents, and people connecting Claude or ChatGPT to their apps (<a href="https://composio.dev/">composio.dev</a>)</td>
<td>People who already automate in Zapier (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">help article</a>)</td>
<td>A company giving its own staff governed access</td>
</tr>
<tr>
<td>Apps</td>
<td>"1,500+ apps available" (<a href="https://composio.dev/mcp-gateway">MCP Gateway</a>)</td>
<td>9,000+ apps and 40,000+ actions (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">help article</a>)</td>
<td>600+ connectors, plus a team's own remote MCP server</td>
</tr>
<tr>
<td>Address</td>
<td>A gateway endpoint plus one per team (<a href="https://composio.dev/mcp-gateway">MCP Gateway</a>)</td>
<td>One shared endpoint, usually one server per person per client (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">connections</a>)</td>
<td>One address, <code>https://api.elaichi.ai/mcp</code>, the same for every organization; one grant per person per client</td>
</tr>
<tr>
<td>App credentials</td>
<td>AES-256 encrypted, decrypted in Composio's execution layer (<a href="https://composio.dev/enterprise">Enterprise</a>)</td>
<td>Zapier holds them (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">connections</a>)</td>
<td>A separate credential service holds them, encrypted</td>
</tr>
<tr>
<td>Access rules</td>
<td>Per user and per role, down to one action (<a href="https://composio.dev/enterprise">Enterprise</a>)</td>
<td>App and action restrictions, account-wide (<a href="https://docs.zapier.com/mcp/manage/security">security</a>)</td>
<td>Restrictions per role or per member, down to one tool</td>
</tr>
<tr>
<td>Record of calls</td>
<td>User, team, tool, action and outcome, denied calls included (<a href="https://composio.dev/enterprise">Enterprise</a>)</td>
<td>History tab per user, plus the account audit log (<a href="https://docs.zapier.com/mcp/manage/security">security</a>)</td>
<td>One entry per call that reaches execution, succeeded or failed; a call refused earlier writes no row</td>
</tr>
<tr>
<td>Billing unit</td>
<td>Tool calls; Pro is $29 a month (<a href="https://composio.dev/pricing">pricing</a>)</td>
<td>Two tasks per successful call, from the plan (<a href="https://docs.zapier.com/mcp/overview/usage">usage</a>)</td>
<td>Seats; Gold lists at $15 per user per month in USD (<a href="/pricing/">pricing</a>)</td>
</tr>
</tbody>
</table>
<p>The Composio column follows Composio's own pages and the Zapier MCP column follows Zapier's own docs, all checked October 2026. Each cell links the page it comes from, such as <a href="https://composio.dev/enterprise">composio.dev/enterprise</a> and <a href="https://docs.zapier.com/mcp/manage/security">Zapier MCP security</a>.</p>
<h2 id="what-are-composio-and-zapier-mcp-each-built-for">What are Composio and Zapier MCP each built for?</h2>
<p>Composio is built first for people who build agents, and Zapier MCP is built for people who already work in Zapier. Composio's homepage speaks to two audiences. One wants Claude or ChatGPT to act in their apps; the other builds agents on the Composio Platform (<a href="https://composio.dev/">composio.dev</a>, checked October 2026).</p>
<p>Composio Connect is a shared MCP URL, <code>connect.composio.dev/mcp</code>, that reaches its apps through 7 meta-tools. When an agent first needs an app, the person approves an OAuth link in the browser (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026). The company-facing piece is the MCP Gateway. The gateway has an endpoint of its own, and each team gets one scoped to the tools it may use. SSO (one company login for every app) verifies the user before any tool resolves (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked October 2026).</p>
<p>Zapier's help article describes Zapier MCP as the link between a person's MCP client and their Zapier account. Its tools run on the same app connections and actions that the person's Zaps use (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">What is Zapier MCP</a>, checked October 2026). Zapier's own comparison page frames the split the same way. It calls Zapier a "no-code AI orchestration platform" and Composio a "developer-first integration and authentication layer" (<a href="https://zapier.com/compare/zapier-vs-composio">Zapier vs. Composio</a>, checked October 2026).</p>
<h2 id="how-do-composio-and-zapier-mcp-charge-for-usage">How do Composio and Zapier MCP charge for usage?</h2>
<p>Composio charges for tool calls, and Zapier MCP spends tasks from a Zapier plan. Composio's pricing page counts each tool execution once and leaves meta tools such as tool search free. Trigger events, premium tools and usage-based add-ons are billed as well (<a href="https://composio.dev/pricing">Composio pricing</a>, checked October 2026).</p>
<p>The same Composio page lists three plans (checked October 2026):</p>
<ul>
<li><strong>Hobby:</strong> $0, with 100,000 tool calls, 50,000 triggers and 3 team members a month (<a href="https://composio.dev/pricing">pricing</a>).</li>
<li><strong>Pro:</strong> $29 a month, with a $29 usage credit that expires at the end of each billing month, and unlimited team members (<a href="https://composio.dev/pricing">pricing</a>).</li>
<li><strong>Enterprise:</strong> custom terms. SSO, SCIM and customer-managed keys sit here, not on Hobby or Pro (<a href="https://composio.dev/pricing">pricing</a>).</li>
</ul>
<p>Zapier MCP has no separate MCP bill. It runs on the person's existing Zapier plan, and each successful tool call uses two tasks at a fixed rate. Failed calls use none (<a href="https://docs.zapier.com/mcp/overview/usage">Zapier MCP usage and billing</a>, checked October 2026). A call that finds a HubSpot contact and a second call that emails them through Gmail use four tasks between them.</p>
<p>Both bills move with how much the AI does. Elaichi's bill moves with headcount instead, and the trade-offs of each meter are set out in <a href="/blog/mcp-gateway-pricing/">the per-seat and per-call pricing breakdown</a>.</p>
<h2 id="who-keeps-the-app-credentials-in-composio-and-zapier-mcp">Who keeps the app credentials in Composio and Zapier MCP?</h2>
<p>In both products the vendor keeps the app credentials, so the AI client never holds a third-party API key. Zapier says it holds the app credentials for Zapier MCP. On the OAuth path, the MCP client stores and refreshes its own OAuth token (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how Zapier MCP connections work</a>, checked October 2026).</p>
<p>The case to watch in Zapier MCP is the connection token. A client off Zapier's supported list, or a person's own code, connects with one instead. Zapier describes it as long-lived and bound to one server, and anyone holding it can run that server's tools. Zapier's docs say to treat it like a password (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">Zapier connections page</a>, checked October 2026).</p>
<p>Composio's Enterprise page says credentials are stored AES-256 encrypted and decrypted inside Composio's execution layer. Developers do not handle raw credentials, and the model does not see them (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026). A deeper read is in <a href="/blog/is-composio-secure-enough-for-enterprise-use/">the Composio security review</a>.</p>
<p>Elaichi keeps app credentials in a separate credential service, encrypted at rest with AES-256-GCM. It fetches them into memory only for the call that needs them. The MCP address carries no credential, and the AI client holds only an Elaichi token, sent in a header.</p>
<h2 id="how-does-each-person-get-access-in-composio-and-zapier-mcp">How does each person get access in Composio and Zapier MCP?</h2>
<p>Zapier MCP gives each person their own servers, while Composio's gateway gives each team its own endpoint alongside the gateway's own. In Zapier MCP every client uses the same endpoint. Each person owns their own servers on the Zapier account, usually one per named MCP client (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">Zapier connections</a>, checked October 2026).</p>
<p>An organization rollout lets an admin make Zapier available in the MCP client. Each member still signs in to Zapier and runs tool calls as themselves (<a href="https://docs.zapier.com/mcp/get-started/rollout/overview">Zapier MCP rollout</a>, checked October 2026). Sharing a server with teammates needs a Team or Enterprise plan. It lets them review or manage its tools, not run them as the owner (<a href="https://docs.zapier.com/mcp/manage/server-access">Zapier server access</a>, checked October 2026).</p>
<p>What happens to a member's servers when they leave is not documented on Zapier's MCP security, server access or usage pages (checked October 2026). Put that question to Zapier before a rollout.</p>
<p>Composio's MCP Gateway page lists SAML or OIDC single sign-on and SCIM 2.0 (automatic user provisioning from a directory). SCIM maps directory groups to teams and revokes access at offboarding (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked October 2026). Composio's pricing page lists shared connection tool calls as a metered add-on. In those, other users reuse one connected account (<a href="https://composio.dev/pricing">Composio pricing</a>, checked October 2026).</p>
<h2 id="what-can-an-admin-restrict-and-review-in-each-one">What can an admin restrict and review in each one?</h2>
<p>Composio documents permissions per user and per role, and Zapier MCP inherits Zapier's account-wide restrictions. Composio's Enterprise page says admins set permissions down to a single action. The rules are checked in the request path, before the model is involved. Each call is logged with the user, team, tool, action and outcome, including calls that policy denied (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026).</p>
<p>The Composio gateway adds two details. Members can ask for tools they cannot reach, and admins approve or deny centrally. Tool-call payloads are not stored, and audit records hold metadata, kept for 7 days to 1 year (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked October 2026). Elaichi's audit log has one limit to compare: it writes a row for each call that reaches execution, succeeded or failed, and a call refused before that point, for example for a tool a restriction withholds, writes no row.</p>
<p>Zapier MCP enforces app and action restrictions set at the Zapier account level. Those restrictions cannot be set for Zapier MCP alone; they apply across every Zapier feature. With Zapier Workspaces, admins can allow or restrict Zapier MCP for specific users and set task quotas per workspace. The History tab shows tool calls per user, and superadmins can review any user's. MCP events also reach the account audit log (<a href="https://docs.zapier.com/mcp/manage/security">Zapier MCP security</a>, checked October 2026).</p>
<h2 id="what-is-the-third-option-for-a-company-wide-rollout">What is the third option for a company-wide rollout?</h2>
<p>The third option is a governed MCP control plane: one hosted MCP gateway that every employee's AI client signs in to. Elaichi is built that way. Every person connects Claude, ChatGPT, Cursor or any MCP client to one address, <code>https://api.elaichi.ai/mcp</code>. They sign in over OAuth, the standard flow that hands a client a token instead of a password. Each person approves their own grant, the record that ties one client to one person. Every call then acts as that person.</p>
<p>Elaichi serves 600+ connectors. It authors and runs most of them itself. The rest are native MCP connectors, where the app's vendor builds and runs its own MCP server and Elaichi handles sign-in, access and audit. A team on Gold can also add its own remote MCP server under the same rules. In Elaichi, connected tools are never listed one by one, however few there are. The model finds a tool with <code>search_tools</code> and runs it with <code>execute_tool</code>.</p>
<p>Admins restrict whole connectors or single tools for a role or for one member, and a block always beats an allow. A role or restriction change takes effect within about two minutes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so a removed or suspended member's clients stop on their next call. A member who needs a restricted tool can file an access request from the client, and an admin decides it in the console.</p>
<p>Every call that reaches execution writes one audit row, succeeded or failed. A call refused earlier, for example for a tool a restriction withholds, writes no row. Everyone can see their own activity in the audit log. People with the audit permission see the whole organization, and the read-only Auditor role does not take a billable seat. Gold lists at $15 per user per month in USD, or $10 billed annually. The <a href="/pricing/">pricing page</a> lists SAML or OIDC SSO and SCIM on Gold. Gold starts with a 14-day trial and needs no card to begin.</p>
<h2 id="when-is-composio-or-zapier-mcp-the-right-answer">When is Composio or Zapier MCP the right answer?</h2>
<p>Composio fits when seats do not map to your employees, for example when the tool users are your own customers. Zapier MCP fits when your team already runs on Zapier. Composio's Enterprise page says it maps an agent and its end user to a connected account. That account may belong to an employee or to the customer's own customer (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026). That fits a product team putting tool access inside something it sells.</p>
<p>Choose Composio when:</p>
<ul>
<li>You are building an agent into your own product, and seats do not map to employees.</li>
<li>You need an app that Composio lists and the Elaichi catalog lacks.</li>
<li>You want a separate endpoint per team, or self-hosting, which Composio's Enterprise page offers (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026).</li>
</ul>
<p>Choose Zapier MCP when:</p>
<ul>
<li>Your team already builds Zaps, and the apps it needs are already connected in Zapier.</li>
<li>Each person signs in to Zapier themselves, and Zapier's restrictions and History answer your reviewer.</li>
<li>Your task allowance absorbs two tasks per successful call at the volume you expect.</li>
</ul>
<p>Elaichi assumes a workforce. Roles, seats and SCIM describe employees and contractors, not your end users. It has no per-team endpoint. Every new grant needs a person to approve a consent screen, so it does not suit an agent that runs unattended in a build pipeline. Three people with one read-only app may need nothing at all, as <a href="/blog/when-you-dont-need-an-mcp-gateway/">the post on skipping a gateway for now</a> argues.</p>
<h2 id="which-one-should-a-company-pick">Which one should a company pick?</h2>
<p>Pick by who uses the tools and who has to answer for them. Three questions sort most cases in one meeting:</p>
<ol>
<li><strong>Who holds the sessions?</strong> Your customers point to Composio. Your employees point to Composio's gateway, Zapier MCP or Elaichi.</li>
<li><strong>Where are the apps connected now?</strong> If they are already connected in Zapier, Zapier MCP reuses that work. If not, check your five most-used apps against the <a href="/connectors/">connector catalog</a> and both vendors' lists.</li>
<li><strong>Who answers the security reviewer?</strong> One admin may have to say what a role can reach, cut off a leaver and show each call that ran. Test exactly that in a pilot on each product.</li>
</ol>
<p>Each pairing has a fuller head-to-head. The connector authorship and endpoint questions are in <a href="/blog/elaichi-vs-composio/">Elaichi compared with Composio</a>. The per-member server model is in <a href="/blog/zapier-mcp-alternative/">the Zapier MCP alternative guide</a>. For the category itself, start with <a href="/blog/what-is-an-mcp-gateway/">what an MCP gateway does</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is the difference between Composio and Zapier MCP?</strong></dt><dd>Composio is an agent tool platform: its MCP Gateway gives the company a gateway endpoint and each team its own, admins set permissions per user and per role, and pricing meters tool calls (https://composio.dev/mcp-gateway and https://composio.dev/pricing, checked October 2026). Zapier MCP connects a person's MCP client to their Zapier account, runs on the app connections their Zaps already use, and each successful tool call uses two tasks from the Zapier plan (https://docs.zapier.com/mcp/overview/usage, checked October 2026). Composio leans toward teams that build agents; Zapier MCP leans toward teams that already automate in Zapier.</dd><dt><strong>How does Composio pricing compare with Zapier MCP pricing?</strong></dt><dd>Composio meters tool calls. Its Hobby plan is $0 with 100,000 tool calls and 3 team members a month, Pro is $29 a month with a $29 usage credit, and Enterprise is custom (https://composio.dev/pricing, checked October 2026). Zapier MCP has no separate MCP bill: each successful tool call uses two tasks from the Zapier plan's allowance, and failed calls use none (https://docs.zapier.com/mcp/overview/usage, checked October 2026). Elaichi prices by seat instead: Gold lists at $15 per user per month in USD, whatever the call volume.</dd><dt><strong>Does Zapier MCP give each employee their own access?</strong></dt><dd>Yes. In Zapier MCP the per-person unit is the MCP server: each member creates their own servers on the Zapier account, usually one per named MCP client, while every client uses the same endpoint. An organization rollout changes what members can reach, but each member still signs in and runs tool calls as themselves (https://docs.zapier.com/mcp/overview/how-connections-work and https://docs.zapier.com/mcp/get-started/rollout/overview, checked October 2026).</dd><dt><strong>Where does Elaichi fit next to Composio and Zapier MCP?</strong></dt><dd>Elaichi is a governed MCP control plane and hosted MCP gateway for a company's own staff. Every person connects Claude, ChatGPT, Cursor or any MCP client to one address, https://api.elaichi.ai/mcp, and approves their own OAuth grant. Admins restrict connectors and single tools per role or per member, tool calls are recorded in one audit log, and Gold lists at $15 per user per month in USD with SSO and SCIM included.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>comparisons</category>
    </item>
    <item>
      <title>How to connect AI to CRM without engineers</title>
      <link>https://elaichi.ai/blog/connect-ai-to-crm/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-ai-to-crm/</guid>
      <description>To connect AI to CRM data safely, give each person&apos;s assistant only their own CRM access, start with reads, and keep a log of what it does.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Connect your AI assistant to your CRM so that each person's assistant works with that person's own CRM access, starts with reading, and writes only where you allow it. Elaichi connects the assistant a company already uses to its CRM, accounting app and support desk through one address, with restrictions on single actions, an activity log and a choice of region for its data. If the work never leaves the CRM, the CRM's own built-in AI may be all you need.</aside>
<p>A sales lead at a 40-person company asks her AI assistant which deals to chase this week. It gives a careful answer about pipeline habits in general. It cannot see her pipeline. The deals live in the CRM, the unpaid invoices live in the accounting app, and the open complaints live in the support desk. Each one is a tab the assistant cannot open.</p>
<p>This guide is for the owner or sales lead who wants to connect AI to CRM data without hiring engineers. It covers what changes once the assistant can see the CRM, the four ways to set it up, and what to get right before it writes anything. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The project's own site calls it an <a href="https://modelcontextprotocol.io/docs/getting-started/intro">open-source standard for connecting AI applications to external systems</a>.</p>
<h2 id="what-can-your-ai-assistant-do-once-it-can-see-your-crm">What can your AI assistant do once it can see your CRM?</h2>
<p>It can take on some of the non-selling work that fills a rep's week. Salesforce's sixth State of Sales survey found reps spend 70% of their time on non-selling tasks (<a href="https://www.salesforce.com/news/stories/sales-ai-statistics-2024/">Salesforce</a>).</p>
<p>Four jobs usually come first:</p>
<ul>
<li><strong>Prioritize leads.</strong> Ask which new leads look like your best customers. The assistant reads the records and returns a short, ranked list.</li>
<li><strong>Brief before a call.</strong> Ask for a one-page brief on the account. With the accounting app connected, the brief shows the overdue invoice. With the support desk connected, it shows the open ticket.</li>
<li><strong>Find quiet deals.</strong> Ask which open deals have had no activity for three weeks. The assistant lists them and drafts a follow-up for each owner.</li>
<li><strong>Update records.</strong> After a call, ask it to log the notes, move the stage and set the next task. This is the first job that writes, so it needs the most care.</li>
</ul>
<p>Clean records matter here. In the same survey, only 35% of sales professionals said they completely trust the accuracy of their company's data (<a href="https://www.salesforce.com/news/stories/sales-ai-statistics-2024/">Salesforce</a>).</p>
<p>The apps around the CRM matter as much as the CRM. A brief that misses an unpaid invoice can embarrass the rep on the call. Elaichi connects one assistant to <a href="/connectors/hubspot/">HubSpot</a>, <a href="/connectors/salesforce/">Salesforce</a>, <a href="/connectors/pipedrive/">Pipedrive</a>, <a href="/connectors/quickbooks/">QuickBooks</a>, <a href="/connectors/xero/">Xero</a>, <a href="/connectors/zendesk/">Zendesk</a> and 700+ apps in all through one connection.</p>
<h2 id="what-are-the-ways-to-connect-ai-to-a-crm">What are the ways to connect AI to a CRM?</h2>
<p>There are four, and each suits a different company. The right one depends on how many apps the work touches and how many people will use it.</p>
<table>
<thead>
<tr>
<th>Option</th>
<th>What it is</th>
<th>Good when</th>
<th>Watch for</th>
</tr>
</thead>
<tbody>
<tr>
<td>The CRM's own AI</td>
<td>AI features built into the CRM</td>
<td>The work stays inside the CRM</td>
<td>It is built for that one CRM</td>
</tr>
<tr>
<td>Per-person add-ons</td>
<td>Each person connects the CRM vendor's own MCP server to their assistant</td>
<td>One or two people, one app</td>
<td>Each person sets it up alone, with no shared rules across apps</td>
</tr>
<tr>
<td>A shared connection layer</td>
<td>One connection, such as Elaichi, between the assistant and every app</td>
<td>Several people, several apps</td>
<td>Someone has to decide the access rules</td>
</tr>
<tr>
<td>Engineers set it up for you</td>
<td>A team that connects the apps and builds the jobs</td>
<td>Nobody in-house has the time</td>
<td>Make sure you own what they build</td>
</tr>
</tbody>
</table>
<p>Per-person add-ons are now common. HubSpot's remote MCP server is generally available to all HubSpot accounts, and it can read CRM records and activity history and create or update contacts, companies, deals and tickets (<a href="https://developers.hubspot.com/changelog/remote-hubspot-mcp-server-is-now-generally-available">HubSpot developer changelog</a>, checked October 2026). HubSpot says all actions respect the user's existing HubSpot permissions. For Salesforce, <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the guide to each rep's own Salesforce access</a> covers its hosted option.</p>
<p>A shared layer works differently. Elaichi gives every company the same address, <a href="https://api.elaichi.ai/mcp">https://api.elaichi.ai/mcp</a>. Each person adds it to their assistant once and signs in as themselves. Apps are connected once in Elaichi, and the access rules and the activity log cover all of them. Under the default choice at sign-in, an app connected later needs no new step in the assistant.</p>
<h2 id="when-is-the-crms-own-built-in-ai-enough">When is the CRM's own built-in AI enough?</h2>
<p>It is enough when the work starts and ends inside the CRM. If your team wants a summary of a deal's emails or a draft follow-up from one record, the AI built into your CRM may be all you need. You skip a second vendor, a second login and a second set of rules.</p>
<p>The same goes for one person and one app. If a founder wants HubSpot in their assistant and nothing else, HubSpot's own MCP server covers it. Elaichi is not needed there.</p>
<p>The case changes when a job crosses apps, or when many people use AI on the same data. A call brief that needs the CRM, the invoices and the tickets reaches past any one vendor's AI. So does one list of who may do what across all three apps, and one log of what the assistant did. That is the point where a shared layer earns its place.</p>
<h2 id="should-each-persons-ai-see-only-what-that-person-can-see">Should each person's AI see only what that person can see?</h2>
<p>Yes, and this is the rule to get right first. A shared admin login gives every person's assistant the admin's reach. A new rep could then read every deal, including the ones the CRM hides from them.</p>
<p>In Elaichi, every call runs as the person who signed in, in the organization they picked. Where the CRM should see the person, each person connects the CRM under their own login. The CRM then applies the access its admin already set, such as territories, record owners and private deals. Elaichi decides who may use a connection, and the CRM decides which records that login can read.</p>
<p>Some connections should be shared, such as a reporting account. Share each one only with the people who need it, because a shared connection runs on its owner's login to the app.</p>
<p>People leave, too. When someone is removed from Elaichi, their assistant's next call through Elaichi is refused. Their CRM user is a separate step inside the CRM.</p>
<h2 id="should-the-ai-only-read-your-crm-or-also-write-to-it">Should the AI only read your CRM, or also write to it?</h2>
<p>Start with reads, then add writes one job at a time. Most of the value is in reading: ranking leads, writing briefs and finding quiet deals all read. Most of the risk is in writing, because a wrong stage or a merged contact changes what everyone else sees.</p>
<p>In Elaichi, the sign-in screen has a box called "Run your connected tools". It covers reading and changing data in connected apps, so on its own it does not make the assistant read-only. To hold an assistant to reads, pick toolboxes of read tools at sign-in, or block the write tools with a restriction. A toolbox is a named set of tools. A restriction is a rule that allows or blocks apps and single tools for a role or for one person.</p>
<p>Add writes in small steps. Logging a call note or creating a task is low risk. Changing a deal's owner or amount is not. Let the team use reads for two weeks, check the activity log, and then turn on the first write job.</p>
<h2 id="which-crm-actions-should-you-restrict">Which CRM actions should you restrict?</h2>
<p>Restrict anything that deletes, merges, works in bulk or changes who can see what. One bad call there reaches many records, and none of the four common jobs needs those actions.</p>
<p>A short list to start from:</p>
<ul>
<li>Deletes of contacts, companies or deals.</li>
<li>Merges of duplicate records.</li>
<li>Bulk updates, and catch-all tools that can change any kind of record.</li>
<li>Changes to users, roles and permissions inside the CRM.</li>
</ul>
<p>In Elaichi, a restriction names whole apps or single tools, for a role or for one person. A block always beats an allow. A restricted tool cannot be run. If the assistant searches for it, it sees only the name, flagged as restricted. A delete tool also needs a separate box at sign-in, "Delete data and remove access", which is never ticked by default.</p>
<p>A new rule takes about two minutes to reach everyone. Set the rules before people start, then test them as an ordinary member.</p>
<h2 id="what-should-the-activity-log-and-data-storage-look-like">What should the activity log and data storage look like?</h2>
<p>What the assistant does should land in a log you can read, and you should know where your data is kept. Without a log, nobody can say what the assistant changed last Tuesday, or for whom.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the person, the app, the account the call reached and the assistant that made it. Every member can read their own entries. An admin, or a read-only Auditor, can read the whole organization's log.</p>
<p>For storage, Elaichi has three regions, EU, US and APAC, chosen when the organization is created and fixed after that. For EU or US, the organization's data store stays in that region. APAC uses best-effort placement and is not a residency guarantee. The activity log for every region is kept in the EU, as the <a href="/privacy/">privacy policy</a> says. Elaichi does not see your conversations with the assistant; it sees only the action the assistant asks to run. The <a href="/security/">security overview</a> has the rest.</p>
<h2 id="how-do-you-connect-ai-to-crm-without-an-engineering-team">How do you connect AI to CRM without an engineering team?</h2>
<p>Pick one job, connect the apps it needs, set the rules, then test with one person. An admin and one person who does the work every day can do it together.</p>
<ol>
<li>Pick one job, such as the brief before a call, and list the apps it reads.</li>
<li>Connect the CRM and those apps in Elaichi. Each rep connects the CRM under their own login.</li>
<li>Write restrictions on the sales role: reads first, with deletes, merges and bulk tools blocked.</li>
<li>Add <a href="https://api.elaichi.ai/mcp">https://api.elaichi.ai/mcp</a> to your assistant's connector settings. Each person signs in once.</li>
<li>Run the job as one rep, then read the activity log and check each entry.</li>
<li>After two weeks, add the next job or the first write.</li>
</ol>
<p>The <a href="/blog/connect-company-apps-to-claude-and-chatgpt/">technical walkthrough for IT</a> has the details of step 4. Many AI projects stall between the demo and daily use, and <a href="/blog/why-ai-pilots-fail/">why AI pilots stall</a> looks at that gap.</p>
<p>If nobody has the time, Elaichi's <a href="/services/">forward deployed engineers</a> do this with you. They learn how your team works, write a plan you approve, set it up in your own apps, test it on real work and hand over a written guide. You own everything they build. The services process is described step by step, and the <a href="/use-cases/">use cases page</a> shows the same pattern for other teams.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Elaichi's forward deployed engineers connect your AI assistant to your CRM and the apps around it, set the access rules with you, and stay until your team uses it every day.</p><a href="/services/" class="cta-button">Talk to our engineers</a></aside>
<h2>FAQ</h2><dl><dt><strong>Can I connect AI to my CRM without a developer?</strong></dt><dd>Yes. With Elaichi, an admin connects the CRM once, sets which actions each role may take, and adds one address to the company's AI assistant. Each person then signs in once. If nobody has the time, Elaichi's forward deployed engineers do the setup with the team and hand it over.</dd><dt><strong>Is it safe to let an AI assistant update CRM records?</strong></dt><dd>It is safe when writes are added on purpose. Start the assistant on reading only, block deletes, merges and bulk updates, and turn on one write job at a time, such as logging call notes. Keep an activity log so that any change can be traced to a person and an app.</dd><dt><strong>Will the AI see every record in our CRM?</strong></dt><dd>Not if each person connects the CRM under their own login. The assistant then reads only what that person's CRM account can read, under the territories and record owners the CRM admin already set. A shared admin login would give every person's assistant the admin's reach.</dd><dt><strong>Do I need Elaichi if my CRM already has built-in AI?</strong></dt><dd>Not always. If the work starts and ends inside the CRM, the CRM's own AI may be enough. Elaichi is for work that crosses apps, such as a call brief that needs the CRM, the accounting app and the support desk, and for one set of access rules and one log across all of them.</dd><dt><strong>Which CRMs can an AI assistant connect to through Elaichi?</strong></dt><dd>Elaichi's catalog includes HubSpot, Salesforce and Pipedrive, along with accounting apps such as QuickBooks and Xero and support desks such as Zendesk. Elaichi connects to 700+ apps in all, through one address that any AI assistant supporting MCP can use.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai-adoption</category>
    </item>
    <item>
      <title>Enterprise MCP: a buyer&apos;s guide for IT teams</title>
      <link>https://elaichi.ai/blog/enterprise-mcp/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/enterprise-mcp/</guid>
      <description>Enterprise MCP for buyers: what changes when MCP goes from one laptop to a whole company, and what to ask a vendor before you sign.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Enterprise MCP is MCP run for a whole company: each person signs in as themselves, their role decides which tools they reach, nobody handles app credentials, and each call that runs leaves an audit record. Elaichi, a governed MCP control plane and hosted MCP gateway, puts all of that behind one endpoint that Claude, ChatGPT and Cursor sign into. A company with one team, one app and no AI writes to a system of record may not need one yet.</aside>
<p>An engineer, Emily Carter, adds an MCP server to Claude Desktop on a Friday. It takes a few lines in a config file and a personal API token. By Monday it saves her an hour a day. Then sales asks for the same thing, and so do finance and support. Enterprise MCP is MCP run for a whole company instead of one laptop: each person signs in as themselves, a role decides which tools they reach, and each call that runs is recorded. It is the name for what has to change before a whole company can do what Emily did on her own laptop.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. On one laptop, the person, the credential and the record are the same machine. Across a company they come apart, and each needs an owner. This guide is the buyer's view. It walks an enterprise AI platform buyer through seven decisions, shows where a governed control plane fits, and covers the case where a company does not need one yet. The rule model behind those decisions, with restrictions, credentials, the record and offboarding in detail, is in <a href="/blog/mcp-governance/">MCP governance</a>.</p>
<h2 id="what-changes-when-mcp-moves-from-a-laptop-to-a-company">What changes when MCP moves from a laptop to a company?</h2>
<p>Identity, the address, the rules, the credentials and the record all move from the person to the organization. On a laptop, the <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization specification</a> makes sign-in optional. It tells servers on the local stdio transport to read credentials from the environment instead.</p>
<p>A local server lives in a file on each machine. Claude Desktop keeps its list in <code>claude_desktop_config.json</code>, per the <a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">MCP guide to local servers</a>. That works for one person. Nobody else can see the file, revoke the token or read what ran.</p>
<table>
<thead>
<tr>
<th>Decision</th>
<th>On one laptop</th>
<th>Across a company</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who is calling?</td>
<td>Whoever owns the token</td>
<td>Each person, through the identity provider</td>
</tr>
<tr>
<td>Which address?</td>
<td>A server per machine</td>
<td>One endpoint, or one per team</td>
</tr>
<tr>
<td>What can it reach?</td>
<td>Everything the token can</td>
<td>What the person's role allows</td>
</tr>
<tr>
<td>Where is the credential?</td>
<td>A config file or environment variable</td>
<td>A vault no person or AI client reads</td>
</tr>
<tr>
<td>What is recorded?</td>
<td>Nothing central</td>
<td>One audit record per call that reaches execution</td>
</tr>
<tr>
<td>What happens at departure?</td>
<td>Someone remembers the token</td>
<td>The identity provider ends access</td>
</tr>
<tr>
<td>Where does data live?</td>
<td>The laptop and the app vendor</td>
<td>A region the company picked</td>
</tr>
</tbody>
</table>
<h2 id="does-each-person-sign-in-to-mcp-as-themselves">Does each person sign in to MCP as themselves?</h2>
<p>They should, because a shared token makes every call look like one person. OAuth, the standard for delegated sign-in that never hands the client a password, gives each person their own grant.</p>
<p>In Elaichi, each person connects their AI client once and approves their own grant on a consent screen. Every call made with that grant acts as that person, in the organization they picked. Their permissions are looked up on each request, not stored in the token.</p>
<p>SSO (single sign-on through the company's identity provider) sits in front of that. Elaichi supports SAML and OIDC. An admin can enforce SSO for a verified domain, so an email-code or social sign-in for an address on it is refused. What the consent screen asks, and which boxes start ticked, is covered in the <a href="/blog/mcp-security-review-checklist/">MCP security review checklist</a>.</p>
<h2 id="should-you-run-one-mcp-endpoint-or-a-server-per-team">Should you run one MCP endpoint or a server per team?</h2>
<p>One endpoint is simpler, as long as it knows who is calling. A server per person or per team multiplies configs, tokens and logs. With one address, the person's grant decides the rest.</p>
<p>Elaichi has one address for every organization, <code>https://api.elaichi.ai/mcp</code>. The grant behind the token, not the URL, decides the organization and the person. Every client points at that same string. In Claude Team and Enterprise, an Owner adds a custom connector for the organization, and users then connect to it individually, per <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's help article on remote MCP connectors</a> (checked October 2026). The cost of each shape at 200 people is worked out in <a href="/blog/one-endpoint-vs-per-team-endpoint/">one endpoint versus one per team</a>.</p>
<p>Behind the address sits one governed catalog of 600+ connectors. Elaichi authors and runs most of them. The rest are native MCP connectors: the vendor builds and runs its own MCP server, and Elaichi handles sign-in, access and audit. An organization on Gold can also bring its own remote MCP server under the same rules.</p>
<h2 id="how-do-you-give-each-role-different-mcp-tools">How do you give each role different MCP tools?</h2>
<p>With roles and restrictions enforced on the server, not instructions to the model. OWASP's <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">guidance on excessive agency</a> says to limit an extension's permissions in other systems "to the minimum necessary".</p>
<p>In Elaichi, each member holds exactly one role. Every organization starts with eight system roles, and custom roles are available on Gold. A restriction is an allow or block rule. It targets a role or one member, and names whole connectors or single tools. A block always beats an allow. So support can keep its ticketing tools while finance reads the accounting app and cannot write to it, from the same address.</p>
<p>A role or restriction change takes effect within about two minutes. Removing a person takes effect on the next call. Starting roles per department are in the <a href="/blog/roll-out-claude-and-chatgpt-to-employees/">guide to rolling out Claude and ChatGPT</a>. What each AI client's own admin console controls is compared in <a href="/blog/it-admin-controls-mcp-connectors/">IT admin controls for MCP connectors</a>.</p>
<h2 id="who-holds-the-app-credentials-when-nobody-pastes-a-token">Who holds the app credentials when nobody pastes a token?</h2>
<p>A vault the gateway reads for each call, not the person and not the AI client. On a laptop, the API key sits in plain text beside the server config.</p>
<p>In Elaichi, a separate credential service holds every connected account's secrets. They are encrypted at rest with AES-256-GCM, and the key can be rotated. Elaichi fetches a credential into memory only for the call that needs it. The AI client holds only an Elaichi token: an access token that lasts one hour and a refresh token that rotates on every use. The MCP endpoint accepts nothing else, so a pasted API key does not work there.</p>
<p>One trade-off belongs in the design. A connection someone shares runs on its owner's sign-in to the app, so every caller acts with that owner's app permissions. Where the app should see each person, each person connects their own account. <a href="/blog/stop-sharing-personal-api-keys-with-ai-tools/">Moving off personal API keys</a> covers the switch.</p>
<h2 id="what-should-an-mcp-audit-record-show">What should an MCP audit record show?</h2>
<p>Who made the call, from which client, against which account, and whether it worked. In Elaichi, every connected-tool call that reaches execution writes a row. The row names the person, the connector, the connection the call actually reached, the MCP client, how the call was approved and the outcome. It records no argument values beyond the one path argument that names the object.</p>
<p>Every member sees their own activity. People with the audit permission see the whole organization. That includes the Auditor role, a free, read-only seat for compliance reviewers. Elaichi keeps 90 days of history, and export to your own Datadog comes with the Black plan, which is launching soon.</p>
<p>Note one limit in your control description. A call refused at the OAuth scope check, before any tool runs, writes no row. The full field list is in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must capture</a>.</p>
<h2 id="what-happens-to-mcp-access-when-someone-leaves">What happens to MCP access when someone leaves?</h2>
<p>The identity provider should end it, and the next call should fail: in Elaichi, a SCIM deprovision (SCIM is the protocol an identity provider uses to create and remove accounts in other services) suspends the member, which revokes every MCP grant they hold. <a href="/blog/mcp-governance/">MCP governance</a> covers the rest of the offboarding rules, and <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding when the agent holds access</a> gives the order of steps.</p>
<h2 id="where-does-enterprise-mcp-data-live">Where does enterprise MCP data live?</h2>
<p>In a region the company picks, with the exceptions written down. Elaichi has three regions, EU, US and APAC, picked when the organization is created and fixed after that. For EU and US organizations, the organization's data store stays in that region. So does the execution of its requests and tool calls. An APAC organization gets no such guarantee.</p>
<p>Some things sit outside the region. User accounts and SSO settings are not pinned to one. Files stored from tool results go to the EU for every organization. Elaichi's <a href="/privacy/">privacy policy</a> says its audit-log store is one EU instance serving all regions. For key custody, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. The GDPR side is covered in <a href="/blog/eu-data-residency-ai-agents/">EU data residency for AI agents</a>.</p>
<h2 id="where-does-a-governed-mcp-control-plane-fit">Where does a governed MCP control plane fit?</h2>
<p>Between the AI clients and the apps, as the one place where identity, rules, credentials and records meet. Elaichi is a governed MCP control plane and hosted MCP gateway. Every call from Claude, ChatGPT, Cursor or any MCP client passes through it. Each call is checked against the caller's access, and each call that reaches execution is written to the audit log. That holds whether the tool is a catalog connector Elaichi runs or an MCP server behind it.</p>
<p>Hosted means the company does not run an MCP server to use Elaichi. Gold includes the MCP endpoint, custom roles, restrictions, SSO, SCIM and group-to-role mappings. Gold lists at $15 per user per month in USD, and <a href="/pricing/">pricing</a> shows the local price. The category itself is set out in <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>.</p>
<p>Elaichi has one limit to state plainly. Its MCP endpoint never receives the person's prompt, only the tool call the client's model wrote. So it has nothing to judge a call against, and defense against prompt injection belongs to the client. Least privilege, enforced by roles and restrictions, limits the damage. Whether a client asks before each write is that client's own setting.</p>
<h2 id="what-to-ask-any-vendor-and-how-elaichi-answers">What to ask any vendor, and how Elaichi answers</h2>
<p>Ask about each decision in writing, then test the answers in a trial. The table pairs each question with why it matters and with Elaichi's answer.</p>
<table>
<thead>
<tr>
<th>Ask the vendor</th>
<th>Why it matters</th>
<th>Elaichi's answer</th>
</tr>
</thead>
<tbody>
<tr>
<td>How does each person sign in?</td>
<td>A shared token hides who acted</td>
<td>Their own OAuth grant, behind SAML or OIDC SSO</td>
</tr>
<tr>
<td>How many addresses will we manage?</td>
<td>Each one is a config and a token to rotate</td>
<td>One, <code>https://api.elaichi.ai/mcp</code></td>
</tr>
<tr>
<td>Can a rule cover one tool for one role?</td>
<td>App-level rules are too coarse for writes</td>
<td>Yes, allow and block rules per role or member</td>
</tr>
<tr>
<td>Who holds app credentials?</td>
<td>A pasted key outlives its owner</td>
<td>A separate encrypted credential service</td>
</tr>
<tr>
<td>What does one audit record hold?</td>
<td>Reviewers need the account reached</td>
<td>Person, client, connector, connection, approval, outcome</td>
</tr>
<tr>
<td>What happens when the identity provider removes someone?</td>
<td>Access should end with the account</td>
<td>SCIM suspends, grants are revoked, the next call fails</td>
</tr>
<tr>
<td>Where does data live, and what is outside it?</td>
<td>Residency claims have exceptions</td>
<td>EU, US or APAC, with the exceptions named</td>
</tr>
<tr>
<td>What does the product not cover?</td>
<td>Every gateway has a limit</td>
<td>Prompt injection, and app accounts at offboarding</td>
</tr>
</tbody>
</table>
<p>Security teams ask a deeper set of questions about tokens, consent and evidence. Send them the <a href="/blog/mcp-security-review-checklist/">ten-question security review</a> alongside this table.</p>
<h2 id="when-does-a-company-not-need-enterprise-mcp-tooling-yet">When does a company not need enterprise MCP tooling yet?</h2>
<p>When MCP is still one person's tool, or one app's. A developer running local servers against their own files needs none of this. The risk sits on their laptop, and endpoint controls cover it, not a gateway.</p>
<p>A company where one team uses one app may be fine for a while too, if that app's vendor runs its own MCP server. The vendor's own permissions apply. The same holds while no AI client can write to a system of record.</p>
<p>The case changes at the second app, the second client or the first write. Then one set of rules and one trail start to matter. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway</a> lists the signals to watch. When they arrive, start from the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is enterprise MCP?</strong></dt><dd>Enterprise MCP is the Model Context Protocol run for a whole company rather than on one person's laptop. It adds what a single user never needed: each person signs in through the company's identity provider, their role decides which tools they can reach, app credentials sit in a vault instead of config files, every tool call that runs leaves an audit record, and access ends when the identity provider removes the person. Products that provide this are usually called MCP gateways or MCP control planes.</dd><dt><strong>Do we need SSO and SCIM to roll out MCP?</strong></dt><dd>SSO decides who can sign in, and SCIM keeps membership in step with the identity provider, so both matter once more than a handful of people use MCP. Neither decides which tools a person can reach; roles and restrictions do that. In Elaichi, SSO (SAML or OIDC) and SCIM are on the Gold plan. A SCIM deprovision suspends the member, which revokes their MCP grants, so their AI client fails on its next call.</dd><dt><strong>Does each team need its own MCP server?</strong></dt><dd>Not when the endpoint knows who is calling. With Elaichi, everyone in every organization uses the same address, https://api.elaichi.ai/mcp. The OAuth grant behind each person's token decides the organization and the person, and their role and restrictions decide the tools. Each person still connects their AI client once and approves their own grant.</dd><dt><strong>How long does Elaichi keep the MCP audit log?</strong></dt><dd>Elaichi keeps 90 days of audit history. Every member can see their own activity, and people with the audit permission, including the free, read-only Auditor role, see the whole organization. For a longer history, export to your own Datadog comes with the Black plan, which is launching soon.</dd><dt><strong>Is Elaichi a self-hosted MCP gateway?</strong></dt><dd>No. Elaichi is a governed MCP control plane and hosted MCP gateway, so a company does not need to run an MCP server to use it. A company that does run a remote MCP server, reachable over public HTTPS, can add it to Elaichi as its own connector on the Gold plan, and calls through it follow the same roles, restrictions and audit log as every other connector.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Hosted MCP gateway vs running the gateway yourself</title>
      <link>https://elaichi.ai/blog/hosted-mcp-gateway/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/hosted-mcp-gateway/</guid>
      <description>A hosted MCP gateway runs the checkpoint every AI tool call passes through. Self-hosting puts it on your servers. Six questions decide which fits.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An MCP gateway is the layer every AI client's tool calls pass through, where access is checked and each call that runs is recorded. A self-hosted gateway puts that layer, or at least its data plane, on your infrastructure, in front of MCP servers you run. Elaichi, a governed MCP control plane and hosted MCP gateway, runs the endpoint, the credential store and most of its connectors, and governs vendors' own MCP servers under the same rules. Self-hosting is the better fit when the servers must stay on your network.</aside>
<h2 id="hosted-mcp-gateway-or-self-hosted-which-one-should-carry-your-ai-tool-calls">Hosted MCP gateway or self-hosted: which one should carry your AI tool calls?</h2>
<p>Choose hosted unless a policy or network rule forces the gateway onto your hosts. Elaichi is a governed MCP control plane and hosted MCP gateway, so weigh the trade-offs with that in mind.</p>
<p>A hosted MCP gateway and a self-hosted one do the same job. The difference is who runs it. The request usually reaches IT as a security requirement: every AI tool call must pass through one checkpoint that checks access and records the call. The platform team offers to run one. A vendor offers to run it for you.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An MCP gateway is the layer between AI clients and the tools they call. It signs each person in, decides which tools that person may reach, and writes down what happened. <a href="/blog/what-is-an-mcp-gateway/">The four shapes the name covers</a> are set out separately. This post takes one question only: should that layer sit on your infrastructure or on someone else's?</p>
<h2 id="what-does-a-self-hosted-mcp-gateway-put-on-your-servers">What does a self-hosted MCP gateway put on your servers?</h2>
<p>It puts the gateway's data plane, the part that handles each call, and usually the MCP servers behind it, on infrastructure you operate. Some of these products are managed through a vendor's console; the traffic still runs on your hosts. Your team installs the data plane, upgrades it and keeps it up.</p>
<p>Three products show the range of gateways whose data plane runs on your infrastructure. Docker calls its MCP Gateway an "open source solution for orchestrating Model Context Protocol (MCP) servers". It "runs MCP servers in isolated Docker containers", and with Docker Desktop's MCP Toolkit enabled it runs in the background (<a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">Docker docs</a>, checked October 2026). Docker's docs tag the whole MCP Catalog and Toolkit section Beta (same page, checked October 2026). <a href="/blog/docker-mcp-gateway-vs-managed-mcp-platform/">The Docker gateway comparison</a> covers it in depth.</p>
<p>Kong AI Gateway is managed through Kong's Konnect, while its data plane nodes "run in your environment (self-hosted, cloud, or Kubernetes)" (<a href="https://developer.konghq.com/ai-gateway/">Kong docs</a>, checked October 2026). Kong's AI MCP Proxy plugin supports per-tool access lists for its Consumers and Consumer Groups. All access attempts, allowed or denied, go to the plugin's audit log, and the plugin is part of Kong's AI Gateway Enterprise offering (<a href="https://developer.konghq.com/plugins/ai-mcp-proxy/">Kong plugin docs</a>, checked October 2026).</p>
<p>Lunar.dev presents MCPX as an enterprise MCP gateway, and its FAQ says MCPX is fully self hosted, running entirely inside your infrastructure (<a href="https://www.lunar.dev/">lunar.dev</a>, checked October 2026). <a href="/blog/lunar-mcpx-alternative-governed-access/">Counting servers before choosing MCPX</a> goes further on that product.</p>
<p>Each of these is built for a team that already runs services and wants policy in front of them.</p>
<h2 id="what-do-you-run-and-patch-on-each-side">What do you run and patch on each side?</h2>
<p>Self-hosted, you run the gateway and everything it depends on. Hosted, you run nothing for the gateway itself.</p>
<p>On the self-hosted side the list is concrete. There is the gateway binary or containers, the hosts under them, TLS certificates, the sign-in wiring to your identity provider, and each MCP server behind the gateway. Every one has its own release cycle. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The cost of running MCP servers yourself</a> prices the servers line by line, so this post does not repeat it.</p>
<p>On the hosted side, Elaichi hosts the one MCP endpoint and the catalog connectors behind it. A company does not need to run an MCP server to use Elaichi. Running one is a choice. What stays with you is configuration: who holds which role, which tools each role may reach, and which accounts are connected.</p>
<h2 id="where-do-the-app-credentials-live">Where do the app credentials live?</h2>
<p>With a self-hosted gateway, they live in your secret store. With Elaichi, they live in a separate credential service that Elaichi runs.</p>
<p>Someone has to hold them. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a> says an MCP server must only accept tokens valid for its own resources and "MUST NOT accept or transit any other tokens". The token used at the upstream app is a separate one. So the gateway, or the servers behind it, hold every app's credential. Docker describes its gateway as a proxy that manages configuration, credentials and access control (<a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">Docker docs</a>, checked October 2026). On a self-hosted gateway, that store, its encryption and its key rotation are yours.</p>
<p>Elaichi keeps connector credentials out of its main data. A separate credential service holds them, encrypted at rest with AES-256-GCM, and the key can be rotated without re-encrypting old rows. Elaichi fetches a credential into memory only for the call that needs it. The AI client holds only an Elaichi token. Elaichi never forwards that token to a remote MCP server, so a server sees only tokens its own authorization server issued.</p>
<p>The trade is custody. You trust the hosted vendor's handling instead of your own. For key custody, customer-managed keys in AWS KMS come with the Black plan, which is launching soon.</p>
<h2 id="who-writes-the-connectors-behind-the-gateway">Who writes the connectors behind the gateway?</h2>
<p>A self-hosted gateway governs servers that already exist. A hosted MCP gateway like Elaichi also serves the connectors, most of which it writes.</p>
<p>A gateway in front of servers adds a door, not apps. Kong's route is to turn existing APIs into tools an agent can call over MCP, which suits a company whose APIs already sit behind Kong (<a href="https://developer.konghq.com/ai-gateway/">Kong docs</a>, checked October 2026). For SaaS apps, the servers come from your team, the app vendor or the community.</p>
<p>Elaichi's catalog holds 600+ connectors of two kinds. Elaichi authors and runs most of them itself, so an app's API change is Elaichi's to fix. The rest are native MCP connectors: the vendor builds and runs its own MCP server, and Elaichi handles sign-in, access and audit in front of it. Datadog and Linear are there that way. <a href="/blog/vendor-mcp-servers-through-elaichi/">How vendor MCP servers run through Elaichi</a> covers that path.</p>
<p>A company can also bring its own server. On Gold, an Org Owner or Org Admin adds a remote MCP server as the organization's own connector. It must speak MCP over Streamable HTTP, the transport that sends each message as an HTTP request, and be reachable over public HTTPS. Restrictions and OAuth scopes, the permissions a person approves on the consent screen, are checked before a call leaves Elaichi, and only a tool on that connection's own active list can run.</p>
<h2 id="how-many-addresses-do-ai-clients-point-at">How many addresses do AI clients point at?</h2>
<p>With a self-hosted gateway, as many as you deploy. With Elaichi, one.</p>
<p>A self-hosted gateway's address count follows your topology. One gateway per laptop, one per team or one shared cluster are all possible, and each is a configuration someone keeps in step across Claude, ChatGPT, Cursor or any MCP client.</p>
<p>Elaichi serves every organization at <code>https://api.elaichi.ai/mcp</code>. The OAuth grant behind each token, not the URL, decides the organization and the person. OAuth is the sign-in standard that lets a client act as a named person without holding that person's password. Each member still connects their client once and approves their own grant. No URL carries a token, and there is no per-team or per-toolbox address to hand out or take back. <a href="/blog/one-endpoint-vs-per-team-endpoint/">Per-team and org-wide endpoints</a> compares the two models.</p>
<h2 id="who-carries-upgrades-uptime-and-the-pager">Who carries upgrades, uptime and the pager?</h2>
<p>Self-hosted, your team does, on its own schedule. Hosted, the vendor does, on the vendor's schedule.</p>
<p>Running the gateway yourself means you choose when to upgrade. You can hold a version through a busy quarter, test a release in staging first, and read the code before it runs. It also means the pager. A gateway outage stops every tool call routed through it, so it needs monitoring, failover and someone on call.</p>
<p>Elaichi patches the endpoint and the connectors it authors. For a native MCP connector, the vendor maintains its own server's tools. You give up control of timing: a change lands when Elaichi ships it. Ask any hosted vendor, Elaichi included, for its uptime commitment in writing before a rollout depends on it.</p>
<p>Changes you make yourself have timing too. In Elaichi a role or restriction change takes about two minutes to reach every surface. Removing or suspending a member revokes every live grant, so their AI clients fail on the next call.</p>
<h2 id="where-does-the-data-sit-with-a-hosted-mcp-gateway">Where does the data sit with a hosted MCP gateway?</h2>
<p>With a self-hosted gateway, it sits where you put it. With Elaichi, an EU or US organization is pinned to its region, APAC carries no residency guarantee, and a few things sit outside the region.</p>
<p>Self-hosting gives the most control over placement. The gateway's logs, config and secrets stay on your hosts. Calls to SaaS apps still leave your network, because the apps live elsewhere.</p>
<p>Elaichi has three regions, EU, US and APAC. The organization picks one at creation, and it cannot change later. For an EU or US organization, the data store (the per-organization store that holds most organization data) and the execution of its requests and tool calls are pinned to that region. For an APAC organization, region is not a residency guarantee.</p>
<p>Some things sit outside the region. User accounts and SSO settings are not pinned to one. Files stored from tool results go to the EU for every organization. Elaichi's <a href="/privacy/">privacy policy</a> says its audit-log store is one EU instance serving all regions, so a US or APAC organization should not expect its audit trail to stay in its region. Elaichi keeps 90 days of audit history. <a href="/blog/eu-data-residency-ai-agents/">Data residency for AI agents in the EU</a> goes deeper.</p>
<h2 id="how-do-the-two-compare-question-by-question">How do the two compare, question by question?</h2>
<p>Self-hosting keeps control and work in-house. A hosted MCP gateway moves both to a vendor.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Self-hosted MCP gateway</th>
<th>Hosted MCP gateway (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>What you run and patch</td>
<td>The gateway, its hosts, TLS, and the MCP servers behind it</td>
<td>Nothing for the gateway; Elaichi hosts the endpoint and catalog connectors</td>
</tr>
<tr>
<td>Where credentials live</td>
<td>Your secret store, encryption and rotation</td>
<td>A separate credential service, AES-256-GCM at rest; the client holds only an Elaichi token</td>
</tr>
<tr>
<td>Who writes the connectors</td>
<td>Your team, the app vendor or the community</td>
<td>Elaichi authors most; vendors run their own native MCP servers; you can add your own remote server on Gold</td>
</tr>
<tr>
<td>Addresses clients point at</td>
<td>One per gateway you deploy</td>
<td>One, <code>https://api.elaichi.ai/mcp</code>, for every organization</td>
</tr>
<tr>
<td>Upgrades and uptime</td>
<td>Your schedule and your pager</td>
<td>Elaichi's schedule; ask for the uptime commitment in writing</td>
</tr>
<tr>
<td>Data location</td>
<td>Wherever you run it</td>
<td>EU or US: data store and request execution pinned to the region. APAC: no residency guarantee. User accounts, stored tool files and the audit log sit outside the region</td>
</tr>
<tr>
<td>Inside your own network</td>
<td>Yes</td>
<td>No</td>
</tr>
</tbody>
</table>
<h2 id="when-is-self-hosting-the-mcp-gateway-the-right-call">When is self-hosting the MCP gateway the right call?</h2>
<p>Self-host when the servers or the policy require your own network. In these cases Elaichi is the wrong fit, and saying so saves a pilot.</p>
<ul>
<li><strong>The servers cannot be exposed.</strong> Elaichi's remote MCP connector needs public HTTPS. A server on an internal hostname, an IP address or localhost cannot be added, so a gateway inside the network fits.</li>
<li><strong>Policy says the checkpoint runs on your hosts.</strong> Some security programs require every gateway to sit in infrastructure the company operates. Elaichi is hosted only.</li>
<li><strong>The tools are local.</strong> A filesystem or browser tool on a developer's machine belongs in a local container, which is where Docker's gateway runs.</li>
<li><strong>Your MCP traffic is your own APIs.</strong> If those APIs already sit behind Kong, exposing them as MCP tools is configuration, not a new vendor.</li>
<li><strong>You need to hold upgrades or read the code.</strong> Docker's gateway is MIT-licensed open source in the <a href="https://github.com/docker/mcp-gateway">docker/mcp-gateway repository</a>, checked October 2026.</li>
<li><strong>The audit trail or the data must stay in your region.</strong> Elaichi's privacy policy says its audit-log store is one EU instance serving all regions, so a US or APAC organization should not expect its audit trail to stay in its region (<a href="/privacy/">privacy policy</a>). For APAC, the region is not a residency guarantee.</li>
</ul>
<p>With one app, one client and a few engineers, <a href="/blog/when-you-dont-need-an-mcp-gateway/">no gateway is needed yet</a>.</p>
<h2 id="can-you-run-a-self-hosted-gateway-and-a-hosted-one-together">Can you run a self-hosted gateway and a hosted one together?</h2>
<p>Yes. Split them by where the server lives. Internal and local tools stay behind the gateway you run. Company SaaS accounts go through Elaichi, where each person signs in once.</p>
<p>Keep each app on one path only. If Salesforce is reachable through both, Elaichi's restrictions and audit log miss the calls that took the other route. <a href="/blog/best-mcp-gateways/">Shortlisting MCP gateways by shape</a> lays out the vendors on each side. The <a href="/connectors/">connector catalog</a> shows which apps Elaichi already serves, and <a href="/use-cases/">team-by-team use cases</a> show where a rollout usually starts.</p>
<h2>FAQ</h2><dl><dt><strong>What is a hosted MCP gateway?</strong></dt><dd>A hosted MCP gateway is a checkpoint for AI tool calls that a vendor runs for you. Claude, ChatGPT, Cursor or any MCP client points at the vendor's address, each person signs in, each call is checked against that person's access, and each call that runs is recorded. A self-hosted gateway does the same job on servers your own team runs and patches. Elaichi is a hosted MCP gateway with one address, https://api.elaichi.ai/mcp, for every organization.</dd><dt><strong>Can Elaichi be self-hosted inside our own network?</strong></dt><dd>No. Elaichi is a hosted service only. The location control it offers is the region, EU, US or APAC, picked when the organization is created and fixed after that. An EU or US organization has its data store and request execution pinned to its region; an APAC organization gets no residency guarantee. If your policy says the gateway must run inside your own network, a self-hosted MCP gateway, where the data plane runs on your own infrastructure, is the better fit.</dd><dt><strong>Can a hosted MCP gateway govern an MCP server we run ourselves?</strong></dt><dd>Elaichi can, if the server speaks MCP over Streamable HTTP (the MCP transport that sends each message as an HTTP request) and is reachable over public HTTPS. An Org Owner or Org Admin on the Gold plan adds it as the organization's own remote MCP connector. Restrictions and OAuth scopes (the permissions a person approves when connecting a client) are then checked before a call leaves Elaichi, and every call that runs is written to the audit log. A server on localhost, an IP address or an internal hostname cannot be added.</dd><dt><strong>Where does a hosted MCP gateway keep the app credentials?</strong></dt><dd>In Elaichi, connector credentials sit in a separate credential service, not in the main data store. They are encrypted at rest with AES-256-GCM and fetched into memory only for the call that needs them. The AI client holds only an Elaichi token, never the app's credential. Elaichi also never forwards its own access token to a remote MCP server.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>comparisons</category>
    </item>
    <item>
      <title>MCP governance: who may do what, in which app</title>
      <link>https://elaichi.ai/blog/mcp-governance/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-governance/</guid>
      <description>MCP governance decides who connects which app, which tools each role calls, whose account a call uses, what is logged and how access ends.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> MCP governance is the set of rules for AI tool calls once MCP spreads past one developer: who may connect which app, which tools each role may call, whose credentials a call runs on, what is recorded and how access ends. Elaichi enforces those rules as a governed MCP control plane and hosted MCP gateway, at one endpoint that Claude, ChatGPT, Cursor or any MCP client signs into. A team with one developer, one client and read-only access does not need it yet.</aside>
<h2 id="what-does-mcp-governance-cover">What does MCP governance cover?</h2>
<p>MCP governance is the set of rules for what AI assistants may do in company apps. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The rules answer five questions: who may connect which app, which tools each role may call, whose credentials a call runs on, what is recorded, and how access ends when someone leaves.</p>
<p>One developer connects Cursor to <a href="/connectors/jira/">Jira</a> with a personal token, and it works. Six months later, support uses Claude against <a href="/connectors/zendesk/">Zendesk</a>, and finance uses ChatGPT against <a href="/connectors/quickbooks/">QuickBooks</a>. Emily Carter in sales has connected two <a href="/connectors/salesforce/">Salesforce</a> accounts. Then security asks: when Jake Morgan leaves on Friday, what can his assistant still reach? Nobody can answer it from one place.</p>
<p>This post is the rule model: restrictions, credentials, the record and offboarding. The buyer's view, with data regions and a vendor question table, is in <a href="/blog/enterprise-mcp/">enterprise MCP: a buyer's guide</a>.</p>
<p>The protocol leaves these decisions to you. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a> makes authorization optional. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">spec's tools section</a> wants a human who can deny tool calls, and asks clients to log tool use for audit. It does not say who that human is, which tools they may allow, or where the log lives. That gap is the governance layer.</p>
<h2 id="why-do-ai-governance-programs-miss-the-tool-call">Why do AI governance programs miss the tool call?</h2>
<p>Frameworks such as the NIST AI Risk Management Framework and ISO/IEC 42001 work at the level of policy, risk and management systems. They do not decide what one person's assistant may do in one app right now. MCP governance does, and it names who answers for it.</p>
<p>The frameworks show the altitude. The <a href="https://www.nist.gov/itl/ai-risk-management-framework">NIST AI Risk Management Framework</a> aims to bring trustworthiness into the design, development, use and evaluation of AI products and systems. <a href="https://www.iso.org/standard/42001">ISO/IEC 42001</a> sets requirements for an AI management system: the policies, objectives and processes an organization keeps for responsible AI. Neither tells you whether the support team's assistant may close tickets in Zendesk.</p>
<p>The risk lists come closer. <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP's entry on excessive agency</a> names three usual root causes: excessive functionality, excessive permissions and excessive autonomy. It advises acting in the context of the specific user, with least privilege, and enforcing authorization in downstream systems rather than in the model. A policy can state those rules. Something on the path of every call has to enforce them.</p>
<h2 id="who-may-connect-which-app">Who may connect which app?</h2>
<p>An admin decides which apps each role may reach, and members connect their own accounts inside that list. In Elaichi, the rule that sets this is a restriction. A restriction is an allow or block rule that targets a role or one member and names whole connectors or single tools.</p>
<p>With no rule in place, a Member can connect any catalog connector with their own account. For a shorter list per role, write allow rules that name whole connectors. Once a role carries any allow rule, every connector those rules do not name is restricted for that role. Watch for one trap: an allow rule that names nothing restricts everything for its target. It is a lockout, not a placeholder.</p>
<p>The same check runs everywhere a member meets a connector: the catalog, the connect step, the tool list their AI client sees, the call itself and the outbound request. A rule written for one member can only narrow what their role allows. It never loosens it.</p>
<p>Adding a new app is a separate decision. Creating a custom connector needs the connector:create permission, and among the built-in roles only Org Owner and Org Admin hold it. The console tags it "High trust". A restriction binds a connector's identity, not the host it calls, so a new connector aimed at a restricted API slips past the old restriction. <a href="/blog/approved-ai-tools-per-team/">Approved AI tools per team</a> walks through these rules for a real rollout.</p>
<h2 id="which-tools-can-each-role-call">Which tools can each role call?</h2>
<p>Tool-level rules decide which tools of an approved app a role may call. In Elaichi, a block always beats an allow.</p>
<p>An allow rule that names a few read tools holds the role to those tools on that app. The role then also needs allow rules for each other app it uses; otherwise those apps are restricted. A layer with only block rules has no allowlist, so every tool it does not name stays reachable. Three block rules on write tools leave the fourth write tool open. Allow rules also match a tool by the operation it performs, not by its label, so renaming a tool cannot widen access. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a>. Choosing between one tool and the whole app is covered in <a href="/blog/per-tool-vs-per-app-restrictions/">six restriction cases</a>.</p>
<p>The role also has to permit tool use at all. Running any connected tool over MCP needs the tool:execute permission. Guest, Billing Admin and Auditor do not hold it. A compliance reviewer can read the record without being able to act.</p>
<p>The person adds one more limit when they connect a client. Elaichi's consent screen lists what the client may do. "Run your connected tools" lets it read and change data in connected apps. Deleting there also needs "Delete data and remove access", which is never ticked by default. The person can also limit the client to toolboxes they pick (a toolbox is a named set of tools).</p>
<p>A change to a role or a restriction reaches every client within about two minutes, so plan pilots around that window.</p>
<h2 id="whose-credentials-does-each-call-run-on">Whose credentials does each call run on?</h2>
<p>Every call runs as one named person, on the account behind the connection it uses. Elaichi never runs a connected-tool call as the organization at large.</p>
<p>Over MCP, the person comes from the OAuth grant behind the client's token. OAuth is the sign-in standard MCP clients use, and a grant is the access one person approves for one client. Each member connects their client once and approves their own grant. The account comes from the connection. A connection a member made with their own login carries their own permissions in that app. A connection shared with a team runs every caller's call on its owner's sign-in.</p>
<p>Picking one is a governance decision. Use per-person connections when the app should see who is asking, such as a CRM with record-level sharing. Use one shared connection when a fixed permission set is the point, such as a read-only reporting account. A toolbox shared with a team runs each entry on the connection pinned into it, not on each member's own account. The longer argument is in <a href="/blog/ai-agents-employee-permissions/">AI agents with employee permissions</a>.</p>
<p>The AI client holds only an Elaichi token, never the app credential. Connector secrets sit in a separate credential service, encrypted at rest with AES-256-GCM. Elaichi fetches them into memory only for the call that needs them.</p>
<h2 id="what-should-the-record-show-for-each-ai-tool-call">What should the record show for each AI tool call?</h2>
<p>Each call that runs should leave a row naming the person, the client, the account reached and the outcome. Elaichi writes that row for every connected-tool call that reaches execution, whether it succeeds or fails.</p>
<p>The row records the acting person, the MCP client, the connector, the connection the call actually reached, the toolbox and the tool. It records whether the call was a read, a write or a delete, how it was approved, how it ended, an error code on failure, and what the call touched. It keeps no argument values beyond the id of the object a call names. A call refused earlier, for example for a missing scope, writes no row.</p>
<p>Everyone can read their own activity in the audit log. People with the audit:view permission, which Org Owner, Org Admin and Auditor hold, see the whole organization. Elaichi keeps 90 days of audit history. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. The field-by-field case is in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="how-does-ai-access-end-when-someone-leaves">How does AI access end when someone leaves?</h2>
<p>Removing or suspending a member ends their AI access on their client's next request. In Elaichi, removal and suspension revoke the person's MCP grants, and every MCP request reads the grant again.</p>
<p>Identity providers follow the same path. SCIM is the standard an identity provider uses to add and remove users in other apps. A SCIM deprovision suspends the member rather than deleting them, and suspension revokes their grants and API tokens. Reactivation does not restore the grants, so they connect again.</p>
<p>What the person built is the harder part. Elaichi's offboarding preview lists their connections, toolboxes, templates, synthetic tools and custom connectors, plus toolbox entries elsewhere that rely on them. Transfer each shared connection to someone staying as part of the removal. Left in place, it stays owned by the departed member, and nobody can transfer it afterwards. Toolbox entries the leaver pinned stop working for everyone until someone re-pins them.</p>
<p>Removing someone from Elaichi does not deactivate their accounts inside the connected apps. Deprovision those in each app or through your identity provider. The full last-day sequence is in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding AI access, contractors included</a>.</p>
<h2 id="where-does-a-hosted-mcp-gateway-fit">Where does a hosted MCP gateway fit?</h2>
<p>A hosted MCP gateway puts every AI tool call through one place where these rules are checked and recorded. Elaichi is a governed MCP control plane and hosted MCP gateway: Claude, ChatGPT, Cursor or any MCP client signs in to <code>https://api.elaichi.ai/mcp</code>, the same address for every organization, and one restriction applies to all of them. Each client's own settings, such as Claude's <a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">per-tool permissions</a> (Always allow, Needs approval or Blocked) and ChatGPT Business's <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">admin-only custom MCP apps</a>, govern that one client only (both checked October 2026). The buying questions are in <a href="/blog/enterprise-mcp/">enterprise MCP: a buyer's guide</a>.</p>
<h2 id="what-can-an-mcp-gateway-not-govern">What can an MCP gateway not govern?</h2>
<p>A gateway governs the calls that pass through it, and only those. Four limits apply to Elaichi.</p>
<ul>
<li><strong>Direct calls.</strong> A call a client makes straight to a vendor's own MCP server, outside Elaichi, is not governed by Elaichi. On Gold, an Org Owner or Org Admin can add that server as a remote MCP connector, if it is reachable over public HTTPS, to bring it under the same rules.</li>
<li><strong>Per-call approval.</strong> Over MCP, Elaichi does not ask before each call. The consent screen is the approval, and any per-call prompt a person sees comes from their own client.</li>
<li><strong>Injected instructions.</strong> Elaichi does not scan tool results sent to MCP clients for prompt injection, the trick of hiding instructions for the model inside data. That defense belongs to the client.</li>
<li><strong>Client-side tool rules.</strong> Claude's per-tool permissions see all of Elaichi's connected tools as a single tool, so they cannot tell one app from another. Write per-app rules in Elaichi instead.</li>
</ul>
<h2 id="when-can-a-team-skip-mcp-governance-for-now">When can a team skip MCP governance for now?</h2>
<p>A team with one developer, one client, one app and read-only access does not need a governance layer yet. The app's own permissions and the client's own settings cover that case. A gateway there adds a bill and a sign-in step, and its log has nobody to read it.</p>
<p>The answer changes when any one of four signals appears. A second client or team arrives. There are more accounts than people. A leaver's assistant still holds access. Someone outside the team has to answer for what an assistant did. The signals are spelled out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway yet</a>.</p>
<p>When they show up, start with <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is and who needs one</a>. Then check that your apps are in the <a href="/connectors/">connector catalog</a>, and compare plans on the <a href="/pricing/">pricing page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is MCP governance?</strong></dt><dd>MCP governance is the set of rules that controls what AI assistants may do in company apps through the Model Context Protocol. It covers who may connect which app, which tools each role may call, whose credentials each call runs on, what is recorded, and how access ends when someone leaves. Elaichi enforces these rules at one hosted MCP endpoint that Claude, ChatGPT, Cursor or any MCP client signs into.</dd><dt><strong>How is MCP governance different from AI governance?</strong></dt><dd>AI governance programs, such as ones built on the NIST AI Risk Management Framework or ISO/IEC 42001, deal with AI systems, risk and policy across the organization. MCP governance deals with single tool calls: which person's assistant may run which tool in which app, on whose account, and with what record. Most companies need both. The second is the one a policy document cannot enforce by itself.</dd><dt><strong>Do the admin settings in Claude or ChatGPT replace an MCP gateway?</strong></dt><dd>They govern one client each. On Claude's Team plan, only Owners and Primary Owners add custom connectors, and on ChatGPT Business only admins and owners deploy a custom MCP app (https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp and https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt, checked October 2026). A hosted MCP gateway such as Elaichi applies one set of roles, restrictions and audit records to every client that signs in, so one rule covers Claude, ChatGPT and Cursor together.</dd><dt><strong>How fast does an access change take effect in Elaichi?</strong></dt><dd>A change to a role, a restriction or a team takes effect within about two minutes. Removing or suspending a member, disconnecting a client's grant or revoking a share takes effect on the next call, because Elaichi reads those again on every request.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>governance</category>
    </item>
    <item>
      <title>Why AI pilots fail, and how to get to daily use</title>
      <link>https://elaichi.ai/blog/why-ai-pilots-fail/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/why-ai-pilots-fail/</guid>
      <description>Why AI pilots fail: the AI cannot reach your apps, nobody trusts it, or nobody owns it. The fix for each cause, and how to measure daily use.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Most AI pilots fail for plain reasons: the AI cannot reach the apps where the work happens, nobody trusts it with company data, it was built for a demo, nobody owns it afterward, and nobody said what "working" means. Each cause has a plain fix. Elaichi's forward deployed engineers build in a company's real apps, with access rules per person and an activity log, and stay until the team uses the AI every day.</aside>
<p>The demo went well. The AI wrote a clean reply to a customer, or built a sales
summary in seconds, and the room was impressed. Six weeks later, almost nobody
on the team opens it. This is the most common end for a company AI pilot (a
small trial run before a full rollout), and the reasons why AI pilots fail are
usually plain ones. They are about access, trust, design, ownership and
measurement, not about how clever the AI is. Each one has a plain fix.</p>
<h2 id="why-ai-pilots-fail-the-five-causes">Why AI pilots fail: the five causes</h2>
<p>AI pilots fail mostly because the pilot never touches the real work. The AI
model is rarely the problem.</p>
<p>The numbers say this is common.
Gartner predicted that at least 30% of generative AI projects would be abandoned after proof of concept by the end of 2025, citing poor data quality, weak risk controls, rising costs or unclear business value (<a href="https://www.gartner.com/en/newsroom/press-releases/2024-07-29-gartner-predicts-30-percent-of-generative-ai-projects-will-be-abandoned-after-proof-of-concept-by-end-of-2025">Gartner, July 2024</a>).
A proof of concept is a small test that shows an idea can work.
In a survey of more than 1,000 companies, S&#x26;P Global Market Intelligence found 42% had abandoned most of their AI initiatives in 2025, up from 17% a year earlier (<a href="https://www.ciodive.com/news/AI-project-fail-data-SPGlobal/742590/">CIO Dive</a>).
MIT's NANDA report "The GenAI Divide" found that only about 5% of AI pilots reached fast revenue growth, while most had little or no measurable effect on profit and loss (<a href="https://fortune.com/2025/08/18/mit-report-95-percent-generative-ai-pilots-at-companies-failing-cfo/">Fortune</a>).
"Fail" there means no measurable financial result, not a broken tool.</p>
<p>Five causes show up again and again. Each has its own fix.</p>
<h2 id="cause-one-the-ai-cannot-reach-the-apps-where-work-happens">Cause one: the AI cannot reach the apps where work happens</h2>
<p>When the AI cannot open the CRM, the help desk or the accounting app, people
must copy data in and copy answers out. That extra step kills daily use.</p>
<p>Take a support team at an online store. The pilot AI writes good replies, but
it cannot see the customer's orders or past tickets. So an agent opens three
apps, copies the details into the chat, then pastes the reply back. After a
week, the agent decides it is faster to write the reply alone.</p>
<p>The fix is to connect the AI to the apps the team already uses, so it reads
and acts there. Elaichi connects an AI assistant to 700+ apps, which you can
browse in the <a href="/connectors/">connector catalog</a>. A CRM is the usual first example: see <a href="/blog/connect-ai-to-crm/">connecting AI to your CRM</a>. The rule of thumb is simple.
If a job needs three apps, the AI needs all three before the pilot starts.</p>
<h2 id="cause-two-nobody-trusts-the-ai-with-company-data">Cause two: nobody trusts the AI with company data</h2>
<p>A pilot stalls when IT, legal or the team leads do not know what the AI can
see or change. Without clear limits, the safe answer is "do not use it."</p>
<p>A finance team at an accounting firm is a good example. The partners like the
idea of AI that matches invoices to payments. But nobody can say whether it
could also see payroll, or send a payment by mistake. So the pilot stays on
sample data, and sample data never becomes daily work.</p>
<p>The fix is limits that are set before people start. With Elaichi, the AI can only use the apps and actions you allow for each person. An admin can restrict a tool
or a whole app for a role or for one member, and that change takes effect
within about two minutes. Each action the AI runs goes into an activity log (a record of who did what, and when). The customer picks EU, US or APAC when the organization is created. For EU and US, the company's Elaichi data store and the execution of its org-scoped requests stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The <a href="/security/">security page</a> has the details.</p>
<h2 id="cause-three-the-pilot-was-built-for-a-demo-not-for-the-job">Cause three: the pilot was built for a demo, not for the job</h2>
<p>A demo pilot shows what the AI can do on a good day. A daily-use pilot fits
how one team does one job, including the dull steps and the exceptions.</p>
<p>Picture a sales team at a software company. The pilot answers clever
questions about the market, which looks good in a meeting. What the reps
actually need is a short brief before each call and a list of deals that have
gone quiet. Nobody asked them, so they never use what was built.</p>
<p>The fix is to start with the people who do the job. Sit with them for an hour.
Write down the steps they repeat every day and the ones they hate. Pick one
job, then build the AI around that job and nothing else. Elaichi's
<a href="/use-cases/">use cases</a> show this job-first approach for sales, support,
finance, HR and IT.</p>
<h2 id="cause-four-nobody-owns-the-ai-after-the-pilot">Cause four: nobody owns the AI after the pilot</h2>
<p>Pilots often belong to a project, and projects end. When nobody owns the AI
afterward, it breaks quietly and people stop trusting it.</p>
<p>A logistics firm runs a pilot that helps dispatch see shipments and jobs in
one place. The outside team that built it leaves. Then a new hire needs
access, an app changes, and a step stops working. Nobody knows who to ask.
Within a month, dispatch is back to spreadsheets.</p>
<p>The fix is to name an owner inside the company before the pilot starts. That
person adds people, changes who can do what, and checks the activity log. They
also need a written guide, not a memory of a meeting. When Elaichi's engineers
hand over, the customer's admins run everything from Elaichi with a written
guide. The customer also owns what was built: the setup, the instructions for
the AI and everything it produces stay in its own account and apps.</p>
<h2 id="cause-five-nobody-defined-what-working-means">Cause five: nobody defined what "working" means</h2>
<p>If nobody says what success looks like, every pilot ends with "it was
interesting." Interesting is not a reason to change how a team works.</p>
<p>An HR team pilots AI for new-hire setup. It seems to help. But nobody counted
how long setup took before, or how many steps were missed. So when the budget
review comes, there is nothing to show, and the pilot ends.</p>
<p>The fix is to write down two or three measures before the pilot starts. Keep
them about the job: time per task, number of missed steps, or how many items
the team clears in a week. Measure them on real work, before and after. Agree
on them with the person who owns the job, not only with the person who bought
the tool.</p>
<h2 id="what-does-daily-use-of-ai-look-like">What does daily use of AI look like?</h2>
<p>Daily use means people reach for the AI as part of the job, without a reminder.
It also means the AI stays inside each person's access, and its actions are on
record.</p>
<p>Three signals tell you a pilot has become daily work:</p>
<ul>
<li><strong>People use it without being reminded.</strong> Nobody sends a message asking the
team to "try the AI." Usage holds steady after the launch week ends.</li>
<li><strong>It acts only within each person's access.</strong> A sales rep's AI sees what the
rep can see, and an intern's AI sees less. When someone changes role, the AI
changes with them.</li>
<li><strong>Its actions are recorded.</strong> Anyone who needs to can check what the AI did,
for whom, and in which app.</li>
</ul>
<p>Elaichi's activity log keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none), so the third signal is a
report you read rather than a guess. The post on
<a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must capture</a>
covers what a useful record holds.</p>
<h2 id="when-should-an-ai-pilot-stop">When should an AI pilot stop?</h2>
<p>A pilot should stop when the job does not suit AI, and stopping then is a good
result. It frees the team to try a job that does suit it.</p>
<p>Stop when the job happens too rarely to be worth the setup. Stop when the AI's
mistakes take longer to fix than the work it saves. Stop when the data the job
depends on is wrong or missing, because AI makes bad data move faster. And stop
when the people who do the job, after a fair trial on real work, do not want it.</p>
<p>Some jobs need a person to decide every time. For those, the AI can prepare the
work and a person approves it, as the post on
<a href="/blog/human-approval-for-ai-agent-actions/">human approval for AI actions</a>
explains. If even that adds no value, end the pilot and write down why.</p>
<h2 id="how-elaichis-engineers-take-a-pilot-to-daily-use">How Elaichi's engineers take a pilot to daily use</h2>
<p>Elaichi Services is AI consulting, automation and integration delivered by
forward deployed engineers. These are engineers who work directly with your
team, build in your real apps, and stay until the AI is in daily use.</p>
<p>They learn the work with the people who do it. They write a plan that says
which jobs the AI takes over, which apps it needs, who can use it, and how
everyone will know it works. The company approves the plan first. Then they
connect the apps, set the access rules, test on real work, fix what is off, and
hand over a written guide. Each step is laid out on the page for <a href="/services/">Elaichi's AI consulting, automation and integration</a> service.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Tell us which job keeps eating your team's week. Our engineers will set up AI that does it inside the apps you already use.</p><a href="/services/" class="cta-button">Talk to our engineers</a></aside>
<h2>FAQ</h2><dl><dt><strong>Why do most AI pilots fail?</strong></dt><dd>Most AI pilots fail for reasons that have little to do with the AI model. The AI cannot reach the apps where the work happens, so people copy and paste. Nobody trusts it with company data. It was built to impress in a demo, not for the people who do the job. Nobody owns it after the pilot ends. And nobody wrote down what "working" would look like.</dd><dt><strong>How do you measure whether an AI pilot worked?</strong></dt><dd>Measure use, not impressions. Check whether people use the AI for the job without being reminded, whether it acts only within each person's own access, and whether its actions in your apps are recorded. Then compare the time the job took before and after on the same real work. Decide these measures before the pilot starts, with the person who owns the job.</dd><dt><strong>When should a company stop an AI pilot?</strong></dt><dd>Stop when the job is too rare to be worth it, when the AI's mistakes cost more to fix than the work it saves, or when the data it needs is not reliable. Also stop when the people who do the job do not want it after a fair trial on real work. Stopping a pilot that does not fit is a good result, because it frees time for one that does.</dd><dt><strong>How long should an AI pilot run?</strong></dt><dd>Long enough for the people who do the job to use it on real work through a normal cycle, such as a week of support tickets or one month-end close. A pilot that ends before a normal cycle ends tells you how the demo went, not how the work goes.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai-adoption</category>
    </item>
    <item>
      <title>Vendor MCP servers: why run them through Elaichi</title>
      <link>https://elaichi.ai/blog/vendor-mcp-servers-through-elaichi/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/vendor-mcp-servers-through-elaichi/</guid>
      <description>Vendor MCP servers bring the vendor&apos;s own tools. Through Elaichi they also get one address, per-person sign-in, tool rules and one audit log.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Vendor MCP servers, such as Linear's or Datadog's, are built and run by the app's own vendor. Connected straight to each AI client, every client needs its own setup, and Elaichi sees none of the calls. Connected once through Elaichi as a native MCP connector, the same server sits behind one address that Claude, ChatGPT and Cursor all sign into, with per-person sign-in, restrictions down to a single tool and one audit log. The vendor still owns the tools, and tool issues go to its support contact.</aside>
<h2 id="what-do-vendor-mcp-servers-change-for-it">What do vendor MCP servers change for IT?</h2>
<p>Vendor MCP servers move the tool code to the app's own vendor. The open question becomes where the calls go, and who is allowed to make them.</p>
<p>Linear, Datadog, GitLab and PostHog each run an MCP server of their own. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An engineer can paste one of those server addresses into Claude this afternoon, and it will work. Then support wants Linear in ChatGPT, and finance wants another app in Cursor. Each request is reasonable on its own. Together they become a list of servers, clients and sign-ins that nobody owns.</p>
<p>This post covers one choice for each of those servers. You can point every AI client at the vendor's server directly, or connect it once through Elaichi as a native MCP connector. Elaichi's catalog holds two kinds of connector. Most are connectors Elaichi writes and runs itself. A native MCP connector is the vendor's own server: the vendor builds and runs it, and Elaichi handles sign-in, access and audit in front of it.</p>
<h2 id="what-happens-when-each-ai-client-connects-to-the-vendor-directly">What happens when each AI client connects to the vendor directly?</h2>
<p>Each client becomes its own setup, with its own rules and its own record. Calls a client makes to a vendor's server directly do not pass through Elaichi, so Elaichi does not govern them.</p>
<p>The setup work repeats for every client. On Claude Team and Enterprise plans, an Owner adds a remote MCP server as a custom connector, and each member then clicks Connect to sign in (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic</a>, checked October 2026). In ChatGPT, an admin or owner creates a custom MCP app, gives the server's endpoint and sign-in method, and scans its tools (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI</a>, checked October 2026). Cursor reads servers from an <code>mcp.json</code> file in a project or in each person's home directory (<a href="https://cursor.com/docs/mcp">Cursor docs</a>, checked October 2026).</p>
<p>Three vendor servers across three clients can mean nine separate setups. Each one keeps its own idea of which tools are allowed. Claude sets tool permissions per connector, per group of tools or per tool, but only inside Claude (<a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">Anthropic</a>, checked October 2026). None of those settings follows a person into another client. When someone leaves, the offboarding list includes every client where they signed in to a vendor's server.</p>
<h2 id="what-does-elaichi-add-in-front-of-a-vendors-mcp-server">What does Elaichi add in front of a vendor's MCP server?</h2>
<p>Elaichi puts the vendor's server behind the same address, sign-in, rules and audit log as every other connector. The vendor's tools still run on the vendor's server.</p>
<p><strong>One address.</strong> Claude, ChatGPT and Cursor all sign into <code>https://api.elaichi.ai/mcp</code> with OAuth, the standard way an app gets scoped access without a password. Tools from every connected app come through that one address, whichever vendor makes the app. A model finds a connected tool with <code>search_tools</code> and runs it with <code>execute_tool</code>. Elaichi staff already publish Linear's server in the catalog, so nobody adds it to each client: each member connects it once.</p>
<p><strong>Each person signs in as themselves.</strong> Each person signs in to Elaichi as themselves. Members connect with their own sign-in at the vendor, and a connection someone shares runs on its owner's account. For an OAuth server, that runs through an OAuth client Elaichi set up. Elaichi's separate credential service keeps the credential and fetches it for each call. The AI client holds only its Elaichi token. Elaichi never forwards that token to the vendor's server, which sees only a token its own authorization server issued.</p>
<p><strong>Rules checked before the call leaves.</strong> A restriction is a rule that blocks or allows connectors and tools. It can name the whole connector or a single tool. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Every check runs before a call leaves Elaichi for the vendor's server. By default, a tool the vendor does not label read-only or non-destructive counts as destructive. Over MCP it needs the "Delete data and remove access" consent, which is never ticked by default.</p>
<p><strong>One audit log.</strong> The audit log is the record of who did what. Each call that runs is recorded with the person, the tool, the connector, the connection it reached and the AI client that sent it. A Linear call from Claude and a Datadog call from Cursor land in the same log. Everyone can see their own activity there, and people with the audit permission see the whole organization.</p>
<p><strong>One offboarding step.</strong> A grant is the approval a person gives one AI client to act for them in Elaichi. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The person's next call fails in every client at once, whichever vendor's server it was headed for.</p>
<h2 id="what-stays-with-the-vendor">What stays with the vendor?</h2>
<p>The vendor owns the server and every tool on it. Elaichi governs the calls, and its staff do not write or curate the tools.</p>
<p>By default, the tools a member can call are the ones the vendor's server lists to the connection they use. Elaichi reads that list when the connection becomes active, when someone refreshes it, once a day, and when a call names a tool the list lacks. Different connections can see different tools, because each list comes from that connection's own account.</p>
<p>When an automatic refresh adds, changes or re-tiers a tool, Elaichi writes an audit entry with the counts, naming up to 20 of the added and re-tiered tools. A vendor changing what its server offers is therefore on the record, not just in the vendor's release notes.</p>
<p>Tool issues go to the vendor. Each native MCP connector page names the vendor's support contact, an email address or a link, as on the <a href="/connectors/linear/">Linear connector page</a>. Someone who can manage the connector can still turn a single tool off for everyone while the vendor looks into it. A restriction can block it for one role instead, and a restriction change takes effect within about two minutes. If Elaichi unpublishes a server, its connections are kept and show as unavailable, and they work again if it is published again.</p>
<h2 id="what-does-routing-through-elaichi-cost-you">What does routing through Elaichi cost you?</h2>
<p>It adds a hop, some limits and one more party in the path. Name these before you route every vendor server through Elaichi.</p>
<ul>
<li><strong>A second party in every call.</strong> A call passes through Elaichi and then the vendor. Elaichi does not run the vendor's server, so an outage or a faulty tool there is the vendor's to resolve.</li>
<li><strong>Limits per call.</strong> Elaichi gives the vendor's server 30 seconds per operation and 60 seconds per call, retries included. It caps one tool result at 4 MiB, and one connection at 500 tools.</li>
<li><strong>Coarser switches in the client.</strong> Behind Elaichi, a client sees <code>execute_tool</code> rather than each vendor's tools. A Claude permission set on <code>execute_tool</code> covers every connected app at once, so tool-level rules belong in Elaichi.</li>
<li><strong>No per-call approval over MCP.</strong> Once a person's grant holds the delete consent, a tool that deletes runs without a per-call approval. Without that consent, the call is refused.</li>
</ul>
<h2 id="when-is-a-direct-connection-enough">When is a direct connection enough?</h2>
<p>A direct connection is enough when one team uses one vendor's server from one client, and that client's own controls cover the risk. Elaichi adds little in that case.</p>
<p>A five-person engineering team using Linear's server only in Claude can manage it from Claude's console. Claude's per-tool settings can block a tool or require approval for it (<a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">Anthropic</a>, checked October 2026). The case for Elaichi starts when a second client or a second team appears. It also starts when someone asks for one record of what every AI did, across every app.</p>
<p>The same logic covers a server that is not in Elaichi's catalog. An Org Owner or Org Admin on Gold, or on Black once it launches, can add a remote MCP server reachable over public HTTPS as the organization's own connector. Its calls then follow the same rules and land in the same audit log. A server on a private network or a laptop cannot be added that way, and stays a direct connection.</p>
<h2 id="how-does-a-native-mcp-connector-differ-from-one-elaichi-writes">How does a native MCP connector differ from one Elaichi writes?</h2>
<p>The difference is who writes and runs the tools. The address, the rules and the audit log are the same for both kinds.</p>
<table>
<thead>
<tr>
<th></th>
<th>Connector Elaichi writes</th>
<th>Native MCP connector</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who builds and runs the tools</td>
<td>Elaichi</td>
<td>The app's vendor</td>
</tr>
<tr>
<td>Which MCP server answers</td>
<td>Elaichi itself</td>
<td>The vendor's own server, behind Elaichi</td>
</tr>
<tr>
<td>Where the tool list comes from</td>
<td>Elaichi's catalog</td>
<td>The vendor's server, read per connection</td>
</tr>
<tr>
<td>Address clients use</td>
<td><code>https://api.elaichi.ai/mcp</code></td>
<td><code>https://api.elaichi.ai/mcp</code></td>
</tr>
<tr>
<td>Restrictions and audit log</td>
<td>Elaichi's</td>
<td>Elaichi's</td>
</tr>
<tr>
<td>Where tool issues go</td>
<td>Elaichi, which maintains it</td>
<td>The vendor's support contact</td>
</tr>
</tbody>
</table>
<p>Both kinds sit side by side in the <a href="/connectors/">connector catalog</a>, where a native MCP connector carries the MCP mark beside its name. <a href="/connectors/datadog/">Datadog</a> and <a href="/connectors/posthog/">PostHog</a> are native, and <a href="/connectors/salesforce/">Salesforce</a> is one Elaichi writes. For the model underneath, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For what each client's own console can and cannot do, see <a href="/blog/it-admin-controls-mcp-connectors/">the admin controls in Claude, ChatGPT and Cursor</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can I connect a vendor's MCP server to Claude directly instead of through Elaichi?</strong></dt><dd>Yes. On Claude Team and Enterprise plans an Owner adds the server as a custom connector, and each member connects it (Anthropic's help center, checked October 2026). Calls made that way go straight to the vendor's server and do not pass through Elaichi, so Elaichi's restrictions and audit log do not apply to them. Each other client then needs its own setup for the same server.</dd><dt><strong>Who fixes a broken tool on a native MCP connector in Elaichi?</strong></dt><dd>The app's vendor builds and runs a native MCP connector's server and tools, and Elaichi staff do not curate them. Report the problem to the vendor through the support contact on the connector's page. Inside Elaichi, someone who can manage the connector can turn that tool off for everyone, or a restriction can block it for one role.</dd><dt><strong>Do Elaichi's restrictions apply to a vendor's own MCP server?</strong></dt><dd>Yes, for every call made through Elaichi. A restriction can block the whole connector or a single tool for a role or one person, and it is checked before the call leaves Elaichi for the vendor's server. By default, a tool the vendor does not label read-only or non-destructive counts as destructive, so over MCP it also needs the "Delete data and remove access" consent.</dd><dt><strong>Does the AI client hold my credential for the vendor's app?</strong></dt><dd>No. The AI client signs in to Elaichi with OAuth and holds only an Elaichi token. The credential for the vendor's app is kept by Elaichi's separate credential service and fetched for each call. Elaichi never forwards its own token to the vendor's server, which sees only a token its own authorization server issued.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate>
      <category>governance</category>
    </item>
    <item>
      <title>AI agents with employee permissions, no shared bot</title>
      <link>https://elaichi.ai/blog/ai-agents-employee-permissions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/ai-agents-employee-permissions/</guid>
      <description>How to run AI agents with employee permissions instead of one shared service account, and the cases where a named service identity is still correct.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Give the agent the employee's own OAuth grant rather than a shared key. In Elaichi the AI client points at one organization-wide MCP endpoint, each person signs in once in a browser, and every call is checked against that person's role, scopes and restrictions. Where the app itself must see the person, share a template each member stamps onto their own connection, because a shared connection runs on its owner's credential.</aside>
<h2 id="why-a-shared-service-account-fails-the-first-access-review">Why a shared service account fails the first access review</h2>
<p>A finance analyst asks Claude for last quarter's unpaid invoices. The call has to reach the accounting app as somebody. Most first builds answer that with a service account: one API key, one bot user, wired in for everyone. The alternative is AI agents with employee permissions, where each call runs on the grant of the person who asked.</p>
<p>A service account is one identity holding the union of everyone's access. Three failures follow from that single sentence, and each one surfaces in a different room.</p>
<p><strong>Reach.</strong> The bot has to cover the widest user of the app, so it carries records and fields the narrowest user should never see. Everyone who can prompt the assistant inherits that reach by default. A support rep asks the assistant to "check this customer's account". That call is routed through a credential that can also see payroll data, refund limits, and every other customer record the app holds. The bot's single API key was provisioned for whoever on the team needed the broadest access.</p>
<p><strong>Attribution.</strong> The SaaS app's own log shows the bot, not the person. A deal stage changes in Salesforce. The audit log answer to "who changed this" is the same service-account name for every person in the company, every time. An investigator cannot tell whether a CFO or a first-week hire triggered a sensitive export. The app's native logging has no way to distinguish them, because as far as that app is concerned, there's only one user.</p>
<p><strong>Revocation.</strong> Removing a person from the identity provider touches nothing the bot holds. The API key lives in a config file or environment variable outside the IdP's reach. So offboarding a person through Okta or Entra does nothing to the credential. The key keeps working for whoever else still points at it. Rotating it is a single change that breaks every integration built on that key at once, not a per-person revocation.</p>
<p>A key sitting in a client config has further problems of its own. Credential sprawl follows across every client that stores it. There is no scoping per use case, and no expiry tied to employment status. <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth or API keys for AI agents</a> works through them in detail.</p>
<p><strong>The three patterns compared:</strong></p>
<table>
<thead>
<tr>
<th></th>
<th>Shared service account</th>
<th>Delegated OAuth (per-person grant)</th>
<th>Named service identity (frozen entry)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Who the app sees</strong></td>
<td>One bot identity for everyone</td>
<td>The actual employee, every call</td>
<td>One named owner, for a specific unattended job</td>
</tr>
<tr>
<td><strong>Reach per call</strong></td>
<td>Union of every grantee's needs</td>
<td>Exactly that employee's own access</td>
<td>Whatever the owner's account can do, often narrowed by frozen arguments</td>
</tr>
<tr>
<td><strong>Attribution in the app's log</strong></td>
<td>Bot name, always</td>
<td>The employee's own account</td>
<td>The owner's account, by design</td>
</tr>
<tr>
<td><strong>Revocation on offboarding</strong></td>
<td>Nothing happens automatically; manual key rotation required</td>
<td>On the next call once the member is removed or suspended, including a suspension by SCIM</td>
<td>The entry stops resolving until someone present re-pins it</td>
</tr>
<tr>
<td><strong>Setup cost</strong></td>
<td>One key, once</td>
<td>One OAuth sign-in per person</td>
<td>One owner, one frozen toolbox entry</td>
</tr>
<tr>
<td><strong>Correct use case</strong></td>
<td>Never, structurally</td>
<td>Any action a specific person asks the agent to take</td>
<td>Scheduled or team-owned jobs nobody is asking for in chat</td>
</tr>
</tbody>
</table>
<h2 id="what-does-it-take-to-run-ai-agents-with-employee-permissions">What does it take to run AI agents with employee permissions?</h2>
<p>The AI client becomes an MCP client on one organization-wide endpoint, and each employee signs in once with their own OAuth grant. No shared key exists, so no identity holds the union.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. In Elaichi the address is <code>POST https://api.elaichi.ai/mcp</code>, the same for every organization. Standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. It follows the <a href="https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization">MCP authorization specification</a>'s model of per-client, per-user grants rather than a single server-held credential. There are no per-toolbox URLs and no embedded tokens, so there is no server to create or revoke per person. The grant is what varies.</p>
<p>An admin adds that address once where the client allows it. A custom connector in <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Claude</a> Team or Enterprise, a custom app in <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">ChatGPT</a> Business, a shared server in <a href="https://cursor.com/docs/mcp">Cursor</a>. Each member then connects and signs in themselves. That is one browser step per person, not zero. The tradeoff for eliminating the shared key is that every new employee has an onboarding action instead of inheriting a pre-wired bot.</p>
<p>The client registers itself through <a href="https://datatracker.ietf.org/doc/html/rfc7591">OAuth dynamic client registration</a>, so there is no client ID or secret to type. The person lands on Elaichi's consent screen, picks the organization if they belong to more than one, and ticks scopes. Every scope the client asked for is pre-ticked except delete, which is never pre-ticked by default. The asymmetry is deliberate, since over-granting read access is recoverable and over-granting delete is not.</p>
<p>After that, each call is checked three ways, every time, not just at sign-in:</p>
<ol>
<li><strong>Role check.</strong> The person's role must carry <code>tool:execute</code>, or the tool list comes back empty.</li>
<li><strong>Scope check.</strong> The grant's scopes gate what the endpoint will advertise and run.</li>
<li><strong>Restriction check.</strong> Restrictions are rules naming which connectors and tools a target may reach, written <a href="/blog/per-tool-vs-per-app-restrictions/">per whole app or per single tool</a>. They are enforced against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</li>
</ol>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</p>
<p>Freshness is the part people get wrong. A permission model that only checks at OAuth consent time is a permission model that's wrong the moment someone's role changes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A role or restriction change is different in kind from a full grant revocation, and takes effect within about two minutes.</p>
<h2 id="when-should-the-app-itself-see-the-person-not-a-shared-account">When should the app itself see the person, not a shared account?</h2>
<p>Whenever the record ought to carry a name. The way to get that is a template each person stamps onto their own connection. A shared connection runs on its owner's credential regardless of who triggers it.</p>
<p>The distinction is worth being exact about, because the two look similar and behave very differently:</p>
<ul>
<li>A <strong>toolbox</strong> shared at <code>use</code> runs on the connection pinned in its entries, which belongs to the owner. Every grantee's call reaches the app as that one account, and the app's log names the owner rather than the person who asked. This is correct for the named-service-identity pattern below and wrong for everything else.</li>
<li>A <strong>template</strong> holds a tool list with renames, defaults, and frozen parameters, and never holds a connection. Share it at <code>use</code>, and each member stamps their own toolbox from it. Stamping fills each entry from connections that person already has permission to use, so the resulting toolbox runs on their own account. An entry with no usable connection is left as "needs connection" until they connect one themselves.</li>
</ul>
<p>So never pair "each person connects their own account" with "share one toolbox with the team". That combination silently collapses into the owner's identity. Per-person connections need a shared <em>template</em>, not a shared <em>toolbox</em>. Stamping copies the template once, so editing the template later does not retroactively change a toolbox someone already stamped from it.</p>
<p>This is what makes the Salesforce or Zendesk record show the rep or the agent who asked, instead of a generic integration user. It also means a person's reach inside the app is exactly whatever their own account already had, nothing more. The app's own permission model still binds, and Elaichi narrows it further rather than widening it. A template or restriction can remove access the person's app account technically has. Nothing can grant access their account doesn't have.</p>
<h2 id="what-the-audit-trail-says-when-an-agent-acts-for-someone">What the audit trail says when an agent acts for someone</h2>
<p>The person is the actor, not the client and not the organization. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), with <code>actor_kind</code> recorded at the point of action rather than inferred afterward from context.</p>
<p>For a call from Claude, ChatGPT, Cursor, or any other MCP client, <code>actor_kind</code> is <code>user</code>. The surface is <code>mcp</code>, and the OAuth client is named on the entry. The client's name is marked verified only when its redirect URIs prove it, which covers Claude, ChatGPT, and Cursor among others. A client signing in through a loopback address, such as Claude Code or Codex CLI, shows the name it registered with, marked unverified. The distinction matters because an unverified client name is the name the client registered with, not one its redirect URIs prove. The value <code>ai_assistant</code> marks the in-app Elaichi Agent only, so do not expect it on an MCP client's call.</p>
<p>Each entry names the connection actually reached, taken from the execution rather than from the intent expressed in the tool call. That answers the first question after an unexpected change. Which of the two Notion workspaces did it actually write to, not which one the prompt seemed to ask for.</p>
<p>The approval line is stated in plain words on the entry rather than left for someone to reconstruct from scope lists. For an MCP call it reads "Allowed by the access the client was granted," because over MCP the OAuth grant <em>is</em> the approval. There is no separate in-the-moment approval step the way there is for a chat-window write gate. The trail is append-only and eventually consistent, so a row may take a moment to appear after the call completes. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> goes field by field.</p>
<h2 id="where-delegated-sign-in-stops">Where delegated sign-in stops</h2>
<p>Three limits apply.</p>
<p><strong>Sign-in needs a browser.</strong> Claude Code, or any client, running headless in CI or in a terminal with no browser cannot complete Elaichi's OAuth sign-in. Unattended jobs are not covered by the delegated pattern, so do not plan a nightly reconciliation job around it. That is what the named service identity pattern below is for.</p>
<p><strong>An organization API token resolves to the member who created it</strong>, so it carries that member's permissions and no more. It is not a separate, broader credential. It is created only from a browser session with a step-up approval. It reaches less than a browser session does, because several routes are human-session-only by design.</p>
<p><strong>The REST API has no route that runs a connected tool.</strong> Connected tools run over <code>POST /mcp</code> with a person's OAuth grant, or inside the Elaichi Agent, and a synthetic tool's execute route is owner-only. So "an agent with the employee's permissions" specifically means an MCP client holding that employee's own OAuth grant. It is not a long-lived token calling a REST endpoint on their behalf.</p>
<p>The prompt-injection write gate in the Elaichi Agent chat window does not apply to <code>POST /mcp</code>, and cannot. An MCP server never sees the user's prompt text. It only sees the tool call the client already decided to make. What holds on the endpoint instead is role checks per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits, and audit logging of each call that reaches execution. These are enforced regardless of what any client-side safety layer does or doesn't do.</p>
<h2 id="when-a-named-service-identity-is-still-the-right-answer">When a named service identity is still the right answer</h2>
<p>A job nobody is asking for in chat still needs an owner. Take a weekly team report, a recurring sync, or a workflow where one argument must never vary across runs. These are team-owned, not person-triggered. The honest shape for them is a named person who owns the connection. Not a bot account, and not a per-person grant, since there is no "person" triggering the call.</p>
<p>Set it up this way:</p>
<ol>
<li>Pick an owner who is staying, not a departing employee, not a contractor near the end of an engagement.</li>
<li>The owner connects the account and leaves that connection unshared with the team.</li>
<li>The owner pins it into a toolbox entry with the arguments frozen. That strips those keys from the advertised schema and merges the frozen values over whatever the model passes. So the model literally cannot override the frozen argument, not just "isn't supposed to."</li>
<li>The owner shares the toolbox at <code>use</code>.</li>
</ol>
<p>Grantees can now run the tool only through that entry. They cannot open, see, or share the underlying connection, and it is absent from their own tool set by design. One gap to watch: anyone who <em>also</em> independently holds <code>use</code> on that same connection can call the same tool unfrozen. That is exactly why the connection itself stays unshared rather than relying on a restriction to close the gap. A restriction will not help here. Restrictions resolve the called tool's identity at advertise and execute, toolbox entries included. So a block on the tool withholds the frozen entry too, defeating the point.</p>
<p>The owner vouches for the entry on every single call. If that person loses <code>use</code>, is removed, or is suspended through SCIM, the entry resolves as unmet for every grantee until someone re-pins it. The job doesn't silently fail open onto a different account, it stops. Offboarding is built around this. A private connection pinned by a toolbox its owner shared is marked as needing resolution. The person's removal is blocked until an administrator decides what happens to it. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Lock AI agent tool arguments, like a wire's payee</a> covers the freeze itself, and <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding AI access</a> covers the exit in full.</p>
<h2 id="when-you-do-not-need-this-pattern-at-all">When you do not need this pattern at all</h2>
<p>If three people use one app in one client, the app's own native MCP server is the shorter road. One exists for Notion, HubSpot and Slack among them. It runs under that app's own permission model, and each person signs in with their own account. There is no second vendor, no control plane, and no extra abstraction to buy or maintain. The pattern described in this post earns its keep specifically when the count rises on more than one axis at once. Several apps from several vendors. Several AI clients in use across the team. And a reviewer who wants one audit trail and one offboarding step instead of N separate ones per app.</p>
<p>It is also the wrong frame if the agent is a product you ship to customers rather than a tool your own employees use. Authorizing end users inside your own multi-tenant application is an authorization-library problem. Think an OAuth/OIDC provider plus a policy engine in your own stack, not a control-plane-for-internal-tools problem. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> draws that line more slowly.</p>
<p>For the architecture underneath all of this, start with <a href="/blog/what-is-an-mcp-control-plane/">the control plane explainer</a>. For how one role per member shapes the permission layer, read <a href="/blog/designing-roles-for-ai-agents/">designing roles for AI agents</a>. The 600+ apps a person can connect their own account to are listed in the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can an AI agent use an employee's own permissions instead of a shared service account?</strong></dt><dd>Yes, if the agent is an MCP client holding that employee's own OAuth grant. In Elaichi the AI client points at one organization-wide endpoint, the employee signs in once in a browser, and every call is then checked against that person's role, grant scopes and restrictions. No shared key exists, so no single identity holds the union of everyone's access.</dd><dt><strong>What happens to an AI agent's access when the employee leaves?</strong></dt><dd>In Elaichi, removal is the fast path: removing or suspending a member revokes every live grant in the same transaction as the membership change. A role or restriction change is slower, taking about two minutes. Removal ends access through Elaichi only; the person's account inside each SaaS app still has to be deprovisioned there.</dd><dt><strong>Does a shared connection give each person their own access to the app?</strong></dt><dd>No. A shared connection runs on its owner's credential, so every grantee's call reaches the app as that one account. To have the app see each person, share a template instead. Each member stamps their own toolbox from it, and stamping binds every entry to a connection that member can use, so the call runs on their own account.</dd><dt><strong>Can an API token run a connected tool on a user's behalf?</strong></dt><dd>No. In Elaichi the REST API has no route that runs a connected tool; connected tools run over the MCP endpoint with a person's OAuth grant, or inside the Elaichi Agent. An organization API token does resolve to the member who created it and carries that member's permissions, but it reaches less than a browser session does, because several routes are human-session-only.</dd><dt><strong>How do unattended jobs work if sign-in needs a browser?</strong></dt><dd>They do not use the delegated pattern. Any MCP client running headless in CI or in a terminal with no browser cannot complete Elaichi's OAuth sign-in. A recurring team-owned job instead needs a named owner who connects the account, leaves that connection unshared, pins it into a toolbox entry with frozen arguments, and shares the toolbox at use.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>governance</category>
    </item>
    <item>
      <title>How to approve apps for Claude across a company</title>
      <link>https://elaichi.ai/blog/approve-apps-employees-connect-to-claude/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/approve-apps-employees-connect-to-claude/</guid>
      <description>There are two places you approve apps for Claude: Anthropic&apos;s connector controls, and the restriction rules behind your one MCP endpoint.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> You approve apps for Claude in two places. Claude's own admin console decides which connectors exist in your organization, and on Team and Enterprise only Owners and Primary Owners add a custom one. Elaichi decides which company apps sit behind that single custom connector, using an allow rule written on a role, with access requests as the intake for everything else.</aside>
<h2 id="where-do-you-approve-apps-for-claude">Where do you approve apps for Claude?</h2>
<p>Finance asks for Xero in Claude. You switch something on. A month later somebody has connected a note-taking app nobody reviewed. There are two places you approve apps for Claude, and they answer different questions. Claude's own admin console decides which connectors exist in your Claude organization. Elaichi decides which company apps sit behind the one custom connector you added, and which tools inside them each role may reach.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A connector in Claude is an MCP server Claude is allowed to talk to. An app in Elaichi is a connected account: one Zendesk workspace, one Salesforce org, one Xero company file. Approving a connector and approving an app are different units of control, which is why one surface does not replace the other:</p>
<table>
<thead>
<tr>
<th></th>
<th>Claude admin console</th>
<th>Elaichi control plane</th>
</tr>
</thead>
<tbody>
<tr>
<td>Unit of approval</td>
<td>MCP server (connector)</td>
<td>Connected account (app), per role or per user</td>
</tr>
<tr>
<td>Granularity</td>
<td>Per tool or tool group, connector-wide</td>
<td>Per tool, per app, per role or per user, plus access grants for one person</td>
</tr>
<tr>
<td>Who can approve</td>
<td>Owner / Primary Owner (Enterprise: custom role with Libraries Manage)</td>
<td>Writing an allow rule needs <code>restriction:manage</code>; access requests are resolved with <code>member:manage</code></td>
</tr>
<tr>
<td>Default state</td>
<td>Off until added</td>
<td>Permissive until a restriction is written</td>
</tr>
<tr>
<td>Cross-client coverage</td>
<td>Claude only</td>
<td>Any MCP client pointed at the same endpoint (Claude, ChatGPT, Cursor)</td>
</tr>
<tr>
<td>Local/unmanaged servers</td>
<td>Out of scope (see below)</td>
<td>Out of scope</td>
</tr>
<tr>
<td>Revocation</td>
<td>Not documented by Anthropic (see below)</td>
<td>Documented: user-initiated or admin-initiated, logged</td>
</tr>
</tbody>
</table>
<p>This same two-surface pattern, client-level connector approval plus a server-side control plane for app-level and tool-level approval, applies to any MCP client, not just Claude. The specifics below are Claude's, but the pattern generalizes to ChatGPT, Cursor, or any other MCP-capable client pointed at the same custom connector.</p>
<h2 id="approving-connectors-inside-claude-team-and-enterprise">Approving connectors inside Claude Team and Enterprise</h2>
<p>In Claude Team and Enterprise, a connector stays off until an Owner adds it. Directory connectors are added by an Owner or Primary Owner at Organization settings, then Connectors, by browsing the directory and adding one to the team. Adding connects nobody. Each member still signs in to that connector with their own account (<a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">support.claude.com</a>, checked October 2026).</p>
<p>On Team, members have an intake path. A member sees a Request button on a directory connector. Owners find the pending ones under "Requested by your team" in Organization settings, Connectors, and on the Requests tab in Notifications, then enable or dismiss them (<a href="https://claude.com/docs/connectors/directory">claude.com/docs/connectors/directory</a>, checked October 2026). Anthropic's page does not say Enterprise members get the same button, so do not plan a rollout around it.</p>
<p>Custom connectors are narrower. A custom connector is a remote MCP server you point Claude at, which is what Elaichi's endpoint is. Owners and Primary Owners add one. On Enterprise, so can a custom role carrying Libraries (Manage). Ordinary members cannot add one; they connect and enable what was already added, and a Free account is limited to a single custom connector (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">support.claude.com</a>, checked October 2026).</p>
<p>Then there are tool permissions. Each connector's tools can be set to Always allow, Needs approval or Blocked, per tool or per group, set by Owners and binding on members. On Enterprise, custom roles narrow that further. Know one thing before planning per-app approval there: Elaichi's connected tools all run through a single tool called <code>execute_tool</code>, so a permission set on that one tool in Claude's console covers every connected app at once, undifferentiated. Claude's console cannot distinguish "allow Xero" from "allow Zendesk" once both sit behind the same custom connector. Per-app and per-tool approval for those apps has to happen in Elaichi, not in Claude's connector settings.</p>
<h2 id="what-claudes-connector-controls-do-not-reach">What Claude's connector controls do not reach</h2>
<p>Anthropic is explicit about the edge of these controls. Its guidance on custom roles says connector tool permissions "don't govern connectors a member runs locally on their own machine" (<a href="https://support.claude.com/en/articles/13930452-manage-custom-roles-on-enterprise-plans">support.claude.com</a>, checked October 2026). A server an engineer installed in a local config file sits outside the console entirely, and no Owner setting reaches it. Shrinking that population is a separate job, covered in <a href="/blog/replace-personal-mcp-servers/">replacing personal MCP servers on laptops</a>.</p>
<p>A second gap is worth putting to Anthropic directly. As of this writing, Anthropic's published docs do not state whether removing a connector revokes members' already-issued OAuth tokens for it or merely hides the connector from the UI going forward. Treat that as an open question, not a settled fact, until Anthropic documents it. Do not assume removal equals revocation. On the Elaichi side the behavior is written down. A person ends their own grant under Settings, then Connected apps. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="writing-the-approved-apps-list-in-elaichi">Writing the approved-apps list in Elaichi</h2>
<p>Behind the single custom connector, Elaichi starts permissive and you narrow it. Every organization uses one address, <code>https://api.elaichi.ai/mcp</code>, added once. A Member role holds <code>connection:create</code>, so with no restriction in place a member can connect any of the 600+ apps in the catalog using their own account. That is the right default for a pilot and the wrong one for a company of 300.</p>
<p>A restriction is a rule naming which connectors and which individual tools a target may reach. Targets are a role or a single user. There is no organization-level target, because the organization default is the absence of any rule, which means allow everything. So the approved-apps list is an allow rule written on the role. There is no separate "approved apps" object; the rule itself is the list.</p>
<p>Three properties decide whether the rule you write is the rule you meant:</p>
<ul>
<li>In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is easy to create by accident, for example by saving a rule before adding any entries to it.</li>
<li>An allow rule naming a connector whole reaches all of that connector and denies everything else. That is how an approved-apps list is written.</li>
<li>An allow rule naming a connector whole <strong>and</strong> some of its tools reaches all of that connector anyway. The tool entries grant nothing extra and read as tighter than they are. The API refuses that overlap on new rules, so it cannot be created going forward, but check existing rules for this pattern if they predate the validation.</li>
</ul>
<p>Within a layer, blocks union with blocks, allows union with allows, and blocks always beat allows. A member is under two layers at once: the rules on their role and the rules aimed at them. A connector or tool is reachable only when both layers admit it. So a rule aimed at one person can only narrow what the role allows. The same resolver runs everywhere a member can reach a connector or tool. Four of its checks decide most cases:</p>
<ol>
<li><strong>Browse</strong>: what the member sees when listing available connectors and tools.</li>
<li><strong>Connect</strong>: whether the member is permitted to link an account to a given app.</li>
<li><strong>Advertise</strong>: whether the tool is included in the schema Claude's model actually sees.</li>
<li><strong>Execute</strong>: whether a specific call is allowed to run.</li>
</ol>
<p>A final check on the outbound URL runs independently of those four. A tool withheld at the advertise step is left out of the tool list and cannot be called. Search names it, flagged restricted, with no schema. For the split between allowing an app whole and allowing single tools, see <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool or the whole app</a>.</p>
<p>A role or restriction change takes effect within about two minutes. Plan a change window of a few minutes, then verify with a test account before telling the requester it's done.</p>
<p>Write blocks and allows knowing they match differently. A block matches the tool's advertised name or the operation pinned at write time. An allow matches the pinned operation only. A tool's advertised name can be changed by whoever edits the connector's documentation, so governance binds the operation, never the label. A rename should not silently reopen something you blocked. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match names and allows do not</a>.</p>
<h2 id="whose-account-does-an-approved-app-run-on">Whose account does an approved app run on?</h2>
<p>Approving the app is half the decision. The other half is whose credential the calls run on. When each person connects their own account, the app's own permission model stays in play, and the audit trail inside that app names the right person. A shared connection runs on its owner's credential, so every call through it reaches the app as that one account, regardless of who initiated the call from Claude.</p>
<p>If one argument has to be fixed for a whole team, say a specific wire-transfer receiver, a specific Slack channel or a specific cost-center ID, a restriction is the wrong instrument, because a restriction only decides reachability, not argument values. Use frozen parameters on a toolbox entry instead. Frozen keys are stripped from the advertised schema, so the model cannot fill them in. It can see short frozen values in the tool description, but it cannot change them, and frozen values are merged over whatever the caller passes, after the fact. Precedence runs: entry defaults, then caller arguments, then frozen parameters. Frozen always wins last.</p>
<p>The freeze holds only on the path that runs through the entry. So the owner leaves the connection unshared, pins it into a toolbox entry with the frozen values, and shares the toolbox at <code>use</code>. Grantees run the tool only through that entry. Anyone who also holds <code>use</code> on the connection itself can still call the same tool unfrozen, through the raw connection. Closing that second path with a restriction does not work, because a block would withhold the frozen entry too, not just the raw path. The worked example is in <a href="/blog/frozen-parameters-wire-transfer-receiver/">locking an agent's tool arguments</a>.</p>
<h2 id="access-requests-as-the-intake-for-the-next-app">Access requests as the intake for the next app</h2>
<p>Access requests are Elaichi's version of Claude's Request button, and they work across every connected app, not just directory ones. Any member can file one, with no permission needed to ask. Resolving one needs <code>member:manage</code>, and an admin cannot decide their own request. That is a hard rule, not a convention.</p>
<p>An admin decides a request in the console, under Governance, then Access requests, with a step-up check. Approving a request creates an access grant for that one person. The grant lifts exactly the approved connector or tool out of their role rules. Every other role rule still binds them, nobody else on the role changes, and no rule is written. The grant is standing, not a one-time pass. It lasts until the member is removed or an admin approves a replacement.</p>
<p>Two limits belong in your runbook. First, neither an MCP client nor the Elaichi Agent can approve or deny a request from inside a chat. Nobody approves their own request either. Second, when the request names an app Elaichi does not carry, such as GitHub, Datadog, Linear, or any app outside the catalog, the answer is different: either the app's own MCP server, or a custom connector pointed at it. Keep <code>connector:create</code> on roles you already gate carefully, because a custom connector can be pointed at any destination, including ones you did not intend.</p>
<h2 id="the-record-of-what-was-approved-and-used">The record of what was approved and used</h2>
<p>The audit trail turns an approval into evidence. An audit log here is an append-only record of actions.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), not just successful calls. The entry also records the surface the call came through and the OAuth client it came from, with the client's name marked verified only when its registered redirect URIs prove it. Claude is among the clients that verify.</p>
<p>Approval is stated in plain words on the entry. For example, "Allowed by the access Claude was granted" for a call over MCP, or "Didn't need approval because it only read data." That sentence, read next to your allow rule, is the before-and-after pair a reviewer wants: the rule as written, and the system's own statement of why a specific call was or wasn't let through. Give the reviewer the free read-only Auditor seat rather than an admin login. They need to read the trail, not change the rules. More on what belongs in those records: <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="a-checklist-to-run-for-each-new-app">A checklist to run for each new app</h2>
<p>Run this once per app request, in order. It takes a few minutes and it survives a change of admin.</p>
<ol>
<li><strong>Name the app and check the catalog.</strong> If Elaichi does not carry it, decide between the app's own MCP server and a custom connector before anything else.</li>
<li><strong>Decide whose account it runs on.</strong> Per-person connections keep the app's own permissions in play. A shared connection reaches the app as its owner, for every caller.</li>
<li><strong>Decide app-wide or tool-level.</strong> Allow the connector whole when the whole app is approved. Do not mix a whole-connector entry and tool entries in one allow rule. The API will reject the overlap.</li>
<li><strong>Write the rule on the role.</strong> A rule aimed at one person can only narrow what their role allows. Use it to give one person less. Give one person more through an access request.</li>
<li><strong>Verify what a member sees.</strong> Wait about two minutes for the change to take effect, then check the tool list from a test account on that role. A withheld tool is missing from the tool list, so there is no error to spot and you have to check directly. Search still names it, flagged restricted. The other reasons a tool goes missing are in <a href="/blog/mcp-tools-not-showing/">the missing-tool checklist</a>.</li>
<li><strong>Leave access requests as the intake.</strong> The next app should arrive as a request you decide on, not as a connection you discover later in an audit log.</li>
<li><strong>Name the reviewer.</strong> Decide who reads the audit trail each month, and give them the Auditor seat, not an admin login.</li>
</ol>
<h2 id="when-one-approval-surface-is-enough">When one approval surface is enough</h2>
<p>If your company runs Claude and nothing else, and the approved list is one or two SaaS tools that ship their own MCP servers, Anthropic's directory and tool permissions are the whole job. A second control plane buys you nothing yet. The case for a control plane like Elaichi starts when the same approval has to hold across Claude, ChatGPT and Cursor at once, when the number of approved apps is large enough that per-connector console toggles stop scaling, or when a leaver's access through the endpoint has to end for every connected app in one action. That threshold is argued in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you do not need an MCP gateway yet</a>.</p>
<p>For the shape of the thing behind the single custom connector, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For the rollout order across clients, see <a href="/blog/roll-out-claude-and-chatgpt-to-employees/">how to roll out Claude and ChatGPT to employees</a>, and for the setup itself, <a href="/blog/connect-elaichi-to-claude/">connecting Elaichi to Claude</a>. To check which apps are already covered before you write the allow rule, browse the <a href="/connectors/">connector catalog</a> and the <a href="/use-cases/">team use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Who can add a custom connector in Claude Team and Enterprise?</strong></dt><dd>Owners and Primary Owners add a custom connector, which is how a remote MCP server such as Elaichi's endpoint gets into a Claude organization. On Enterprise, a custom role carrying Libraries (Manage) can also add one. Ordinary members cannot add a custom connector; they connect to and enable what was already added (support.claude.com article 11175166, checked October 2026).</dd><dt><strong>How do I stop employees connecting apps we have not approved?</strong></dt><dd>In Elaichi, a member with no restriction in place can connect any app in the catalog with their own account. To limit that, write an allow rule on the member's role naming each approved connector whole. The presence of an allow rule turns on the allowlist, so everything not named is denied. The change takes effect within about two minutes.</dd><dt><strong>What does an allow rule that names nothing do?</strong></dt><dd>It denies everything. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is easy to create by saving a rule before adding any entries to it.</dd><dt><strong>How long does a restriction change take to apply?</strong></dt><dd>Within about two minutes. Role changes and restriction changes in Elaichi resolve through a short cache, on every surface, so they are not immediate and not applied on the next call. Grant revocation, member removal and suspension are different: they take effect on the caller's very next request, as does revoking a share or disconnecting an account.</dd><dt><strong>Do Claude's per-tool permissions control which company apps an employee can reach through Elaichi?</strong></dt><dd>Not individually. Elaichi's connected tools are all called through a single tool named execute_tool, so a Claude tool permission set to Always allow, Needs approval or Blocked on that one tool applies to every connected app at once. Per-app and per-tool approval for those apps is written as a restriction in Elaichi instead.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>setup</category>
    </item>
    <item>
      <title>Approved AI tools per team, set by role</title>
      <link>https://elaichi.ai/blog/approved-ai-tools-per-team/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/approved-ai-tools-per-team/</guid>
      <description>Approved AI tools per team is two jobs: restrictions bound to a role for enforcement, and templates shared to a team for curation.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, approved AI tools per team are enforced with restrictions bound to a role, not a team, because a restriction targets a role or a user only and each member holds exactly one role. Curation is separate: a template shared with a team at use, which each member stamps into their own toolbox on their own connected accounts. Map identity-provider groups to roles, write one allow rule set per role, and handle the exceptions as access requests. A restriction change takes effect within about two minutes.</aside>
<h2 id="why-does-every-team-reach-the-whole-catalog-by-default">Why does every team reach the whole catalog by default?</h2>
<p>Because the absence of a rule means allow-all. A head of IT connects Elaichi and <a href="/blog/roll-out-claude-and-chatgpt-to-employees/">points Claude, ChatGPT and Cursor at one address</a>. Sales, support, engineering and finance all sign in to the same place. With no restriction written, a member can connect any catalog app with their own account. Approved AI tools per team is therefore something you write down, not something you inherit.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected account through one organization-wide MCP endpoint, and each member signs in there with their own OAuth grant. OAuth is the browser sign-in that issues a scoped token instead of handing over a password. The catalog behind that endpoint holds 600+ connectors. No team needs all of them. Four teams typically need four different slices of them. Sales needs CRM and email. Finance needs the accounting suite and nothing with write access to it. Engineering needs the issue tracker and source control. Support needs the helpdesk and nothing else.</p>
<p>The problem is not specific to Elaichi. Any shared endpoint that several teams sign in to needs a written rule before those teams reach different things. The rest of this post sets out the general framework, then how Elaichi implements it.</p>
<h2 id="the-general-framework-enforcement-and-curation-are-two-different-jobs">The general framework: enforcement and curation are two different jobs</h2>
<p>This distinction holds regardless of which platform you're on:</p>
<ul>
<li><strong>Enforcement</strong> is a restriction bound to an identity (a role or a user). It determines what is <em>reachable</em> at all.</li>
<li><strong>Curation</strong> is what a person <em>picks</em> from whatever enforcement left reachable. It determines what is <em>convenient</em>, not what is <em>possible</em>.</li>
</ul>
<p>A restriction decides which connectors and which individual tools a target may reach. In Elaichi it is checked against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A tool a role cannot reach is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. That holds whichever client the person is using: Claude, ChatGPT, Cursor, or a custom agent.</p>
<p>Curation is softer by design. A template is a tool list someone assembled for a team. The consent-screen choice between "All my tools" and "Only the ones I pick" is the person's own scoping. Neither stops anybody from reaching something else they are already allowed to reach. Treat a curated toolbox as a control and the approved-apps plan stops being one. A toolbox changes what shows up in a menu, not what the model can call.</p>
<h2 id="how-to-write-approved-ai-tools-per-team-as-allow-rules">How to write approved AI tools per team as allow rules</h2>
<p>A role's approved-apps list is its allow rules, and naming whole connectors is fine. Allow rules on the same role union, so one allow rule per app works. The role's allowlist is all of its allow rules together.</p>
<p>The trap: an allow rule is the target's <em>whole</em> allowlist, across every connector, not an incremental grant layered on top of some implicit baseline. Once the sales role holds an allow rule naming Salesforce, every connector and tool that role's rules do not name is denied for that role. That is the behavior you want from an approved-apps list, as long as you name every app the team uses. Miss one and the team loses it silently, with no error, because "not listed" and "denied" are the same state.</p>
<p><strong>Worked example.</strong> Say the sales role needs Salesforce, Gmail, and Slack, and nothing else:</p>
<table>
<thead>
<tr>
<th>Rule on sales role</th>
<th>Effect</th>
</tr>
</thead>
<tbody>
<tr>
<td>Allow: Salesforce (whole connector)</td>
<td>Sales reaches every Salesforce tool</td>
</tr>
<tr>
<td>Allow: Gmail (whole connector)</td>
<td>Sales reaches every Gmail tool</td>
</tr>
<tr>
<td>Allow: Slack (whole connector)</td>
<td>Sales reaches every Slack tool</td>
</tr>
<tr>
<td>(no rule for QuickBooks, Jira, etc.)</td>
<td>Sales reaches nothing in any unlisted connector</td>
</tr>
</tbody>
</table>
<p>Three allow rules, unioned, form the complete list. Add a fourth app later and sales gains it within about two minutes of the rule being saved. Forget to add it and sales never sees it, with no visible error on either side.</p>
<p>Two more mechanics decide how the first rule behaves:</p>
<ul>
<li>An allow rule naming connector X whole, plus some of X's tools, reaches all of X. The tool entries grant nothing extra. The API refuses that overlap on new rules, so you can't accidentally create a rule that looks more specific than it is.</li>
<li>An allow rule naming nothing denies everything. It is the strictest rule you can express.</li>
</ul>
<p>Holding one app to its read tools is a different move once the role already has an approved-apps list. Allow rules on one role union. So if finance's allow rules name QuickBooks whole, a second allow rule naming only its read tools changes nothing. The union still reaches all of QuickBooks. To hold QuickBooks to reads, name its read tools in place of the whole connector, or keep the whole-connector allow and put blocks on its write tools. Blocks union with each other, and blocks always beat allows regardless of which rule was written first. Which writes to block is a question a pilot's own call record answers, and <a href="/blog/least-privilege-tool-calls-without-breaking-automation/">narrowing to the tools people actually used</a> keeps that list honest.</p>
<p>The two rule types also match differently. A block matches on the tool name <em>or</em> on the operation pinned against the catalog at write time. An allow matches on the pinned operation only. Whoever edits a connector's documentation can change an advertised tool name. So allows bind the operation rather than the label, and a rename cannot widen what an allow reaches. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks match tool names but allows do not</a> covers that asymmetry, and <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool against restricting the whole app</a> works through six cases.</p>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</p>
<h2 id="which-identity-provider-group-maps-to-which-role">Which identity-provider group maps to which role?</h2>
<p>Map each team's group to its own role. The reason is that restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A SCIM group mapping can confer at most one role, and a member holds exactly one role, enforced by a unique index. SCIM (System for Cross-domain Identity Management) is the provisioning standard your identity provider uses to push users and groups into an application.</p>
<p>So the shape is one role per team persona: a sales role, a support role, an engineering role, a finance role. Each is a complete persona rather than a bolt-on, which is the point of the one-role-per-member rule. It is also the main design constraint to plan around. Custom roles are a Gold-tier feature, so check <a href="/pricing/">pricing</a> before planning a role structure that depends on them.</p>
<p>Verified domains and SSO connections each carry a configurable default role, and domain, SSO and SCIM joins fall back to Member when none is set.</p>
<p>Team membership is set separately from role. SCIM and group mapping never set team membership. People who join by SCIM, domain or SSO are added to teams afterward, and invites can preset teams. Teams matter for sharing (templates, toolboxes), not for enforcement (allow/block rules). A SCIM deprovision suspends the member rather than removing them, which revokes every live grant immediately. Removal is a separate step an admin takes in Elaichi afterward. <a href="/blog/identity-provider-scim-vs-mcp-grants/">SCIM and AI agents</a> covers where provisioning stops and manual admin action starts.</p>
<h2 id="how-does-each-person-get-a-curated-list-on-their-own-accounts">How does each person get a curated list on their own accounts?</h2>
<p>Share a template with the team at use, and let each member stamp it. Stamping creates that person's own toolbox. Each entry is bound to a connection that person can use, with them recorded as the delegator. An entry with no usable connection is left as "needs connection" rather than failing silently.</p>
<p><strong>Worked example.</strong> The sales lead builds a template called "Sales Outreach" with five Salesforce tools, three Gmail tools, and two Slack tools, each with sensible defaults. The lead shares it with the Sales team. Each rep stamps it:</p>
<ol>
<li>Rep A has already connected their own Salesforce and Gmail accounts, so all ten entries bind to Rep A's own connections.</li>
<li>Rep B has connected Gmail but not Salesforce yet, so the five Salesforce entries sit as "needs connection" until Rep B connects.</li>
<li>The template itself never holds a connection; only each stamped copy does.</li>
</ol>
<p>A template holds a tool list with renames, defaults and frozen parameters, and it never holds a connection itself. Stamping copies the list once, so editing the template later does not change a toolbox already stamped. Re-share and re-stamp when the list changes.</p>
<p>Do not pair "each person connects their own account" with "share one toolbox." A toolbox shared at use is the opposite arrangement. Every grantee's call runs on the connection pinned in its entries, which is the <em>owner's</em> account, not the grantee's. That's correct when one account should serve a whole team (a shared support inbox, a shared CRM user). It is wrong when each rep should reach only their own records.</p>
<p>A frozen argument inside a stamped toolbox is not a control over the person who stamped it. A freeze holds only on the path that runs through that entry. Anyone holding direct "use" on the underlying connection can call the same tool unfrozen. Locking an argument for a team requires an unshared connection, pinned into a toolbox by its owner and shared at use. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking AI agent tool arguments</a> sets out the mechanism, such as freezing a wire-transfer receiver account number so no rep can redirect funds.</p>
<p>On the consent screen, a member who ticks "Run your connected tools" gets a second step. "All my tools" is the default. It picks up accounts they connect later and connections shared with them later, so it is a live, expanding grant rather than a snapshot. "Only the ones I pick" narrows the grant to chosen toolboxes, up to 50. If none of those toolboxes resolves any more, say because the underlying connection was revoked, the client sees no connected tools. There is never a silent fallback to everything.</p>
<p>The consent checkboxes do not make a connected app read-only. For a connected app's tools, "run your connected tools" covers reads and writes alike; only a delete action costs an extra destructive-action scope. Read-only access to an app is achieved through a restriction (a block on write tools), not through consent-screen choices.</p>
<h2 id="what-happens-when-finance-asks-for-an-app-outside-the-list">What happens when finance asks for an app outside the list?</h2>
<p>It becomes an access request. Any member can file one with no permission needed; resolving one needs <code>member:manage</code>, the permission that covers managing people.</p>
<p>Approving a request creates an access grant for <em>that one requester only</em>. The grant lifts exactly the approved connector or tool out of their role rules. The role's other rules still bind them, and the rest of the team is unaffected. No rule is written, and the role is not edited. The grant lasts until the member is removed or an admin approves a replacement. An admin cannot approve their own request. The Elaichi Agent and MCP clients can neither approve nor deny a request. An admin decides it in the console, under Governance, then Access requests.</p>
<p><a href="/blog/human-approval-for-ai-agent-actions/">Human approval for AI agent actions</a> sets out the other approval layers, such as per-call approval for destructive actions, independent of access requests.</p>
<p>Time it accordingly: an approval, like any restriction change, takes effect within about two minutes. A team membership change sits in the same bucket. Removal is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="when-are-claude-and-chatgpt-approval-lists-enough-on-their-own">When are Claude and ChatGPT approval lists enough on their own?</h2>
<p>When you run exactly one AI client and its own approval settings give the granularity you need. Both vendors ship that natively, and it is less setup than a separate control plane. The trade-off is granularity and cross-client consistency.</p>
<table>
<thead>
<tr>
<th></th>
<th>Claude (Team/Enterprise)</th>
<th>ChatGPT (Enterprise/Edu)</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Granularity</td>
<td>Per-connector or per-tool: Always allow / Needs approval / Blocked</td>
<td>Per-app on/off; per-app read vs. write actions</td>
<td>Per-connector or per-tool, per role or per user</td>
</tr>
<tr>
<td>Per-team policy</td>
<td>Enterprise custom roles narrow tool permissions further</td>
<td>Yes, via custom roles (Enterprise/Edu only)</td>
<td>Yes, one role per team persona</td>
</tr>
<tr>
<td>Multi-client consistency</td>
<td>Applies only within Claude</td>
<td>Applies only within ChatGPT</td>
<td>Same rule applies across Claude, ChatGPT, Cursor, and any MCP client</td>
</tr>
<tr>
<td>Who configures it</td>
<td>Owners and Primary Owners</td>
<td>Workspace admin</td>
<td>An admin holding <code>restriction:manage</code></td>
</tr>
</tbody>
</table>
<p>Sources: Claude tool permissions (<a href="https://support.claude.com/en/articles/13930452-manage-custom-roles-on-enterprise-plans">support.claude.com</a>, checked October 2026); ChatGPT role-based access control (<a href="https://help.openai.com/en/articles/11750701-managing-feature-access-with-role-based-access-control-in-chatgpt">help.openai.com</a>, checked October 2026); ChatGPT per-app read and write actions (<a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">help.openai.com</a>, checked October 2026).</p>
<p>Two things change the moment a second AI client appears in the organization. First, approvals don't transfer. The same person reaches the same underlying data under two independently-configured lists, one per client. Keeping them in sync is manual. Second, to ChatGPT, a control plane like Elaichi looks like one custom app. Its tools are <code>search_tools</code>, <code>execute_tool</code>, and its own operations. So ChatGPT's per-action switches can toggle the control plane on or off as a whole. They cannot distinguish which <em>catalog</em> app behind it a call is targeting. Per-app and per-tool approval for the apps behind that single connector has to be written in the control plane itself, not in ChatGPT's admin panel.</p>
<p>For the client-side path on its own, without a control plane, there are standalone guides for <a href="/blog/approve-apps-employees-connect-to-claude/">approving apps in Claude</a> and <a href="/blog/restrict-chatgpt-enterprise-connectors/">restricting ChatGPT Enterprise connectors</a>.</p>
<h2 id="the-honest-part-the-role-binds-not-the-team">The honest part: the role binds, not the team</h2>
<p>Restrictions bind a role or a single user. They do not bind a team. A team is a sharing construct, which is why templates go to teams and allow rules go to roles.</p>
<p>That split has a practical consequence. If two people sit on the same team but hold different roles, they reach different apps. A shared template then stamps differently for each. One person's stamped entries might resolve to real connections, while the other's sit at "needs connection" because their role never granted that app. If one person needs a wider list than their role allows, the clean answer is an approved access request, which creates an access grant for that one person. A rule aimed at that person cannot help, because it can only narrow what their role allows. A second role is not an option, since a member holds exactly one role. Design the four roles first and the four teams second. Retrofitting roles after teams are already full of mixed-permission members is the harder order to untangle.</p>
<p>From here: the <a href="/blog/what-is-an-mcp-control-plane/">MCP control plane overview</a> explains the endpoint these rules sit on. <a href="/blog/designing-roles-for-ai-agents/">Designing roles for AI agents</a> covers the one-role constraint in depth. The <a href="/connectors/">connector catalog</a> is where you check that the apps a team wants are ones Elaichi already serves.</p>
<h2>FAQ</h2><dl><dt><strong>Can an Elaichi restriction target a team?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Because each member holds exactly one role, the usual pattern is to map each identity-provider group to its own role and write that role's approved-apps list as allow rules. Teams are used for sharing templates and connections, not for enforcement, and team membership is set separately from SCIM or group mapping.</dd><dt><strong>How do you give one team read-only access to a single app?</strong></dt><dd>It depends on whether the role already has allow rules. If the role has none, put block rules on that app's write tools, because an allow rule naming only its read tools would become the role's entire allowlist across every connector and the role would lose its other apps. If the role already has an approved-apps list of allow rules, name that app's read tools in place of the whole connector, or keep the whole connector and block its write tools. Blocks always beat allows.</dd><dt><strong>How long does a restriction or role change take to apply in Elaichi?</strong></dt><dd>Within about two minutes. Role membership, restrictions and team membership all resolve the same way, on MCP, the console and the REST API alike. Some changes are faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Should a team share one toolbox or one template?</strong></dt><dd>Share a template when each person should run on their own connected account. A template holds a tool list and never holds a connection, and a member who holds use on it stamps their own toolbox, with each entry bound to a connection they can use. Share a toolbox instead when the team should run on one account: every grantee's call then runs on the connection pinned in that toolbox's entries, which belongs to its owner.</dd><dt><strong>What happens when someone requests an app that their role does not allow?</strong></dt><dd>They file an access request, which any member can do with no permission needed. Resolving it requires the member:manage permission, and an admin cannot decide their own request. Approving a request creates an access grant for that one requester. The grant lifts exactly the approved connector or tool out of their role rules. Every other role rule keeps applying, and nobody else on the role changes.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>governance</category>
    </item>
    <item>
      <title>Space permissions for Confluence in ChatGPT</title>
      <link>https://elaichi.ai/blog/chatgpt-confluence-space-permissions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/chatgpt-confluence-space-permissions/</guid>
      <description>ChatGPT ships no Confluence connector, so Confluence in ChatGPT runs over MCP. Here is the route that keeps each person inside their space permissions.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> ChatGPT has no Confluence connector of its own, so Confluence in ChatGPT runs over an MCP server. Atlassian's own remote server covers Atlassian products for one client. Elaichi serves a Confluence connector through one organization-wide MCP endpoint, where each member connects their own Confluence account from a shared template, so space roles and page restrictions follow the person.</aside>
<h2 id="why-confluence-in-chatgpt-takes-a-second-step">Why Confluence in ChatGPT takes a second step</h2>
<p>Someone asks ChatGPT what the incident runbook says, and ChatGPT has nothing to read. Confluence is not one of ChatGPT's built-in synced sources: those are Google Drive, SharePoint and Teams only (<a href="https://help.openai.com/en/articles/10847137-administrator-managed-apps-with-sync-in-chatgpt">help.openai.com</a>, checked October 2026). To reach Confluence, ChatGPT has to go through MCP. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>Two routes implement that for Confluence. Atlassian runs its own remote MCP server, surfaced in ChatGPT as the "Atlassian Rovo" app. Elaichi serves a <a href="/connectors/confluence/"><code>confluence</code> connector</a> through one organization-wide MCP endpoint, alongside the rest of a catalog of 600+ connectors. Both can preserve a person's own space permissions when configured correctly. They differ on how many apps and how many AI clients one setup covers, and on what a security team can see and restrict afterward. The comparison is laid out below.</p>
<p>The requirement that decides between them is blunt. A person with no access to the Security space must not read its pages through an assistant. That holds only when every call runs with that person's own Confluence identity, not a shared one.</p>
<table>
<thead>
<tr>
<th></th>
<th>Atlassian Rovo MCP</th>
<th>Elaichi <code>confluence</code> connector</th>
</tr>
</thead>
<tbody>
<tr>
<td>Endpoint</td>
<td><code>https://mcp.atlassian.com/v2/mcp</code>, Atlassian-hosted</td>
<td><code>https://api.elaichi.ai/mcp</code>, one endpoint for the whole app catalog</td>
</tr>
<tr>
<td>Supported clients</td>
<td>ChatGPT, Claude (named by Atlassian)</td>
<td>Any MCP-capable client, including ChatGPT</td>
</tr>
<tr>
<td>Apps covered</td>
<td>Atlassian products only (Confluence, Jira, etc.)</td>
<td>Confluence plus the rest of 600+ connectors behind one endpoint</td>
</tr>
<tr>
<td>Identity model</td>
<td>Per-user OAuth 2.0 (3LO); "never grants access beyond what the user already has"</td>
<td>Per-user OAuth via template stamping, or OAuth client credentials for a shared service identity</td>
</tr>
<tr>
<td>Tool-level control</td>
<td>Read, Write and Search toggles per app</td>
<td>Per-tool and per-app allow/block rules per role</td>
</tr>
<tr>
<td>Usage cost</td>
<td>Some search calls cost 1 to 10 Rovo credits; single-product lookups and writes are free</td>
<td>Per seat on Elaichi's plan; no per-call charge</td>
</tr>
<tr>
<td>Admin kill switch</td>
<td>Domain allowlist and Read/Write/Search toggle; no single "turn off MCP server" control documented</td>
<td>A restriction change takes effect within about two minutes; disconnecting an account takes effect on the caller's next request</td>
</tr>
</tbody>
</table>
<h2 id="how-do-confluence-space-permissions-survive-the-hop">How do Confluence space permissions survive the hop?</h2>
<p>They survive when the connection is per person and the sign-in is OAuth. OAuth is the sign-in flow where someone approves an app in the browser and no password or API key is copied anywhere. Atlassian is explicit that OAuth 2.0 (3LO) apps act on a user's behalf, and that "Confluence permissions also control access to data and aren't overridden by scopes" (<a href="https://developer.atlassian.com/cloud/confluence/scopes-for-oauth-2-3LO-and-forge-apps/">developer.atlassian.com</a>, checked October 2026). A broad scope does not widen what someone can see. A call made with a person's own credentials sees what that person sees in the browser, and nothing else.</p>
<p>That matters because Confluence permissions are not flat. Space roles (Admin, Manager, Collaborator, Viewer, plus custom roles) decide who works in a space. A page-level view restriction hides a page even from people who hold space view (<a href="https://support.atlassian.com/confluence-cloud/docs/what-are-confluence-cloud-permissions-and-restrictions/">support.atlassian.com</a>, checked October 2026). On Premium and Enterprise, an organization admin can still override page restrictions with an admin key. That is the one documented exception to "the viewer sees only their own permissions."</p>
<p>In Elaichi, per-person identity comes from a template, not from a shared toolbox. This is Elaichi-specific mechanics, not an Atlassian concept. A template holds a tool list with overrides and defaults, and never holds a connection itself. Share it with the team at <code>use</code>, and each member stamps their own toolbox from it. Stamping binds each entry to the stamper's own Confluence connection, so every call reaches Confluence as that member, under that member's space roles. The same pattern, applied to a CRM, is written out in <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the per-rep Salesforce rollout</a>.</p>
<p>Sharing one toolbox does the opposite. A shared connection runs on its owner's credential, so every call lands as that single account, and space roles stop following the person. Elaichi's <code>confluence</code> connector also accepts OAuth client credentials, which sign in as one identity for everyone who uses it: useful for a scripted or scheduled job, wrong for a human reading team. Rule of thumb: client credentials for a scheduled job that should run as one service identity; per-person OAuth wherever space permissions should follow the person.</p>
<h2 id="when-is-atlassians-own-mcp-server-enough">When is Atlassian's own MCP server enough?</h2>
<p>It is enough when one AI client talks to Atlassian products and nothing else. Atlassian's remote MCP server sits at <code>https://mcp.atlassian.com/v2/mcp</code> and "never grants access beyond what the user already has" (<a href="https://developer.atlassian.com/cloud/rovo-mcp/">developer.atlassian.com</a>, checked October 2026). It has been generally available since 4 February 2026 (<a href="https://www.atlassian.com/blog/announcements/atlassian-rovo-mcp-ga">atlassian.com</a>, checked October 2026). It names ChatGPT and Claude as supported clients (<a href="https://support.atlassian.com/atlassian-ai-gateway/docs/get-started-with-the-atlassian-remote-mcp-server/">support.atlassian.com</a>, checked October 2026). It is open to all Atlassian Cloud customers with hourly call limits by plan (<a href="https://www.atlassian.com/platform/rovo-mcp">atlassian.com</a>, checked October 2026). It can create and update Confluence pages (<a href="https://support.atlassian.com/atlassian-ai-gateway/docs/supported-tools/">support.atlassian.com</a>, checked October 2026). Some search calls cost 1 to 10 Rovo credits each, while single-product lookups and writes are free (<a href="https://support.atlassian.com/rovo/docs/rovo-usage-limits/">support.atlassian.com</a>, checked October 2026).</p>
<p>The admin controls are real, not theoretical. Under Atlassian Administration, then Rovo, then Rovo MCP server, an admin allows or blocks Atlassian's default domain list as a whole, and that list includes chatgpt.com. Your own domains can be added, and API tokens turned on or off (<a href="https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-mcp-server-settings/">support.atlassian.com</a>, checked October 2026). A Permissions tab turns Read, Write and Search on or off per app, and overrides Connected apps settings (<a href="https://support.atlassian.com/security-and-access-policies/docs/configure-atlassian-mcp-server-permissions/">support.atlassian.com</a>, checked October 2026). No documented single switch turns the whole server off.</p>
<p>Two broader Atlassian controls sit underneath that. "Block user apps," under Connected apps, is available on every plan, and user-installed apps are allowed by default (<a href="https://support.atlassian.com/organization-administration/docs/installing-and-managing-app-access/">support.atlassian.com</a>, checked October 2026). The policy now called "Marketplace and custom app access" blocks all apps on any plan, but choosing which specific apps to allow back in requires Atlassian Guard Standard or Premium (<a href="https://support.atlassian.com/security-and-access-policies/docs/block-app-access/">support.atlassian.com</a>, checked October 2026). Budget for that licensing tier before planning an allowlist. It is a real cost of the "allow specific apps" path, not a footnote.</p>
<p>The decision point is concrete, not a matter of preference: if the tools in scope are only Confluence and Jira, and ChatGPT is the only client reading them, Atlassian's server plus its native Read/Write/Search toggle and domain allowlist are sufficient. There is no permission gap for an aggregator to close. The case for a second endpoint shows up once any of these is true: a second AI client is in play (Claude plus ChatGPT, say), the same team also needs Zendesk, Slack or Salesforce behind the same assistant, you want one restriction written per role instead of one per app's native console, or you want one audit query that spans tools instead of stitching logs from each vendor's admin panel by hand. Outside those conditions, <a href="/blog/when-you-dont-need-an-mcp-gateway/">a gateway you do not need yet</a> adds an endpoint to secure without closing a gap that existed.</p>
<h2 id="which-of-the-18-confluence-tools-should-a-reading-team-keep">Which of the 18 Confluence tools should a reading team keep?</h2>
<p>Keep the 15 reads and block the 3 writes. Elaichi's <code>confluence</code> connector carries 18 tools (live catalog, read October 2026). The reads cover pages, spaces, CQL search, attachments, labels, users, groups, a user's groups, accessible resources, the signed-in user, and <code>list_all_confluence_audit_logs</code>.</p>
<p>The writes are <code>create_a_confluence_page</code>, <code>update_a_confluence_page_by_id</code> and <code>confluence_groups_remove_member</code>. The update tool does more than edit text: it can move a page under another parent, transfer its owner, and restore a trashed page, any of which changes who can see what afterward. The group-removal tool is a delete that removes a user from a Confluence group, an admin-level action no ordinary reading role needs. The same shape of decision, applied to contracts, is worked through in <a href="/blog/legal-team-chatgpt-ironclad-contracts/">the Ironclad playbook for legal</a>.</p>
<p>Write this as blocks on a role, not as an allow rule. An allow rule is that role's entire allowlist across every connector the role touches, so naming only Confluence read tools in one would silently deny Zendesk, Slack and everything else the role uses, a side effect that is easy to miss until someone reports a missing tool weeks later. Blocks on the three writes leave the rest of the role's apps untouched. Blocks also match on the tool name or the pinned operation, which is why <a href="/blog/block-matches-name-allow-matches-operation/">a block holds when a tool is renamed</a>. The general choice between a tool-level block and an app-level block is laid out in <a href="/blog/per-tool-vs-per-app-restrictions/">six worked cases</a>.</p>
<p>Do not try to get the same result from ChatGPT's own per-action switches. To ChatGPT, Elaichi is one custom app whose tools are <code>search_tools</code>, <code>execute_tool</code> and Elaichi's own operations, because connected tools are never listed one by one, however few there are. So ChatGPT's per-action switches cannot tell one connected app or tool behind it from another. The only place "read-only Confluence, except for this one admin" can be expressed precisely is inside Elaichi's restriction layer, not inside ChatGPT's settings.</p>
<h2 id="setting-it-up-in-the-order-that-works">Setting it up, in the order that works</h2>
<p>Decide the Atlassian side first, then ChatGPT, then the restriction, then the people. Each step is short, and the order avoids a half-connected team where some members have stamped a template and others are still sharing one account.</p>
<ol>
<li>Settle Atlassian's app controls. If you are allowing specific apps rather than blocking all of them, confirm you hold Atlassian Guard Standard or Premium before you plan the allowlist.</li>
<li>Add Elaichi in ChatGPT. An admin creates the custom app from the workspace admin console and publishes it; full MCP support is in beta on Business, Enterprise and Edu plans (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">help.openai.com</a>, checked October 2026). The address is <code>https://api.elaichi.ai/mcp</code>, and the walkthrough is in <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT connection guide</a>.</li>
<li>Write the restriction on the role that will read Confluence. Block the three write tools named above. A restriction change takes effect within about two minutes, on every surface: ChatGPT, Claude, or any other connected client.</li>
<li>Build the template from the Confluence tool list and share it with the team at <code>use</code>.</li>
<li>Each member connects their own Confluence account and stamps the template. The resulting toolbox runs on their connection, under their own space roles, not the admin's who built the template.</li>
<li>Each member signs in from ChatGPT. On Elaichi's consent screen they pick the organization and tick "Run your connected tools," then choose "Only the ones I pick" and select the Confluence toolbox. "Delete data and remove access" is never pre-ticked; leaving it off keeps the group-removal tool out of both the active toolset and search results.</li>
</ol>
<p>A missed scope does not fail silently. The endpoint answers with an in-band tool error naming the checkbox and telling the person to reconnect and allow it. Reconnecting fixes it, as long as the client asked for that scope in the first place. If the client itself never requested the scope, reconnecting alone will not surface it.</p>
<p>One line worth putting in internal onboarding instructions: Elaichi's consent screen warns that anyone can register an app under any name and logo, and shows the redirect host. People should only continue from a sign-in they started themselves, not one they were sent a link for.</p>
<h2 id="what-the-audit-trail-shows-after-a-page-edit">What the audit trail shows after a page edit</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the Confluence account actually reached, not a generic "ChatGPT" actor.</p>
<p>Audit events and application logs share one record shape, so a single query answers what happened instead of correlating two systems by eye. Each entry also records the surface and the OAuth client. ChatGPT is among the clients whose redirect URIs mark the client name as verified, so a Confluence page created from ChatGPT is attributable without guessing from a user-agent string. The approval line on an MCP call reads along the lines of "Allowed by the access ChatGPT was granted." A call from an MCP client is recorded with <code>actor_kind</code> <code>user</code>, not as an assistant, and the distinction matters for anyone reconstructing who actually approved a given write.</p>
<p>The trail is append-only, newest-first, filterable by actor, category and time, and eventually consistent, so a row can take a moment to appear after the call completes. A departed member renders as "Former member" rather than disappearing from historical rows. The audit trail inside Elaichi is included on the Gold plan. Forwarding it to your own Datadog comes with the Black plan, launching soon.</p>
<h2 id="what-this-setup-does-not-do">What this setup does not do</h2>
<p>It does not change anything inside Atlassian. Removing someone in Elaichi ends their access through Elaichi only. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Their Confluence account still exists, and it must be deprovisioned in Atlassian or through your identity provider separately. Elaichi offboarding and Atlassian offboarding are two different actions. Revoking a share or disconnecting an account takes effect on the caller's next request; role and restriction changes take effect within about two minutes.</p>
<p>It does not defend the endpoint against prompt injection. An MCP server never sees the user's prompt, so a prompt-level filter cannot exist at that layer by construction. What does hold at the endpoint: role permissions per operation, restrictions, OAuth scope limits, output redaction and audit logging of each call that reaches execution. If prompt injection is the threat model, the control has to sit somewhere else in the stack. This setup addresses permission scope, not prompt content.</p>
<p>It does not make per-person identity automatic. If somebody shares a Confluence connection instead of stamping the template, every call runs as that owner regardless of who is typing in ChatGPT. The only way to verify the setup is correct is to check the connections themselves, not to assume intent from how the template was distributed.</p>
<p>For the tool lists behind each app, see <a href="/connectors/">the connector catalog</a>. The wider shape this sits inside is covered in <a href="/blog/what-is-an-mcp-control-plane/">the control plane explainer</a>, the same per-person pattern for a different app is in <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the Salesforce rollout for sales</a>, and the ChatGPT-side switches are compared in <a href="/blog/restrict-chatgpt-enterprise-connectors/">the Enterprise connector guide</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does ChatGPT have a Confluence connector?</strong></dt><dd>No. ChatGPT's synced sources are Google Drive, SharePoint and Teams, and Confluence is not among them ([help.openai.com](https://help.openai.com/en/articles/10847137-administrator-managed-apps-with-sync-in-chatgpt), checked October 2026). Confluence reaches ChatGPT through an MCP server instead: either Atlassian's own remote MCP server, surfaced in ChatGPT as the "Atlassian Rovo" app, or a governed MCP endpoint such as Elaichi's, which serves a Confluence connector alongside other company apps.</dd><dt><strong>Do Confluence space permissions still apply when ChatGPT reads a page?</strong></dt><dd>Yes, provided the connection signs in as the person. Atlassian states that OAuth 2.0 (3LO) apps act on a user's behalf and that Confluence permissions are not overridden by scopes ([developer.atlassian.com](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/), checked October 2026). Space roles and page view restrictions carry through. A connection that uses client credentials signs in as one identity for everyone who uses it, so permissions then follow that single account rather than the person asking.</dd><dt><strong>How do you stop an AI assistant from editing Confluence pages?</strong></dt><dd>Block the write tools for the role that should only read. Elaichi's Confluence connector carries 18 tools: 15 reads, plus create_a_confluence_page, update_a_confluence_page_by_id and confluence_groups_remove_member. Blocking those three leaves the reads intact and leaves the role's other apps untouched. A restricted tool is withheld from the tool list and cannot be called, and the change takes effect within about two minutes.</dd><dt><strong>Do you need Atlassian Guard to allow ChatGPT on Atlassian's MCP server?</strong></dt><dd>Blocking all apps works on any Atlassian plan, but choosing which specific apps to allow needs Atlassian Guard Standard or Premium, under the policy now called "Marketplace and custom app access" ([support.atlassian.com](https://support.atlassian.com/security-and-access-policies/docs/block-app-access/), checked October 2026). Separately, the Rovo MCP server settings let an admin allow or block Atlassian's default domain list as a whole, which includes chatgpt.com, and turn Read, Write and Search on or off per app.</dd><dt><strong>What does a Confluence tool call look like in the audit trail?</strong></dt><dd>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the Confluence account actually reached, the surface and the OAuth client, with ChatGPT among the clients marked verified.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Scope Google Drive in Claude to people or folders</title>
      <link>https://elaichi.ai/blog/claude-google-drive-sharing-permissions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/claude-google-drive-sharing-permissions/</guid>
      <description>Google Drive in Claude has two honest shapes: each person connects their own Google account, or one dedicated account whose shared folders draw the line.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Google Drive in Claude works in two shapes, both served through Elaichi's one organization-wide MCP endpoint. To leave each person's Drive permissions intact, share a template with the team at use so every member stamps a toolbox bound to their own Google connection. To hold a team to a fixed set of folders, connect a dedicated Google account that has only those folders shared to it and share that connection at use, because no Google OAuth scope limits an app to a folder.</aside>
<h2 id="google-drive-in-claude-the-two-shapes-that-work">Google Drive in Claude: the two shapes that work</h2>
<p>Someone in finance asks for Claude to read the board folder. Someone in support asks for Claude to search whatever they can already open in Drive. Those are two different builds. Treating them as one request is how a connection ends up reaching every file in the company.</p>
<p>Google Drive access from an AI client reduces to two honest shapes, regardless of which vendor's connector you use:</p>
<ol>
<li><strong>Per-user OAuth</strong>: each person connects their own Google account, so their existing Drive permissions bound every call.</li>
<li><strong>Dedicated account</strong>: one Google account, with only the target folders shared to it, draws the folder line, and the team shares that one connection.</li>
</ol>
<p>These are not Elaichi inventions. They are the two access patterns any OAuth-based Drive integration can offer. A Drive call made with a person's OAuth token is bounded by that signed-in account. Elaichi serves both through one organization-wide MCP endpoint. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi writes and runs most of its 600+ connectors, Drive among them. So Drive is served from Elaichi's infrastructure rather than a server someone on your team has to stand up and patch.</p>
<p>The same address answers ChatGPT and Cursor. The folder question does not change per client, and neither does the answer below.</p>
<p><strong>Simplest case first.</strong> You just want Claude to read whatever one person can already open in Drive, with no folder boundary and no shared account. Shape 1 is it: connect your own Google account, done. The rest of this post is for the harder case. One version: the AI needs to see <em>less</em> than one person's full Drive. The other: the access needs to be shared across a team without multiplying individual logins.</p>
<h2 id="how-does-each-person-keep-their-own-drive-permissions">How does each person keep their own Drive permissions?</h2>
<p>Each member connects their own Google account (shape 1). The way to hand that out at team scale is a template, not a shared toolbox. This part is Elaichi-specific plumbing. It is described here because it's the mechanism, not because it's the only way to think about the problem.</p>
<p>A template holds a tool list with renames, defaults and frozen arguments, and never holds a connection. Share it with the team at <code>use</code>. Each member then stamps their own toolbox from it. Stamping binds every entry to a connection that person can use, so their own Google account runs the call. Stamping copies once, so a later template edit leaves already-stamped toolboxes alone. A member who has not connected Google yet sees that entry marked "needs connection" until they do.</p>
<p>Sharing a toolbox does the opposite: every grantee's call then runs on the connection pinned in its entries, which belongs to the owner. Never pair "each person connects their own account" with "share one toolbox with the team". That silently runs everyone's calls on the owner's own Google account, with the owner's full Drive access.</p>
<p>This part is universal, not vendor-specific: Google enforces access at the API layer, not the AI client. The Drive API bounds every call by the signed-in user. It returns 404 <code>notFound</code> where the person has no read access, and 403 where they have no write access (<a href="https://developers.google.com/workspace/drive/api/guides/handle-errors">developers.google.com</a>, checked October 2026). A support agent asking about a folder nobody shared with them gets nothing back, for the same reason they see nothing in Drive itself. The same per-person shape is what keeps <a href="/blog/sales-team-chatgpt-salesforce-accounts/">each rep inside their own Salesforce sharing rules</a>.</p>
<h2 id="can-an-oauth-scope-limit-drive-access-to-specific-folders">Can an OAuth scope limit Drive access to specific folders?</h2>
<p>No. Stated flatly: <strong>no Google Drive OAuth scope confines an app to a folder.</strong></p>
<ul>
<li><code>drive.file</code> reaches only files the app created or opened, or that the user picked via Google Picker, a per-file consent pattern, not a folder boundary.</li>
<li><code>drive</code>, <code>drive.readonly</code>, and <code>drive.metadata.readonly</code> reach the user's entire Drive (and any shared drives they belong to).</li>
<li>There is no <code>drive.folder</code> scope and no documented scope parameter that recurses into a folder tree.</li>
</ul>
<p>(Source: <a href="https://developers.google.com/workspace/drive/api/guides/api-specific-auth">developers.google.com</a>, checked October 2026.)</p>
<p>A query such as <code>'FOLDER_ID' in parents and trashed = false</code> narrows a <em>search</em>, and Google does not document it as recursive into subfolders. A search filter is not a permission, and a model calling the tool can omit or alter the filter on its own.</p>
<p>So the only real folder line is drawn at the account level, not the scope level: the Google account the connection signs in with. The working pattern is:</p>
<ol>
<li>Create a dedicated Google account.</li>
<li>Share only the folders that team should reach, to that account, in Drive's own sharing UI.</li>
<li>Connect that account to the MCP server (Elaichi or otherwise).</li>
<li>Share that one connection with the team.</li>
</ol>
<p>A shared connection runs on its owner's credential. So every call reaches Drive as that account and sees exactly what was shared to it, nothing more. The dedicated account itself has nothing more. Anthropic recommends the same dedicated-account pattern for Claude Tag's Google connection. The account starts at no access and gains specific folders one at a time (<a href="https://claude.com/docs/claude-tag/admins/connections/google">claude.com</a>, checked October 2026). Before relying on the line, open Drive as that account and check what it can already see, such as files shared with your whole domain.</p>
<p>Two trade-offs come with this pattern:</p>
<ul>
<li><strong>Ownership:</strong> the dedicated connection has an owner in Elaichi. Pick an owner who is staying, and transfer the connection during their offboarding. The credential is the dedicated Google account, not the owner's own, so a transfer keeps it working.</li>
<li><strong>Scope only narrows the connection it's on.</strong> A member who <em>also</em> connects their personal Google account reaches Drive under "All my tools" with their own full Drive access. That is shape 1 running beside shape 2, for that person only.</li>
</ul>
<h2 id="which-tools-can-the-google-drive-connector-actually-run">Which tools can the Google Drive connector actually run?</h2>
<p>Elaichi's <code>googledrive</code> connector connects over OAuth and carries 28 tools; 25 of them read. Files, folders, shared drives, drive items, search, export, permissions, labels, revisions, comments and replies, Docs, Forms and the change log are all reads. Names run like <code>list_all_googledrive_files</code> and <code>get_single_googledrive_file_by_id</code>. The full list is on the <a href="/connectors/googledrive/">Google Drive connector page</a>.</p>
<p>The other three are <code>create_a_googledrive_watch</code>, <code>create_a_googledrive_changes_watch</code> and <code>delete_a_googledrive_channel_by_id</code>. The first two ask Google to post change notifications to an HTTPS address the caller supplies. The third stops a channel. None of the 28 creates, edits, shares, moves, or deletes a file.</p>
<p>A team that only reads blocks those three tools. Blocks, not allows, are the right instrument here, for a structural reason:</p>
<ul>
<li>An <strong>allow</strong> rule becomes that role's <em>entire allowlist across every connector</em>, so the role loses every other app it had.</li>
<li>A <strong>block</strong> removes exactly the named tools and leaves everything else untouched. Three blocks leave 25 reads.</li>
</ul>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A restriction change takes effect within about two minutes. Restrictions are applied before search, so a withheld tool stays out of the tool list and cannot be called. <code>search_tools</code> names it, flagged restricted, with no schema. The case-by-case version of this choice is in <a href="/blog/per-tool-vs-per-app-restrictions/">restrict one AI tool or the whole app</a>.</p>
<p>One thing the OAuth consent screen does <strong>not</strong> do: leaving "Create and change data" unticked does not make a connected app read-only in Drive. That checkbox governs Elaichi's own internal operations, not what the Drive API will accept from the connected account. Read-only access to Drive is a restriction you apply explicitly (the three-tool block above), not a side effect of a consent checkbox. It is the same way <a href="/blog/finance-team-claude-quickbooks-read-only/">QuickBooks has to be held to reads</a> when the vendor ships no read-only scope.</p>
<h2 id="what-does-a-google-workspace-admin-set-before-any-of-this">What does a Google Workspace admin set before any of this?</h2>
<p>The Workspace control is <strong>Manage App Access</strong>, under Security, then Access and data control, then API controls. An app, found by name or OAuth client ID, is set to Trusted, Limited, Specific Google data, or Blocked. Unconfigured apps fall under "Allow users to access any third-party apps" (<a href="https://knowledge.workspace.google.com/admin/apps/control-which-apps-access-google-workspace-data">knowledge.workspace.google.com</a>, checked October 2026).</p>
<p>Order matters, and getting it backwards breaks working connections:</p>
<ol>
<li>Mark the app <strong>Trusted</strong> first.</li>
<li>Restrict afterward (e.g., set Drive to Restricted for the org).</li>
</ol>
<p>Setting Drive to Restricted <em>before</em> trusting the app revokes untrusted apps' tokens, including ones that were working that morning. Google's high-risk Drive scope list includes <code>drive</code>, <code>drive.readonly</code>, and <code>drive.metadata.readonly</code>, but does not include <code>drive.file</code>. Elaichi's console does not show which Google scopes its Drive connector requests. So find the app by name or OAuth client ID, rather than inferring it from the high-risk scope list.</p>
<p>Shared drives need a separate argument entirely. The Drive API returns shared-drive items only when a call sets <code>supportsAllDrives=true</code> and <code>includeItemsFromAllDrives=true</code>. The <code>corpora</code> argument takes one of <code>user</code>, <code>domain</code>, <code>drive</code>, or <code>allDrives</code> (<a href="https://developers.google.com/workspace/drive/api/guides/enable-shareddrives">developers.google.com</a>, checked October 2026). Google also states admins have no control over individual folders inside users' My Drives. That is another reason the dedicated-account pattern, not a central Workspace policy, is how a folder boundary actually gets drawn. Per-tool arguments are on the <a href="/connectors/googledrive/">Google Drive connector page</a>.</p>
<h2 id="claude-native-connector-vs-chatgpt-drive-app-vs-an-mcp-endpoint">Claude native connector vs. ChatGPT Drive app vs. an MCP endpoint</h2>
<table>
<thead>
<tr>
<th></th>
<th>Claude's built-in Google Drive connector</th>
<th>ChatGPT's Google Drive app</th>
<th>Elaichi (MCP endpoint)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Permission model</td>
<td>Mirrors the connecting user's existing Drive permissions</td>
<td>Live access as the user, or admin-managed sync via domain-wide delegation</td>
<td>Per-user OAuth or dedicated-account, admin's choice</td>
</tr>
<tr>
<td>Folder-level restriction</td>
<td>Not documented</td>
<td>Admin-managed sync can include or exclude shared drives; no folder restriction documented</td>
<td>Dedicated Google account + Drive sharing (account-level, not scope-level)</td>
</tr>
<tr>
<td>Per-tool control</td>
<td>Always allow / Needs approval / Blocked, set by Owner</td>
<td>Actions switched per app on the Admin Console's Plugins page</td>
<td>Per-role/per-user restrictions on any of the 28 tools</td>
</tr>
<tr>
<td>Cross-app consistency</td>
<td>Claude only</td>
<td>ChatGPT only</td>
<td>Same endpoint, same restrictions, across Claude, ChatGPT, Cursor</td>
</tr>
<tr>
<td>Audit trail</td>
<td>Compliance API events on Enterprise</td>
<td>Compliance Logs Platform on Enterprise and Edu</td>
<td>One trail across every connected app</td>
</tr>
<tr>
<td>Availability</td>
<td>All plans; Team/Enterprise admin enables org-wide</td>
<td>Enterprise/Edu/Business, Admin Console managed</td>
<td>Any client that takes a custom MCP connector</td>
</tr>
</tbody>
</table>
<p>Sources: Anthropic states Claude "mirrors your existing permissions" (<a href="https://support.claude.com/en/articles/10166901-use-google-workspace-connectors">support.claude.com</a>, checked October 2026). OpenAI documents live access for a personal connection, and admin-managed sync through a domain-wide delegation service account. Individually authorized sync is retired (<a href="https://help.openai.com/en/articles/10929079-google-drive-app-and-setup-in-chatgpt">help.openai.com</a>, checked October 2026). Drive actions start off on Enterprise and Edu and on for Business (<a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">help.openai.com</a>, checked October 2026).</p>
<p><strong>When to just use Claude's native connector and stop.</strong> Drive is the only app the team needs. They need to upload, share, move, or trash files from the chat, not just read. Use it. It's on all plans; an Owner or Primary Owner enables it under Organization settings, Connectors. No folder or shared-drive restriction is documented for it, and each person connects their own Google account. So a folder boundary needs the dedicated-account pattern, through a connector that can share one connection.</p>
<p><strong>The caveat on the Elaichi row:</strong> to ChatGPT, Elaichi presents as one custom app whose tools are <code>search_tools</code>, <code>execute_tool</code> and Elaichi's own operations. ChatGPT's own per-action approval switches therefore cannot distinguish Drive from any other app behind Elaichi. That granularity has to be enforced inside Elaichi's restrictions, not in ChatGPT's UI. The broader trade-off is in <a href="/blog/elaichi-vs-native-ai-connectors/">Claude and ChatGPT connectors vs one MCP endpoint</a>.</p>
<h2 id="adding-the-endpoint-approving-the-scopes-and-the-record-afterward">Adding the endpoint, approving the scopes, and the record afterward</h2>
<p>The address is <code>https://api.elaichi.ai/mcp</code>, the same for every organization. In Claude Team and Enterprise, an Owner adds it under Organization settings, Connectors, Add, Custom, Web. Members then connect it under Customize, Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">support.claude.com</a>, checked October 2026). There is no client ID, secret, or header to type, because the client registers itself through OAuth dynamic client registration.</p>
<p>On Elaichi's consent screen the person picks the organization first. Then come the checkboxes: Read your organization's data, Create and change data, Run your connected tools, and Delete data and remove access. Delete is never pre-ticked. With "Run your connected tools" ticked, a second step asks for All my tools or only chosen toolboxes. For the dedicated-account shape, picking just the Drive toolbox is the tighter choice: All my tools also reaches every other connection that person holds personally.</p>
<p>Afterward, the record is plain. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The record carries the one path argument that names the object as the target id, and no other argument value: no argument names and no count. So the log shows which object was acted on, not what was written to it. That answers the first question in an incident: who reached which Google account, through which client. The entry carries the surface (<code>mcp</code>), and the OAuth client it came through, marked verified for Claude, ChatGPT, and Cursor. The audit trail inside Elaichi is on the Gold plan; forwarding it to your own Datadog comes with the Black plan, launching soon.</p>
<p>If you're still deciding whether any of this machinery is warranted, start with <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is for</a>. If you've decided, <a href="/blog/connect-elaichi-to-claude/">the Claude connection walkthrough</a> covers sign-in, and the <a href="/use-cases/">team use cases</a> show what other teams set up next.</p>
<h2>FAQ</h2><dl><dt><strong>Can you limit an AI assistant's Google Drive access to specific folders?</strong></dt><dd>Not with an OAuth scope. Google publishes no Drive scope that confines an app to a folder, and an 'in parents' query is a search filter rather than a permission. The practical boundary is the Google account the connection signs in with: create a dedicated account, share only those folders to it, and connect that account. In Elaichi, sharing that connection at use means every call reaches Drive as that account, because a shared connection runs on its owner's credential.</dd><dt><strong>Does Elaichi's Google Drive connector let an AI agent edit or delete files?</strong></dt><dd>No. The connector carries 28 tools, 25 of which read files, folders, shared drives, search results, permissions, revisions, comments and the change log. The other three are create_a_googledrive_watch and create_a_googledrive_changes_watch, which ask Google to post change notifications to an HTTPS address the caller supplies, and delete_a_googledrive_channel_by_id, which stops a channel. None creates, edits, shares, moves or deletes a file, and a team that only reads blocks those three.</dd><dt><strong>What happens when someone asks an AI assistant for a Drive file they cannot open?</strong></dt><dd>Google answers the call, not the assistant. The Drive API bounds every request by the signed-in user and returns 404 notFound where that user has no read access, and 403 where they have no write access. So a connection made with a person's own Google account can never surface a document that person could not already open in Drive.</dd><dt><strong>How quickly does a Google Drive restriction take effect in Elaichi?</strong></dt><dd>A restriction or role change takes effect within about two minutes, on every surface. Revoking a share of a connection, or disconnecting the account, takes effect on the caller's very next request, because grants and connections are read fresh on every call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Should a Google Workspace admin mark an app Trusted before restricting Drive?</strong></dt><dd>Yes, and the order matters. In Manage App Access an app is set to Trusted, Limited, Specific Google data, or Blocked. Setting Drive to Restricted revokes the tokens of apps that are not trusted, so mark the app Trusted first and restrict afterward. Google's high-risk Drive scope list includes drive, drive.readonly and drive.metadata.readonly, and does not include drive.file.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Govern SharePoint in Claude with delegated OAuth</title>
      <link>https://elaichi.ai/blog/claude-sharepoint-permissions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/claude-sharepoint-permissions/</guid>
      <description>How to keep SharePoint in Claude inside each person&apos;s own site and library permissions, using per-person OAuth and one allow rule per role.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> SharePoint permissions hold in Claude only when every call is delegated, so each person signs in with their own Microsoft account rather than sharing one app identity. In Elaichi, that means a template shared with the team at use and stamped by each member, plus an allow rule naming the read tools and the Microsoft Search tool. Elaichi's SharePoint connector carries 97 tools, about 48 of which write or act, so a block list is the wrong instrument.</aside>
<h2 id="why-sharepoint-in-claude-needs-per-person-oauth">Why SharePoint in Claude needs per-person OAuth</h2>
<p>SharePoint in Claude stays inside each person's own permissions only when every call is delegated. That means each person signs in with their own Microsoft account. The app never acts beyond what that account can already see. Microsoft states the rule for delegated permissions directly: "the application can't access anything the signed-in user couldn't access" (<a href="https://learn.microsoft.com/en-us/graph/permissions-overview">learn.microsoft.com</a>, checked October 2026). Site permissions, library permissions and item-level restrictions then do the work they already do. The MCP layer adds no new access; it inherits what Entra and SharePoint already enforce.</p>
<p>Elaichi's SharePoint connector accepts two connection modes:</p>
<table>
<thead>
<tr>
<th>Mode</th>
<th>Identity on each call</th>
<th>Who it exposes</th>
</tr>
</thead>
<tbody>
<tr>
<td>OAuth (delegated)</td>
<td>The signed-in person's Microsoft account</td>
<td>Only what that person can already open</td>
</tr>
<tr>
<td>OAuth client credentials (app-only)</td>
<td>A single app identity</td>
<td>Whatever the app was granted, to everyone using that connection</td>
</tr>
</tbody>
</table>
<p>A client-credentials connection signs in as one app identity. Everyone who reuses that connection reaches whatever the app was granted. That is not what they personally can open in a browser. For keeping SharePoint permissions, that is the wrong shape.</p>
<p>Graph permissions come in two forms, and the distinction decides whether an admin has to approve anything. Delegated <code>Sites.Read.All</code> and <code>Files.Read.All</code> need no admin consent; their application (app-only) equivalents do (<a href="https://learn.microsoft.com/en-us/graph/permissions-reference">learn.microsoft.com</a>, checked October 2026). In delegated mode, Graph intersects the app's granted scopes with the signed-in user's actual permissions. The app's scope is a ceiling, and the user's access is the real limit. The lower of the two always wins.</p>
<h2 id="share-a-template-not-a-connection">Share a template, not a connection</h2>
<p>The per-person shape in Elaichi is a template shared at <code>use</code>, never a shared connection. A template holds a tool list with overrides, defaults and frozen arguments, and never holds a connection itself. This is the mechanism that keeps one shared setup from collapsing into one shared identity.</p>
<p>Build a template from the SharePoint connector and share it with the team at <code>use</code>. Each member then stamps their own toolbox from it. Stamping binds every entry to the stamper's own connection, so each person's calls run on the Microsoft account they signed in with. An entry with no usable connection is left as "needs connection" until that person connects, so it fails visibly, not silently.</p>
<p>A shared <em>connection</em> works the opposite way. It runs on its owner's credential, so every call reaches SharePoint as the owner, regardless of who triggers it. A toolbox shared at <code>use</code> has the same effect, because every entry in it is pinned to the connection its owner chose at creation time. For permission parity across a team, the template is the only one of the two that preserves per-person boundaries. A shared connection or a shared toolbox both re-create the app-only problem, just with a human owner instead of a service principal. The same fork appears in <a href="/blog/claude-google-drive-sharing-permissions/">drawing the folder line in Google Drive</a>, where a dedicated account is sometimes the better of the two shapes.</p>
<h2 id="what-elaichis-sharepoint-connector-carries">What Elaichi's SharePoint connector carries</h2>
<p>Elaichi's <code>sharepoint</code> connector carries 97 tools. 49 have names starting <code>list_</code> or <code>get_</code>, and they read. Most of the other 48 create, update, publish, upload or delete pages, lists, list items and files, and five change who can see what.</p>
<p>Elaichi authors and serves this connector from its own infrastructure, one of the 600+ connectors in its catalog. So no third-party MCP server sits in the call path between Claude and Microsoft Graph. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>Two tools behave differently from the rest:</p>
<ul>
<li><code>list_all_sharepoint_search</code> runs Microsoft Search under the hood and is classified <code>other</code>, not <code>read</code>. A rule written to match "all read tools" will not catch it by accident, and a rule meant to allow it must name it explicitly.</li>
<li><code>list_all_sharepoint_get_all_sites</code> requires an app-only token. On a delegated connection it returns HTTP 403. That 403 is the expected result of per-person auth working correctly, not a connector fault. If you see it on a delegated setup, the setup is doing what it is supposed to.</li>
</ul>
<p>The full tool list is on the <a href="/connectors/sharepoint/">SharePoint connector page</a>.</p>
<h2 id="writing-the-allow-rule-for-a-reading-role">Writing the allow rule for a reading role</h2>
<p>Hold a reading role with an allow rule that names the read tools it needs plus <code>list_all_sharepoint_search</code> explicitly, since it is not classified <code>read</code>. A block list fails open on a connector this size. Of 97 tools, roughly 48 write or act. Every one you forget to name in a block list stays reachable. The same arithmetic plays out on <a href="/blog/it-team-claude-intune-devices/">Intune's 198 tools, where six blocks are not enough</a>. An allow list fails closed instead, so anything not named is denied. That is the direction you want on a document store. The cost of one missed write tool is a deleted or overwritten file.</p>
<p>For a reading role, name tools such as <code>list_all_sharepoint_sites</code>, <code>get_single_sharepoint_site_by_id</code>, <code>list_all_sharepoint_drives</code>, <code>list_all_sharepoint_drive_items</code>, <code>get_single_sharepoint_drive_item_by_id</code>, <code>list_all_sharepoint_lists</code>, <code>list_all_sharepoint_list_items</code> and <code>list_all_sharepoint_search</code>.</p>
<p>One property of restrictions catches people out: an allow rule is the target's <em>entire</em> allowlist across every connector, not only the app it names. Once a role holds one allow rule, every connector that rule does not mention is denied for that role. That includes connectors that had no restrictions before. A support role reading SharePoint and working in Jira needs the SharePoint allow rule <em>plus</em> a separate allow rule naming Jira whole. It cannot rely on Jira being unrestricted by omission once any allow rule exists on that role. Allow rules targeting the same role union together, so one rule per connector is the normal way to compose this, not one giant rule.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A block rule matches the advertised tool name or the pinned operation it maps to. An allow rule matches the pinned operation only. The mechanics are covered in <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match names and allows do not</a>. A restriction change takes effect within about two minutes.</p>
<h2 id="the-five-tools-that-change-who-can-see-what">The five tools that change who can see what</h2>
<p>Five tools in the SharePoint connector edit SharePoint's own sharing model rather than its content:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Effect</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>create_a_sharepoint_site_permission</code></td>
<td>Grants a role on a site</td>
</tr>
<tr>
<td><code>create_a_sharepoint_list_item_permission</code></td>
<td>Grants access to one list item</td>
</tr>
<tr>
<td><code>update_a_sharepoint_drive_item_permission_by_id</code></td>
<td>Changes an existing drive-item grant</td>
</tr>
<tr>
<td><code>delete_a_sharepoint_drive_item_permission_by_id</code></td>
<td>Revokes a drive-item grant</td>
</tr>
<tr>
<td><code>sharepoint_drive_item_invite_send</code></td>
<td>Sends a sharing invitation, which can reach an external address where the tenant allows external sharing</td>
</tr>
</tbody>
</table>
<p>These are the tools that can quietly widen the permission model everything else in this post assumes is stable. An invitation sent to the wrong address opens that item to someone outside the team until someone notices and revokes it. A reading role keeps all five out simply by never naming them in its allow rule. There is nothing to block, because anything the allowlist does not name is already denied.</p>
<p>A withheld tool is not merely disabled. It is absent from <code>tools/list</code> and cannot be called. Search names it, flagged restricted, with no schema.</p>
<h2 id="does-sitesselected-limit-sharepoint-to-chosen-sites">Does Sites.Selected limit SharePoint to chosen sites?</h2>
<p>Sites.Selected is Microsoft's mechanism for holding an application to sites it has been granted explicitly, rather than tenant-wide. An app consented for a Selected scope has zero access at first. Access starts once it is granted a role on a specific site through <code>POST /sites/{siteId}/permissions</code>. The role is set to read, write, owner or fullcontrol. Creating that grant itself requires <code>Sites.FullControl.All</code>, and in a delegated flow requires a caller with SharePoint Administrator role or higher (<a href="https://learn.microsoft.com/en-us/graph/permissions-selected-overview">learn.microsoft.com</a>, checked October 2026).</p>
<p>Do not assume every third-party connector draws the site line this way. Sites.Selected is one specific Graph mechanism, and a connector can be delegated (per-user) without also being Selected (per-site). In Elaichi, the site line is drawn by the Microsoft account each person signs in with and by the restriction on their role. Elaichi's console does not show which Graph scopes its SharePoint connector requests, so do not assume it uses Sites.Selected.</p>
<p>For comparison, two other Microsoft-adjacent AI products sit at different points on this same spectrum:</p>
<table>
<thead>
<tr>
<th>Product</th>
<th>Access model</th>
<th>Site-level scoping</th>
</tr>
</thead>
<tbody>
<tr>
<td>Elaichi SharePoint connector</td>
<td>Delegated OAuth (default), app-only optional</td>
<td>Through the signed-in account and role restrictions</td>
</tr>
<tr>
<td>Claude's native Microsoft 365 connector</td>
<td>Delegated, <code>Sites.Read.All</code></td>
<td>None; tenant-wide search, limited to the user's own permissions</td>
</tr>
<tr>
<td>Microsoft Copilot</td>
<td>Delegated, per Microsoft 365 permission model</td>
<td>None by default; Restricted Content Discovery can hide a site from Copilot and search without changing its ACLs</td>
</tr>
</tbody>
</table>
<p>Claude's own Microsoft 365 connector does not support Sites.Selected. Its SharePoint search runs tenant-wide under <code>Sites.Read.All</code>, limited to each user's own permissions (<a href="https://support.claude.com/en/articles/12684923-microsoft-365-connector-security-guide">support.claude.com</a>, checked October 2026). Microsoft Copilot sits in a comparable place. It "only surfaces organizational data to which individual users have at least view permissions" (<a href="https://learn.microsoft.com/en-us/microsoft-365/copilot/microsoft-365-copilot-privacy">learn.microsoft.com</a>, checked October 2026). Restricted Content Discovery can hide a site from organization-wide search and Copilot without changing its underlying permissions (<a href="https://learn.microsoft.com/en-us/sharepoint/restricted-content-discovery">learn.microsoft.com</a>, checked October 2026). Whether Restricted Content Discovery also suppresses a site from third-party Graph-based search, including Elaichi's, is not documented by Microsoft. Do not plan a security boundary around it.</p>
<h2 id="when-claudes-own-microsoft-365-connector-is-the-better-choice">When Claude's own Microsoft 365 connector is the better choice</h2>
<p>If SharePoint is the only system your team needs inside Claude, and read access is all that is required, the answer is simpler. Anthropic's native Microsoft 365 connector is genuinely less machinery to operate. It is available on all Claude plans and takes a one-time Entra Global Administrator consent. On Team and Enterprise plans an Owner can also enable it. It is read-only by default; enabling SharePoint writes requires turning on write tools plus granting <code>Files.ReadWrite.All</code> (<a href="https://support.claude.com/en/articles/12542951-set-up-the-microsoft-365-connector">support.claude.com</a>, checked October 2026). For a single-app pilot with one connector and no cross-tool audit requirement, that is usually the right answer and adds no operational layer worth maintaining.</p>
<p>The trade-off shifts once a role needs more than one system, for example SharePoint plus Jira, Zendesk or Salesforce. The alternative is writing and maintaining access rules separately in each vendor's own console, instead of once per role in a single control plane. It shifts again where a single audit trail needs to cover all the tools a given actor touched, not just one connector's logs. Whether that trade-off is worth the added layer depends on how many connectors a role actually spans, and on how centralized the audit requirement is. It is not automatically the right call for every team.</p>
<h2 id="adding-the-endpoint-and-what-each-person-consents-to">Adding the endpoint and what each person consents to</h2>
<p>The address is <code>https://api.elaichi.ai/mcp</code> for every organization: one URL, not one per team. In Claude Team or Enterprise, an Owner adds it under Organization settings, Connectors, Add, Custom, Web. Members then connect it individually under Customize, Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">support.claude.com</a>, checked October 2026). The same URL also serves ChatGPT, Cursor, any MCP-compatible client, and the Elaichi Agent.</p>
<p>Each person signs in on Elaichi's own consent screen, picks one organization, and ticks what the client may do. Delete is never pre-ticked by default. With "Run your connected tools" ticked, a second step asks whether to grant all tools or only chosen toolboxes. The consent request itself lasts 30 minutes before expiring. That is long enough to stamp a template in a second tab. It does need to happen in one sitting.</p>
<p>One mechanical detail trips people up. For a connected app's tools, the general tools checkbox covers reads <em>and</em> writes together. Only a delete action costs a separate destructive-action scope. Leaving "Create and change data" unticked does not make SharePoint read-only by itself. Read-only access is enforced by the allow rule on the role, not by this checkbox. That is covered in <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool or a whole app</a>.</p>
<h2 id="what-the-audit-trail-records-and-what-leaving-ends">What the audit trail records, and what leaving ends</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The raw error text Microsoft returns to the caller is never copied into the audit record itself. That keeps third-party response payloads out of the audit log pipeline. The entry records that a call failed and which tool and operation it was, not the verbatim upstream error body.</p>
<p>The entry records the surface as <code>mcp</code> and names the OAuth client that made the call. Claude is among the clients whose identity is marked verified by its registered redirect URIs. A call made through an MCP client is logged with an actor kind of <code>user</code>. The grant backing the call belongs to that person, not to the client application.</p>
<p>When someone leaves the organization, removing or suspending them in Elaichi is what ends their access through Elaichi. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Offboarding runs a preflight first. It lists every connection the departing member owns, private and shared alike. A shared connection can be transferred to one active member. A private connection that a shared toolbox relies on blocks the removal until it is transferred to one member or deleted. A private connection that nothing else depends on cannot be transferred and is deleted with the member. Nothing is transferred to a team or the organization, and nothing is silently transferred to the admin running the removal, which would otherwise let one admin accumulate other people's connections during offboarding. The full sequence is set out in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding when the agent holds the access</a>. Removal ends access through Elaichi specifically; the person's underlying Microsoft account still exists and must be deprovisioned separately in Entra or through your identity provider. These are two different revocation events and neither one substitutes for the other.</p>
<p>For the wider model, see <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Claude see SharePoint files a person cannot open?</strong></dt><dd>Not when the connection is delegated. With per-person OAuth, every Microsoft Graph call runs as the signed-in user, and Microsoft states that an application with delegated permissions cannot access anything the signed-in user could not access ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-overview), checked October 2026). The risk comes from client-credentials connections, which sign in as one app identity for everyone who uses them, and from sharing a connection or a toolbox in Elaichi rather than a template.</dd><dt><strong>Does unticking "Create and change data" on Elaichi's consent screen make SharePoint read-only?</strong></dt><dd>No. For a connected app's tools, the "Run your connected tools" scope covers reads and writes alike, and only a tool whose method is a delete needs the destructive scope on top. The "Create and change data" box governs Elaichi's own control-plane operations. Read-only access to SharePoint is a restriction: an allow rule naming the read tools the role needs, plus allow rules naming its other apps whole.</dd><dt><strong>What is Sites.Selected, and does it apply to an AI connector?</strong></dt><dd>Sites.Selected is a Microsoft Graph scope that gives an application no SharePoint access until it is granted a role on a specific site through POST /sites/{siteId}/permissions, with read, write, owner or fullcontrol. Creating that grant needs Sites.FullControl.All and, in a delegated flow, a SharePoint Administrator ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-selected-overview), checked October 2026). Claude's own Microsoft 365 connector does not support it ([support.claude.com](https://support.claude.com/en/articles/12684923-microsoft-365-connector-security-guide), checked October 2026), so check the vendor's own page before assuming any connector draws a site line that way.</dd><dt><strong>How long does a SharePoint restriction take to apply in Elaichi?</strong></dt><dd>Within about two minutes. The change applies on the MCP endpoint, in the console and over the REST API alike. Removal is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Why use an allow rule instead of blocking the SharePoint write tools?</strong></dt><dd>Elaichi's SharePoint connector carries 97 tools, about 48 of which write or act, so a block list leaves every write it fails to name reachable. An allow rule fails closed: anything it does not name is denied for that role. The trade-off is that an allow rule is the role's whole allowlist across every connector, so the role also needs allow rules naming the other apps it uses.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Copilot Studio vs MCP gateway for company apps</title>
      <link>https://elaichi.ai/blog/copilot-studio-vs-mcp-gateway/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/copilot-studio-vs-mcp-gateway/</guid>
      <description>Copilot Studio vs MCP gateway: where each one puts the rules about which company app an AI client may reach, and who gets to write them.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Copilot Studio is Microsoft's builder for agents that live inside Microsoft Copilot and Teams, governed through Power Platform at the environment level. An MCP gateway is a control plane that gives the AI clients your people already use one governed address into company apps. Elaichi is that control plane: one organization-wide MCP endpoint, connectors it mostly authors itself, restrictions down to a single tool for a single role, and one audit trail. Many companies run both and draw a line between them.</aside>
<p>Finance drafts in ChatGPT. Two engineers run Cursor. The HR agent your platform team built sits in Microsoft Teams. Each surface reaches a different company app, under a different rule, and leaves a different record. Copilot Studio vs MCP gateway is the choice underneath that spread. Build agents inside Microsoft's own channels, or govern the AI clients your people already opened. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Both approaches speak it. They differ on where the rules live and how fine they go.</p>
<p>A note on sourcing before the comparison starts. Every Microsoft claim below links to the live docs page and carries the date it was last checked. Treat that date as a freshness marker for the specific paragraph, not a publication date for the post. Where a claim describes Elaichi's own product, it's marked as such and should be weighed as a vendor description, not independent documentation. Verify it against the pricing and docs pages linked inline.</p>
<h2 id="is-copilot-studio-an-mcp-gateway">Is Copilot Studio an MCP gateway?</h2>
<p>No. Copilot Studio is a place to build agents. A gateway is a place to govern clients somebody else built. The distinction matters because the two solve different problems. One gives a maker a canvas and a publish button. The other gives an admin a single policy surface over tools nobody on the admin team built.</p>
<p>In Copilot Studio a maker designs the agent and attaches tools to it. MCP support has been generally available since 29 May 2025. A maker adds it through the onboarding wizard at Tools, Add a tool, New tool, Model Context Protocol. A Power Apps custom connector is the other route. Streamable transport only, with None, API key or OAuth 2.0 for auth; tools and resources work and prompts do not (checked October 2026, <a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-mcp">Microsoft Learn</a>). The finished agent runs in Microsoft Copilot, Microsoft Teams and other Microsoft channels. Microsoft documents no way to expose a Copilot Studio agent to Claude, ChatGPT or Cursor as an MCP server (checked October 2026, <a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/mcp-add-existing-server-to-agent">Microsoft Learn</a>).</p>
<p>An MCP control plane inverts the shape. Nobody builds an agent. Every SaaS account the company uses is connected once, and the tools those accounts expose are served through one organization-wide MCP endpoint. Clients point at that one address and sign in: Claude, ChatGPT, Cursor or any MCP client. There are no per-toolbox URLs and no embedded tokens to hand around. Elaichi serves <a href="/connectors/">600+ connectors</a>, most of them authored on its own infrastructure and the rest vendors' own MCP servers it governs, so the company runs no MCP servers of its own. An app outside the catalog is covered by a custom connector authored from JSON config, or by a fork of a public one.</p>
<h2 id="how-does-copilot-studio-govern-mcp-servers">How does Copilot Studio govern MCP servers?</h2>
<p>Through Power Platform, at the environment level, by the server rather than by the tool.</p>
<p>Each tool runs on the end user's credentials by default, so the agent reaches only what that person can reach in the destination app. Maker-provided credentials are optional. An admin can forbid them per environment. That lockdown also breaks scheduled, autonomous and background agents, since those have no interactive user to authenticate as (checked October 2026, <a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/configure-no-maker-authentication">Microsoft Learn</a>).</p>
<p>Policy sits on the connector layer. Data policies sort connectors into Business, Non-business and Blocked, and cover an MCP server's tools too. Changes usually apply within an hour and can take up to 24 (checked October 2026, <a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-data-loss-prevention">Microsoft Learn</a>). Advanced connector policies are a default-deny allowlist per environment or group. Microsoft states that per-tool MCP control is not available in them (checked October 2026, <a href="https://learn.microsoft.com/en-us/power-platform/admin/advanced-connector-policies">Microsoft Learn</a>). The Microsoft 365 admin center approves, rejects and blocks MCP registrations under Agents, then Tools (checked October 2026, <a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/manage-plugins-skills-mcp-servers">Microsoft Learn</a>).</p>
<p>The practical consequence is one sentence long. A ticketing MCP server exposing a read tool and a delete tool is allowed whole or blocked whole at the policy layer. Makers can switch off single tools per agent at build time. That's a design choice inside one agent. It is not an administrative control an IT admin can apply across every agent that touches that server.</p>
<h2 id="what-does-a-governed-mcp-control-plane-enforce-instead">What does a governed MCP control plane enforce instead?</h2>
<p>This section describes Elaichi's specific implementation, not an industry standard. It is one way to build the generic pattern of RBAC plus resource-level sharing plus explicit allow/deny rules, and other gateways implement that pattern differently.</p>
<p>Three layers, and the finest of them reaches one tool for one role. Role-based access control (RBAC) comes first. It is 58 action strings such as <code>tool:execute</code>, <code>restriction:manage</code> and <code>audit:view</code>, grouped into roles. There is exactly one role per member, no stacking and no union of multiple roles. Resource sharing is second, and it is strict. A member sees only what they own or what was explicitly shared with them. There is no implicit visibility from being in the same team or role. Restrictions are third, and they are the layer that differs most from Copilot Studio's model. A restriction names whole connectors, single tools, or both. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. The default is allow, not deny: with no rule written, a tool is reachable by anyone who holds use on its connection.</p>
<p>So the ticketing case splits cleanly. A Support role carries an allow rule naming the read tools. The delete tool never reaches that role's list. A restricted tool is withheld from the tool list and cannot be called, and search names it, flagged restricted, with no schema. <a href="/blog/per-tool-vs-per-app-restrictions/">Choosing the grain</a> matters, because whole-app rules are sometimes the honest and lower-maintenance answer. Per-tool restrictions multiply the number of rules an admin has to keep correct as tools get added or renamed upstream.</p>
<p>Write the timing down before a reviewer asks. A role or restriction change takes effect within about two minutes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A SCIM deprovision suspends the member. That revokes every live grant at once, rather than waiting for a session or token to expire on its own.</p>
<p>Arguments can be pinned as well as tools. The connection's owner keeps it unshared, pins it into a toolbox entry with frozen values, and shares that toolbox at use. Frozen keys are stripped from the advertised schema, so the model has no input to fill in for them. Frozen values are merged over whatever the caller sends, overriding rather than just defaulting. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Pinning an argument</a> holds on the path that runs through the entry. It does not help if the same tool is reachable through a different, unpinned entry. Close that other path by leaving the connection unshared, because a restriction on the tool would withhold the frozen entry too.</p>
<p>Calls land in <a href="/blog/what-an-ai-audit-log-must-capture/">one audit log</a>. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</p>
<p>Here is what this model does not do. It has no low-code canvas for building a new agent. There is no conversation designer, and no equivalent of Copilot Studio's topic and trigger authoring. It governs clients that already exist; it does not help a team build one from scratch.</p>
<h2 id="copilot-studio-vs-mcp-gateway-a-side-by-side-table">Copilot Studio vs MCP gateway: a side-by-side table</h2>
<p>The two architectures diverge on audience, credential model, blocking granularity and billing unit. Read the table as a description of what each product was built for, including where each one is weaker, not as a scorecard.</p>
<table>
<thead>
<tr>
<th></th>
<th>Copilot Studio</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Built for</td>
<td>Makers building agents for Microsoft channels</td>
<td>IT governing the AI clients people already use</td>
</tr>
<tr>
<td>Where it runs</td>
<td>Microsoft Copilot, Microsoft Teams, other Microsoft channels</td>
<td>Claude, ChatGPT, Cursor, any MCP client</td>
</tr>
<tr>
<td>Tool sources</td>
<td>1500+ pre-built data connectors plus MCP servers you register (<a href="https://www.microsoft.com/en-us/copilot/products/copilot-studio">Microsoft</a>, checked October 2026)</td>
<td><a href="/connectors/">600+ connectors</a> served by Elaichi, most authored by it and some the vendor's own MCP server, with custom or forked connectors for apps outside the catalog</td>
</tr>
<tr>
<td>Credentials</td>
<td>End user by default, maker-provided optional</td>
<td>Each person signs in once with their own OAuth grant; calls run on their own connection or on a shared one</td>
</tr>
<tr>
<td>Finest block</td>
<td>A whole MCP server, per environment or group</td>
<td>A single tool, targeted at a role or a user</td>
</tr>
<tr>
<td>Policy timing</td>
<td>Data policy changes usually within an hour, up to 24 (<a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-data-loss-prevention">Microsoft</a>, checked October 2026)</td>
<td>Within about two minutes</td>
</tr>
<tr>
<td>Record</td>
<td>Purview CopilotInteraction events plus the Monitor page's Tool use view (<a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/admin-logging-copilot-studio">Microsoft</a>, checked October 2026)</td>
<td>one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account reached</td>
</tr>
<tr>
<td>Can build new agents</td>
<td>Yes, the product's core function</td>
<td>No, it governs existing clients only</td>
</tr>
<tr>
<td>Setup per app</td>
<td>Add the connector or MCP server to each agent</td>
<td>Connect each SaaS account once; every client reaches it</td>
</tr>
<tr>
<td>Price</td>
<td>Copilot Credits, $200 a month for a 25,000-credit pack; Microsoft 365 Copilot at $30 per user per month includes internal agents on the standard and Copilot chat harnesses for licensed users (<a href="https://www.microsoft.com/en-us/copilot/pricing/copilot-studio">Microsoft</a>, checked October 2026)</td>
<td>Gold at $15 per user per month, USD list (<a href="/pricing/">pricing</a>)</td>
</tr>
</tbody>
</table>
<p>There is no free Elaichi plan: two plans, Gold and Black. Elaichi offers a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<h2 id="where-does-microsoft-agent-365-fit">Where does Microsoft Agent 365 fit?</h2>
<p>Microsoft is building a cross-client gateway of its own. The part relevant here is still in preview. That matters if you're deciding whether to wait for it.</p>
<p>Agent 365 has been generally available since 1 May 2026. The price is $15 per user per month, or included in Microsoft 365 E7 (<a href="https://www.microsoft.com/en-us/microsoft-agent-365">Microsoft</a>, checked October 2026). Its tooling gateway for registered bring-your-own MCP servers is a preview feature within that product. Admins approve and block servers at runtime. The preview clients include Copilot Studio, VS Code, Claude Code and GitHub Copilot CLI. Tool-level blocking for those servers is planned but not shipped. Gateway tool calls can be hunted in Defender (checked October 2026, <a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/manage-byo-mcp-server">Microsoft Learn</a>). Azure API Management is positioned separately, to expose and govern MCP servers for ChatGPT, Claude and GitHub Copilot (<a href="https://learn.microsoft.com/en-us/azure/api-management/mcp-server-overview">Microsoft Learn</a>, checked October 2026).</p>
<p>If the plan is to wait for Microsoft's gateway, the question to settle is narrow and concrete. Does server-level approval, whole server with no per-tool block yet, cover the review you have to pass this quarter. Do you need per-tool control before Microsoft ships it. Nobody outside Microsoft has a date for that.</p>
<h2 id="when-copilot-studio-alone-is-the-right-answer">When Copilot Studio alone is the right answer</h2>
<p>Plenty of companies <a href="/blog/when-you-dont-need-an-mcp-gateway/">do not need a second control plane</a>, and should not buy one.</p>
<p>If your people only use Microsoft Copilot and Teams, Copilot Studio reaches the apps. Power Platform holds the policy, and Purview holds the record (<a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/admin-logging-copilot-studio">Microsoft Learn</a>, checked October 2026). Your admins already run those consoles. A second product would add a second place for the rules to be wrong, and a second audit trail to reconcile during a review. The same logic holds for one team using one assistant against one app. That app's own MCP server, under its own permission model, is less to carry and needs no extra vendor.</p>
<p>The boundary moves the moment a non-Microsoft client appears on a laptop. <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">A Cursor install</a> or a ChatGPT workspace sits outside Power Platform, and the rules written there do not follow it. Power Platform's policies do not reach a connection made directly from Cursor to a third-party MCP server.</p>
<h2 id="running-both-without-the-rules-drifting-apart">Running both without the rules drifting apart</h2>
<p>Most companies that use Microsoft will run both. Decide early which surface owns which rule, in writing. Do that before the second product is purchased rather than after.</p>
<p>Copilot Studio owns agents built for Teams and Microsoft Copilot, governed by Power Platform data policies and connector allowlists. The MCP control plane owns Claude, ChatGPT, Cursor and the rest. It is governed by one role per person, restrictions down to a tool, and a single audit trail. The two do not overlap by accident. Elaichi does not list Copilot Studio among the clients it connects with. Agents built there stay on Power Platform's side of the line. Name the owner of each half and the review cadence for each. Quarterly connector audits in Power Platform, for instance. A separate cadence covers restriction rules in the MCP control plane.</p>
<p>For the category definitions underneath all of this, <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a> is the place to start. <a href="/blog/what-is-an-mcp-gateway/">The four gateway shapes</a> sorts the rest of the market.</p>
<h2>FAQ</h2><dl><dt><strong>Can Copilot Studio block a single tool inside an MCP server?</strong></dt><dd>Power Platform advanced connector policies act as a default-deny allowlist per environment or group and block a whole MCP server, and Microsoft states that per-tool MCP control is not available in them (checked October 2026). Makers can switch off individual tools when building a given agent, and tool-level control inside a server is rolling out for servers registered on Agent 365.</dd><dt><strong>Can Claude, ChatGPT or Cursor use an agent built in Copilot Studio?</strong></dt><dd>Microsoft documents no way to expose a Copilot Studio agent to Claude, ChatGPT or Cursor as an MCP server (checked October 2026). Reaching those clients means giving them an MCP endpoint of their own to sign into, which is what a governed MCP control plane such as Elaichi provides.</dd><dt><strong>How is Microsoft Agent 365 different from Copilot Studio?</strong></dt><dd>Copilot Studio is an environment for building agents that run in Microsoft channels. Agent 365 is marketed as a control plane for agents, generally available since 1 May 2026 at $15 per user per month or included in Microsoft 365 E7; its tooling gateway for registered bring-your-own MCP servers is a preview in which admins approve and block whole servers at runtime (checked October 2026).</dd><dt><strong>How quickly does a restriction change take effect in Elaichi?</strong></dt><dd>A role or restriction change in Elaichi takes effect within about two minutes. Revoking an OAuth grant, removing a member or suspending one is effective on that person's next call, and so is revoking a share or disconnecting a connected account.</dd><dt><strong>Do AI clients need separate credentials with an MCP control plane?</strong></dt><dd>No. With Elaichi, every client points at the same organization-wide MCP endpoint and each person signs in over OAuth, picking scopes on a consent screen. There are no per-toolbox URLs and no embedded tokens to distribute to clients or employees.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>ClickUp in ChatGPT for a customer success team</title>
      <link>https://elaichi.ai/blog/customer-success-chatgpt-clickup-tasks/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/customer-success-chatgpt-clickup-tasks/</guid>
      <description>Two decisions put ClickUp in ChatGPT for a customer success team: whose account each call runs on, and which ClickUp tools are restricted.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Putting ClickUp in ChatGPT for a customer success team comes down to two decisions in Elaichi. First, identity: each CSM connects their own ClickUp account, so ClickUp's own sharing decides what each call can see. Second, scope: block the ClickUp delete tools and the guest and user tools on the team's role, then share a template at use so every person stamps a toolbox bound to their own connection.</aside>
<h2 id="how-do-you-set-up-clickup-in-chatgpt-for-a-team">How do you set up ClickUp in ChatGPT for a team?</h2>
<p>Two decisions, then menu paths. Whose ClickUp account each call runs on, and which ClickUp tools the model can reach at all. Both are instances of a general MCP governance problem, not something specific to ClickUp. Any time you connect a chat client to a multi-user app through MCP, you have to decide two things. First, identity resolution: which backend credential a given call executes under. Second, tool surface: which of the connector's available operations are reachable at all. Setting up ClickUp in ChatGPT for a whole team is a governance question before it is a configuration one.</p>
<p>The situation is familiar. A customer success team runs client onboarding in ClickUp, one space or folder per account. The CSMs want to ask ChatGPT what is overdue on the Acme rollout. They also want it to update a task status, and to draft the weekly summary from the list. One person can do that today by signing in to ClickUp's own hosted server. Doing it for eight CSMs, with client data sitting in those spaces, is where the shape changes. Identity resolution and tool surface now have to hold across eight people instead of one.</p>
<p>This playbook uses Elaichi, a governed MCP control plane, as the worked example. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected account through one organization-wide endpoint, <code>POST https://api.elaichi.ai/mcp</code>, behind OAuth. OAuth is the browser sign-in flow that issues a client a standing, revocable permission to call on a person's behalf. A static API key, by contrast, has no per-person revocation and no expiry tied to a session. <a href="/connectors/clickup/">ClickUp</a> is one of the 600+ connectors in the catalog.</p>
<p>The order of work: write the restriction first, build and share a template second. Then let each CSM connect ClickUp, and add the endpoint in ChatGPT last. Skipping ahead and connecting accounts before the restriction exists leaves an unrestricted delete tool live in production before anyone notices.</p>
<h2 id="whose-clickup-account-does-each-call-run-on">Whose ClickUp account does each call run on?</h2>
<p>Whichever connection the call resolves to. A connection shared with the team runs on its owner's credential, so every grantee's call reaches ClickUp as that one account. Get it wrong and permissions widen for everyone downstream of the share.</p>
<p>That matters more in ClickUp than in most apps, because ClickUp spaces are usually where client separation lives. If one ops lead connects ClickUp and shares the connection with the customer success team, ClickUp evaluates the ops lead's permissions on every call. A CSM who cannot open the Acme space in ClickUp can read it through that connection, in ChatGPT, with nothing misconfigured. The share is working as designed. The failure is in the sharing decision, not the software.</p>
<p>For a customer success team, pick the other shape:</p>
<ul>
<li><strong>Per-person connection (recommended for this case).</strong> Each CSM connects ClickUp in Elaichi with their own ClickUp account. The Member role already holds <code>connection:create</code>, so nobody waits on an admin. ClickUp's own sharing then decides what each call can see, per person, with no second permission model to keep in step.</li>
<li><strong>Shared connection (correct only for a deliberate single view).</strong> A single reporting account that sees every client space, shared at <code>use</code> for a weekly rollup, is a reasonable thing to own. It should be a named decision with a named owner, not the default because it was the first thing someone set up.</li>
</ul>
<p>Rule of thumb: some apps already enforce per-record access control, such as ClickUp spaces, Zendesk ticket permissions and <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Salesforce sharing rules per rep</a>. Default to per-person connections there, and let that app's permission model do the work. Only use a shared connection when you want a view that deliberately ignores those boundaries.</p>
<h2 id="which-clickup-tools-should-a-customer-success-role-never-reach">Which ClickUp tools should a customer success role never reach?</h2>
<p>The destructive ones and the access-granting ones. Block ClickUp's delete tools for tasks, lists, folders and spaces, plus the tools that create, update or remove guests and users.</p>
<table>
<thead>
<tr>
<th>Tool category</th>
<th>Example ClickUp operations</th>
<th>Why block for CSM role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Deletes</td>
<td>delete task, delete list, delete folder, delete space</td>
<td>Irreversible; a misread instruction ("clear out the old onboarding list") becomes data loss, not a conversation to correct</td>
</tr>
<tr>
<td>Guest/user management</td>
<td>add guest, remove guest, create user, change user role</td>
<td>Looks like a routine task update in a transcript but is actually an access-control decision: it shares client work outside the company</td>
</tr>
<tr>
<td>Reads (task, list, comment)</td>
<td>get task, list tasks, get comments</td>
<td>Needed for the core use case; leave open</td>
</tr>
<tr>
<td>Task/comment writes</td>
<td>update task status, create comment, update due date</td>
<td>Needed for the core use case; leave open</td>
</tr>
</tbody>
</table>
<p>The deletes are the obvious half of the table. The guest tools are the half teams forget. "Add a guest to this task" reads exactly like "update this task", in both the UI and in a model's tool-call log. There is no visual or semantic marker that distinguishes a data operation from an access-grant operation unless you block it explicitly.</p>
<p>A restriction is the rule for which connectors and tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Write the block against the role the customer success team holds, which on the Gold plan can be a custom role. A block beats an allow. A block matches the tool's advertised name, or the operation pinned against the catalog when the rule was written. An allow matches the pinned operation only. That asymmetry has its own writeup in <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match names and allows do not</a>.</p>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged as restricted, with no schema. The model has no description or schema to reason around, and no way to run it. A role or restriction change takes effect within about two minutes.</p>
<p>Resist the urge to write an allowlist instead, unless you mean it. The allowlist stage activates on the presence of an allow rule, not its contents. So an allow rule naming nothing denies everything, which locks the role out of every tool. For a team whose work is open-ended across client spaces, a short block list ages better than a long allow list. A long allow list runs to dozens of entries, one per permitted operation, and needs updating every time the connector adds a tool. The cases where one or the other wins are set out in <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool or the whole app</a>.</p>
<h2 id="why-share-a-template-instead-of-one-toolbox">Why share a template instead of one toolbox?</h2>
<p>Because a template carries no connection and a toolbox does. Share a template at <code>use</code> and each CSM stamps their own toolbox, bound to their own ClickUp account. Share one toolbox at <code>use</code> and every call runs on the connection pinned in its entries, which belongs to the owner, not the grantee.</p>
<table>
<thead>
<tr>
<th>Object</th>
<th>Carries a connection?</th>
<th>What sharing it does</th>
</tr>
</thead>
<tbody>
<tr>
<td>Template</td>
<td>No</td>
<td>Each grantee stamps their own toolbox, pinned to their own connections</td>
</tr>
<tr>
<td>Toolbox</td>
<td>Yes (per entry)</td>
<td>Every grantee's calls run on the connection the owner pinned</td>
</tr>
</tbody>
</table>
<p>A template in Elaichi is a tool list with renames, defaults and frozen parameters, and no connection anywhere in it. Build one holding the ClickUp reads a CSM needs, plus task and comment create and update. Share it with the customer success team at <code>use</code>.</p>
<p>When a CSM stamps it, the new toolbox belongs to them. Each entry is filled from connections that person can use, with them recorded as the delegator. An entry with no usable connection sits as "needs connection", exactly what a CSM who has not connected ClickUp yet will see. The fix is to connect ClickUp and re-pin.</p>
<p>The trade-off is real: stamping copies the template once, at that moment. A later edit to the template never reaches a toolbox already stamped. Adding a tool for the team means editing each toolbox individually or asking people to re-stamp. For an 8-person team, that is 8 manual touches per template change, a real maintenance cost, not a hypothetical one. That is the price of per-person connections. For a team handling client data it is usually worth paying, against an alternative of one shared connection and zero per-person isolation.</p>
<h2 id="how-does-an-admin-add-the-endpoint-in-chatgpt">How does an admin add the endpoint in ChatGPT?</h2>
<p>One URL, added once, then each CSM signs in and gets their own OAuth grant. Nobody types a token and nobody gets a personal URL.</p>
<p>As of this writing, full MCP support including write actions in ChatGPT is in beta for Business, Enterprise and Edu plans. On Business, only admins can enable developer mode (source: <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help center, "Developer mode and MCP apps in ChatGPT"</a>). Check that page directly before rollout, since OpenAI states the feature, UI, and permission model may change. The admin creates the app under Workspace settings, then Apps, then Create, provides the endpoint, clicks Scan Tools, completes the OAuth prompt, and publishes it. It then appears in members' Apps settings labeled "custom."</p>
<p>The endpoint is <code>https://api.elaichi.ai/mcp</code>, typed exactly. With a trailing slash it answers 404 and never starts sign-in.</p>
<p>Each CSM then signs in and lands on Elaichi's consent screen with four checkboxes:</p>
<ol>
<li>Read your organization's data</li>
<li>Create and change data</li>
<li>Run your connected tools</li>
<li>Delete data and remove access</li>
</ol>
<p>Delete is never pre-ticked, and for this team it should stay unticked. There is no legitimate case for a CSM's ChatGPT session to need delete-and-revoke permission. With "run your connected tools" ticked, a second step asks which toolboxes to expose. Choose "only the ones I pick" and select the stamped ClickUp toolbox, rather than "all my tools". All my tools would expose every toolbox the person has access to, including ones unrelated to this rollout.</p>
<p>One behavior to flag in advance: connected tools are never listed in <code>tools/list</code>, however few there are. The model finds a ClickUp tool with <code>search_tools</code> and runs it with <code>execute_tool</code>. A CSM may open the app list, see no ClickUp tools listed, and file a support ticket. That is normal behavior, not a broken connection. The step-by-step walkthrough is in <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>, and the sign-in failures worth recognizing are listed in <a href="/blog/mcp-oauth-errors/">fixing OAuth errors</a>.</p>
<h2 id="who-can-reach-a-clickup-connection-once-it-is-in-use">Who can reach a ClickUp connection once it is in use?</h2>
<p>Everyone the connection itself is shared with, plus everyone holding <code>use</code> on a toolbox that pins it. A member sees only what they own or what was explicitly shared with them. No organization-level permission widens that listing, owners and admins included. This is a deliberate design choice. Visibility into a connection and capability to use it are separated, so granting the latter never silently grants the former.</p>
<p>The second clause is the one that surprises people. Pinning a connection into a toolbox and sharing the toolbox hands out the <em>capability</em> without handing out the <em>connection</em>. The grantee runs the entry and cannot open, see, or share the connection underneath it. The call still reaches ClickUp as the owner's account. They just cannot inspect or redirect it.</p>
<p>So for a per-person setup, the rule is short: each CSM leaves their own ClickUp connection unshared. If someone shares theirs with the whole team, every teammate's "all my tools" grant picks it up. That includes connections shared <em>after</em> the grant was originally made, since the resolution happens at call time, not grant time.</p>
<p>Each toolbox entry also records who pinned it, re-checked on every call. Worked example: a CSM pins their ClickUp connection into a shared toolbox, then goes on leave and is suspended via SCIM. From that point, every grantee's call against that entry resolves as unmet until someone currently present re-pins it with their own connection. The toolbox does not silently fail over to another account. Offboarding surfaces these as a non-blocking warning. A private connection pinned by a toolbox its owner shared blocks removal, until an administrator decides what happens to it.</p>
<p>Timing differs by layer. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A role or restriction change takes effect within about two minutes.</p>
<h2 id="what-does-the-audit-trail-show-after-a-task-changes">What does the audit trail show after a task changes?</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the ClickUp account actually reached. The recorded connection comes from the execution, not from the intent. So "which workspace did it write to" has a verifiable answer rather than an inferred one.</p>
<p>Concretely: you can prove that a CSM's ChatGPT session updated a specific task on their own ClickUp account. It happened at a specific timestamp, via a specific tool call. You cannot read the comment text out of the audit trail. The log records that a write happened and to what object, not the content written, by design.</p>
<p>A call arriving from ChatGPT is recorded with the surface <code>mcp</code> and the OAuth client named. ChatGPT's client identity is marked verified, because its redirect URIs prove it. The <code>ai_assistant</code> actor kind marks the in-app Elaichi Agent only. Do not expect to find it on ChatGPT-originated rows. The approval line reads "allowed by the access ChatGPT was granted." Over MCP, the grant the person approved during OAuth consent is the human decision being referenced, not a per-call approval.</p>
<p>A restricted tool is never advertised, so the audit signal for "deletes are off" is absence rather than a stream of denied attempts. The evidence is the restriction itself, plus the absence of any delete in the trail. A compliance reviewer can hold the free read-only Auditor seat to check both the restriction and the trail. That is the shape described in <a href="/blog/shadow-ai-security-lead-access-review-evidence/">proving AI actions in access review evidence</a>.</p>
<h2 id="when-is-clickups-own-mcp-server-enough">When is ClickUp's own MCP server enough?</h2>
<p>When ClickUp is the only system your team needs inside ChatGPT, and per-user ClickUp permissions are the whole access control you want. In that case, connect ClickUp's server directly and stop here. Adding a control plane buys you nothing in a single-app, single-permission-model setup.</p>
<p>ClickUp hosts a server at <code>https://mcp.clickup.com/mcp</code>, connected via OAuth. ClickUp's developer docs list the supported clients. They name Claude, ChatGPT, Cursor, VS Code, Windsurf and Microsoft Copilot Studio (<a href="https://developer.clickup.com/docs/connect-an-ai-assistant-to-clickups-mcp-server-1">ClickUp developer docs, "Connect an AI assistant to ClickUp's MCP server"</a>, checked October 2026). Per ClickUp's own guide, checked October 2026, it is available on all plans including Free Forever. Calls stay within the account's existing permissions. Personal API keys and access tokens are not accepted as credentials. Without the Everything AI add-on, daily call volume is capped by plan. The cap runs from 100 calls/24h on Free Forever to 5,000 calls/24h on Enterprise (<a href="https://clickup.com/blog/how-to-use-clickup-mcp-server/">ClickUp blog, "How to use ClickUp's MCP server"</a>). Verify current caps and plan terms directly with ClickUp before relying on these numbers. Usage limits are the kind of detail vendors change without much notice.</p>
<table>
<thead>
<tr>
<th>Need</th>
<th>ClickUp's native MCP server</th>
<th>A control plane (Elaichi or similar)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Single app (ClickUp only)</td>
<td>Sufficient</td>
<td>Unnecessary overhead</td>
</tr>
<tr>
<td>Multiple apps in one chat client (ClickUp + Zendesk + Salesforce)</td>
<td>Not described on ClickUp's pages</td>
<td>One endpoint, one policy layer across connectors</td>
</tr>
<tr>
<td>Tool-level restriction beyond ClickUp's own role permissions (e.g., block deletes for a role that otherwise has delete access in ClickUp)</td>
<td>Not described on ClickUp's pages</td>
<td>Supported via restrictions</td>
</tr>
<tr>
<td>Centralized audit trail across apps</td>
<td>Not described on ClickUp's pages</td>
<td>Single trail across all connected apps</td>
</tr>
<tr>
<td>Offboarding</td>
<td>Deprovision in ClickUp or your IdP; no secondary layer to clear</td>
<td>Removing someone in the control plane ends access <em>through the control plane</em>; the underlying ClickUp account still needs separate deprovisioning</td>
</tr>
</tbody>
</table>
<p>Be precise about that last row: removing someone in Elaichi ends their access through Elaichi. Their ClickUp account still exists and still needs to be deprovisioned in ClickUp or through your identity provider. A control plane does not replace offboarding discipline; it adds a layer that also needs clearing.</p>
<p>For the wider picture of what sits between AI clients and company apps, start with <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For the same two decisions made in a support queue, read how a <a href="/blog/support-team-claude-zendesk-tickets/">support team gets Zendesk without bulk deletes</a>. The apps on offer are listed in the <a href="/connectors/">connector catalog</a>, and the team-by-team shapes are on <a href="/use-cases/">use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can each person use their own ClickUp account when ClickUp is connected to ChatGPT through Elaichi?</strong></dt><dd>Yes. Each person connects ClickUp in Elaichi with their own ClickUp account, and an admin shares a template, a tool list that carries no connection, with the team at use. Each person stamps their own toolbox from that template, and stamping binds every entry to a connection that person can use. A toolbox shared directly is the opposite case: every grantee's call runs on the connection pinned in its entries, which belongs to the owner.</dd><dt><strong>How do you stop ChatGPT from deleting ClickUp tasks?</strong></dt><dd>Write a restriction on the role the team holds that blocks the ClickUp delete tools, such as delete_a_clickup_task_by_id, delete_a_clickup_list_by_id, delete_a_clickup_folder_by_id and delete_a_clickup_space_by_id. In Elaichi a restricted tool is withheld from the tool list and cannot be run. If the assistant searches for it, it sees only the name, flagged as restricted. Restrictions target a role or a user, and a change takes effect within about two minutes.</dd><dt><strong>Why block ClickUp's guest tools for a customer success team?</strong></dt><dd>Adding a guest to a task shares client work outside the company, which is an access decision rather than a project update. Blocking create_a_clickup_guest, clickup_guests_add_to_task, create_a_clickup_user and their update and delete counterparts keeps that decision with whoever administers the ClickUp workspace, instead of putting it one sentence away in a chat window.</dd><dt><strong>Does ClickUp have its own MCP server, and when is it enough?</strong></dt><dd>Yes. ClickUp hosts a server at https://mcp.clickup.com/mcp, connected with OAuth, and its own guide dated 8 September 2026, checked October 2026, says it is available on all plans including Free Forever and that what an AI client does stays within your account's existing permissions. It is enough when ClickUp is the only system your team needs in ChatGPT and per-user ClickUp permissions are the only control you want. A control plane adds one address across apps from different vendors, restrictions written once for a role across those apps, and one audit trail across them.</dd><dt><strong>What does Elaichi's audit trail record for a ClickUp call made from ChatGPT?</strong></dt><dd>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the ClickUp account actually reached, taken from the execution rather than the intent. The entry holds the operation and tool, the connection, the classification, whether it was approved, the outcome and an error code only. It holds no argument values, with one exception: the one path argument that names the object is recorded as the target id. The entry records the surface as mcp and names the OAuth client, and ChatGPT's name is marked verified because its redirect URIs prove it.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>QuickBooks read-only for a finance team in Claude</title>
      <link>https://elaichi.ai/blog/finance-team-claude-quickbooks-read-only/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/finance-team-claude-quickbooks-read-only/</guid>
      <description>QuickBooks has no read-only OAuth scope, so QuickBooks read-only has to be enforced by whatever calls the API. Here is how to do it with one restriction.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> QuickBooks Online has no read-only accounting scope, and only QuickBooks admins connect apps, so read-only cannot come from Intuit or from the person who connects. In Elaichi you get QuickBooks read-only by writing an allow rule on the finance role that names the QuickBooks read tools, plus every other app the finance team needs, because an allow rule denies every connector and tool it does not name. It is not a consent checkbox, because "Run your connected tools" runs a connected app's writes as well as its reads.</aside>
<h2 id="why-quickbooks-read-only-cannot-come-from-the-oauth-scope">Why QuickBooks read-only cannot come from the OAuth scope</h2>
<p>A controller wants the monthly profit and loss inside Claude, and nobody wants an AI client editing an invoice. QuickBooks read-only is not a setting you can turn on in QuickBooks. QuickBooks Online has exactly one accounting OAuth scope, <code>com.intuit.quickbooks.accounting</code>, and it covers reads and writes together. There is no read-only variant. Intuit's own developer documentation on scopes confirms this (<a href="https://developer.intuit.com/app/developer/qbo/docs/learn/scopes">developer.intuit.com</a>). Intuit Developer Support's answer to "how do I make my app read-only" is that the app itself should only issue GET requests (<a href="https://help.developer.intuit.com/s/question/0D5TR00001FvXDB0A3/how-can-i-give-an-api-read-access-only">help.developer.intuit.com</a>, checked October 2026). The restraint has to sit in whatever calls the API, not in anything Intuit issues at authorization time.</p>
<p>The person who connects does not impose it either. Whoever authorizes the app grants the whole accounting scope to that app, for that company file, full stop. There is no per-user scope narrowing in QuickBooks' OAuth implementation. So a QuickBooks connection carries admin-level read/write reach regardless of who is asking the resulting question through an AI client.</p>
<p>The consent screen does not impose it. On Elaichi's screen, ticking "Run your connected tools" enables a connected app's read and write tools alike. The checkbox does not distinguish by HTTP verb. Only a tool whose underlying method is a delete requires the separate "Delete data and remove access" box, which is never pre-ticked. "Create and change data" governs Elaichi's own control-plane operations (Elaichi's own records, such as connections and toolboxes). It has nothing to do with what the QuickBooks tools themselves can do. Do not tell a finance team that leaving a box unticked made their books read-only; it did not.</p>
<p>What does impose it is a restriction in Elaichi, the governed MCP control plane your clients call. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A restriction is a rule naming which connectors and which individual tools a role or a person may reach. It is checked at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. This is the only layer in the stack where a read/write distinction can be enforced per person or per role. It sits ahead of QuickBooks, the consent screen and the client.</p>
<h2 id="register-the-intuit-app-and-store-it-in-elaichi">Register the Intuit app and store it in Elaichi</h2>
<p>Open the <a href="/connectors/quickbooks/">QuickBooks connector</a> in Elaichi's sidebar under Connectors. If the card titled <strong>Add your OAuth application</strong> is there, the organization supplies its own Intuit app before anyone connects. That takes <code>connector:manage</code>, held by Org Owner and Org Admin by default.</p>
<p>Create the app in Intuit's Developer Portal, under My Hub then App dashboard. Apps are not created inside QuickBooks itself. Production keys arrive only after Intuit approves an app assessment questionnaire; private, single-company apps need that review too (<a href="https://developer.intuit.com/app/developer/qbo/docs/get-started/get-client-id-and-client-secret">developer.intuit.com</a>). Budget for that review cycle in your rollout plan rather than discovering it is a blocker on launch day.</p>
<p>In Elaichi, press <strong>Add OAuth app</strong>. Copy the read-only <strong>Redirect URL</strong> field with its copy button and paste it into the Intuit app's redirect URIs. Production redirect URIs in Intuit's implementation must be HTTPS, must match the registered string exactly (no trailing slash variance), and cannot carry query parameters (<a href="https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/set-redirect-uri">developer.intuit.com</a>). Fill in <strong>Client ID</strong> and <strong>Client secret</strong>. Leave Scopes blank to keep the scopes Elaichi requests by default. A typed list replaces them wholesale. For QuickBooks it buys nothing, because the one accounting scope carries writes. Press <strong>Save OAuth app</strong>; the change lands in the audit trail as <code>connector.oauth_app.updated</code>, attributed to the admin who made it.</p>
<p>Nothing in the Scopes box buys read-only here. QuickBooks has one accounting scope and it carries writes (<a href="https://developer.intuit.com/app/developer/qbo/docs/learn/scopes">developer.intuit.com</a>). Token refresh is not the finance team's job either. Elaichi's credential service owns refresh, and a failed refresh marks the connection <code>needs_reauth</code> rather than failing silently.</p>
<h2 id="connect-the-books-once-then-share-them-with-finance">Connect the books once, then share them with finance</h2>
<p>A QuickBooks admin connects the company file once in Elaichi, and that single connection is shared with the finance team at <code>use</code>. A shared connection runs on its owner's credential, so every finance member's call reaches QuickBooks as that admin account from Intuit's point of view. Elaichi still records which member made each call that runs, on its own side. So the audit trail does not collapse into one name, even though QuickBooks only ever sees one.</p>
<p>Use a connection share, not a template, for this shape. A template shared at <code>use</code> gives each person a toolbox bound to their own connection. That is correct when every member holds their own login in the underlying app, as with <a href="/blog/sales-team-chatgpt-salesforce-accounts/">per-rep Salesforce access in ChatGPT</a>. Finance has one set of books and typically one QuickBooks login. So one connection shared to the team is the correct unit, not one template per person.</p>
<p>Pick an owner who will stay. When an owner leaves, Elaichi's offboarding lists every connection they own. A shared connection the team depends on is deleted only if an admin explicitly asks for that. Otherwise the admin transfers it to another member. A transfer leaves every share exactly as it was. The credential behind the connection is still that person's sign-in to QuickBooks, so the QuickBooks side still needs its own deprovisioning.</p>
<h2 id="pointing-the-finance-teams-clients-at-the-endpoint">Pointing the finance team's clients at the endpoint</h2>
<p>Every organization uses the same address: <code>POST https://api.elaichi.ai/mcp</code>. Copy it exactly, with no trailing slash. Each member connects their own client and signs in, so each person holds their own OAuth grant against Elaichi. This is the identity Elaichi uses to attribute calls, independent of the shared QuickBooks credential underneath.</p>
<p>On Claude Team and Enterprise, an Owner adds it under Organization settings, then Connectors, then Add, then Custom, then Web. Members then connect it under Customize, then Connectors (<a href="https://support.claude.com/en/articles/11175166">support.claude.com</a>). Note what Claude's per-tool permissions can and cannot do here. Elaichi's connected tools all route through a single Claude-visible tool, <code>execute_tool</code>. So a permission Claude lets you set on "that one tool" actually covers every connected tool across every connector at once. Claude cannot distinguish a QuickBooks report read from a QuickBooks invoice write at its own permission layer. That distinction exists only in Elaichi's restrictions, not in Claude's connector settings. Full walkthrough: <a href="/blog/connect-elaichi-to-claude/">connecting Elaichi to Claude</a>.</p>
<p>ChatGPT Business, Enterprise and Edu have the same shape of limit. An admin publishes Elaichi as one custom app. The per-action read/write switches ChatGPT exposes sit on that single app, not on the individual tools or connectors behind it (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">help.openai.com</a>). The admin-side steps are in <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup walkthrough</a>. In both Claude and ChatGPT, the client's native permission UI is too coarse to do the job. The enforcement has to happen in Elaichi regardless of which client you use.</p>
<h2 id="write-the-allow-rule-that-names-the-read-tools">Write the allow rule that names the read tools</h2>
<p>One allow rule on the finance role, naming the QuickBooks read tools the team actually uses, gives you QuickBooks read-only. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. The rule is the role's whole allowlist, not a QuickBooks filter. Once the finance role holds an allow rule, every connector and every tool that rule does not name is denied for that role. So the same rule must also name every other app the finance team uses. Whole connectors are fine for those. Otherwise the team loses those apps too. Name the reports they ask for (profit and loss, balance sheet), plus read operations over accounts, bills, vendors, invoices and customers. Every create, update and delete tool on the QuickBooks connector falls away without being individually blocked.</p>
<p>Four things to get right:</p>
<ol>
<li>
<p><strong>Restriction targets are role or user only.</strong> There is no organization target and no team target. Finance needs its own role, and each member holds exactly one role. A finance analyst is a Finance role holder, not also a generic Member with broader reach. Custom roles are a Gold-tier feature; see the <a href="/pricing/">pricing page</a> for current plan contents. For how to shape the role itself, see <a href="/blog/designing-roles-for-ai-agents/">designing roles for AI agents</a>.</p>
</li>
<li>
<p><strong>Do not name the whole QuickBooks connector and some of its tools in the same allow rule.</strong> The whole-connector entry wins and grants reach to all of QuickBooks; the tool-level entries in the same rule grant nothing additional. That is a silent over-permission if it saves. In practice Elaichi's API rejects the overlap on new rule creation rather than saving a rule that looks narrow but is not.</p>
</li>
<li>
<p><strong>Allow rules match the operation pinned against the catalog at write time, not the advertised tool name; blocks match either.</strong> This asymmetry matters if a connector's tool names change upstream. Full reasoning: <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match names and allows do not</a>.</p>
</li>
<li>
<p><strong>A new rule is not instant.</strong> A restriction change takes effect within about two minutes. Do not test a new rule one second after saving. If the read tool still looks restricted immediately after you hit save, that is expected, not a bug.</p>
</li>
</ol>
<p>If you would rather block the handful of dangerous writes than allowlist the reads, that trade-off is laid out elsewhere. See <a href="/blog/per-tool-vs-per-app-restrictions/">restrict one tool or the whole app</a>. For books specifically, the allowlist is the safer default. A new QuickBooks write tool added to the connector later is denied by an allowlist automatically, with no rule edit required. A blocklist has to be updated every time the connector's tool set grows.</p>
<h2 id="check-it-from-a-finance-account-before-telling-the-team">Check it from a finance account before telling the team</h2>
<p>Sign in from a test account that holds the finance role and search. In Elaichi, connected tools are never listed one by one, however few there are. So the verification method is a search, not a browse. Ask the client for "invoice" and you should see something like <code>get_single_quickbooks_invoice_by_id</code> or <code>list_all_quickbooks_invoices</code> returned. The create and update tools can come back only by name, flagged restricted, with no schema. They cannot be called.</p>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no description or schema, so a test account can tell a restricted tool from one that never existed. Reading the rule behind the restriction requires an account holding <code>restriction:view</code>. The built-in Auditor role has it and a default Member does not. The Auditor seat is free and strictly read-only on the control plane itself.</p>
<p>Then run a profit and loss and read the resulting audit entry. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The entry also names the surface the call arrived on: Claude through the Elaichi connector, versus the Elaichi web Agent. It names the specific OAuth client it came through too. That is useful when the same person uses both Claude and ChatGPT against the same QuickBooks connection. You need to tell which session asked for what.</p>
<p>When somebody needs a write tool later, they file an access request, which any member can do with no permission required to initiate it. An admin approves it in the console, under Governance, then Access requests. Approval creates an access grant for that one person. The grant lifts exactly the approved tool out of their role rules. Every other role rule keeps applying, nobody else changes, no rule is written and the Finance role is not edited. Those approvals cannot be made from an MCP client or the Elaichi Agent itself. They must go through Elaichi's own admin surface. The separation is deliberate, so a compromised or over-eager AI session cannot self-approve its own elevated access.</p>
<h2 id="intuits-monthly-cap-on-read-calls">Intuit's monthly cap on read calls</h2>
<p>Every app sits on Intuit's free Builder tier by default. That tier caps data-out calls at 500,000 per month per app. Calls past the cap return an error rather than being queued or throttled gracefully (<a href="https://developer.intuit.com/app/developer/qbo/docs/get-started/partner-faq">developer.intuit.com</a>). Read-only access does not exempt you from this. Every read call your team makes still counts against that single number, shared across the whole company file connection.</p>
<p>AI clients are chatty. One question about a quarter can become several report calls: one per report type, sometimes one per month if the model paginates naively. A model that gets a truncated result may re-ask for the same data, assuming it failed rather than was trimmed. Elaichi caps a result at 32,000 characters per string and 200 items per array, and sets <code>elaichi_truncated: true</code> on the response when it cuts data. That is a signal your client should use to request a narrower query, not retry the same one. Elaichi also rate-limits a single token to 120 MCP requests per minute independent of Intuit's monthly cap. Narrow allow rules help on both counts: a tool nobody can call is a call nobody makes, which directly reduces pressure on Intuit's 500,000-a-month ceiling.</p>
<h2 id="when-intuits-own-quickbooks-options-fit-better">When Intuit's own QuickBooks options fit better</h2>
<p>Sometimes the honest answer is that <a href="/blog/when-you-dont-need-an-mcp-gateway/">you do not need a control plane</a>.</p>
<p>Intuit hosts a QuickBooks connector for Claude (announced April 2026). Intuit's own help documentation states it is for US customers, and that destructive actions require the user's explicit confirmation at the moment of the call. Its tool listing covers both reads and writes across invoices, estimates, customers and reports (<a href="https://quickbooks.intuit.com/learn-support/en-us/help-article/accounting-bookkeeping/use-quickbooks-connector-claude/L3YBlo6Ht_US_en_US">quickbooks.intuit.com</a>). You may be a US business where one or two people use it. If you actively want Claude to draft invoices rather than just read reports, that is the faster path to set up. A confirmation prompt asks the person in the moment and depends on them reading it. A restriction removes the capability before the question is ever asked. These are different security properties, not different strengths of the same one.</p>
<p>Intuit also publishes <code>intuit/quickbooks-online-mcp-server</code>, an open-source MCP server you run yourself. OAuth credentials go in environment variables, and three boolean switches (<code>QUICKBOOKS_DISABLE_WRITE</code>, <code>QUICKBOOKS_DISABLE_UPDATE</code>, <code>QUICKBOOKS_DISABLE_DELETE</code>) leave only read operations reachable (<a href="https://github.com/intuit/quickbooks-online-mcp-server">github.com</a>). That is genuinely read-only, enforced at the server, for one analyst on one machine. The constraint is that it is per-machine and per-process. Five analysts means five installs, five copies of the client secret, and five sets of environment variables. All of them have to be kept in sync if a scope or credential changes. There is no shared audit trail across those five instances unless you build one.</p>
<p>Elaichi earns its place when the team is more than one or two people, and QuickBooks is one of several systems they ask about, not the only one. It earns it when someone has to be able to show an auditor who read what, when, from which client. Elaichi keeps one audit trail across every client and every connected app. The same connection-share-plus-allowlist shape applies to the rest of the finance stack. See <a href="/blog/finance-team-claude-xero/">Xero in Claude, without letting it edit invoices</a> for the same pattern on a different ledger. For the control-plane concept itself, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>, and browse the <a href="/connectors/">600+ connectors</a> for the other apps finance already runs.</p>
<h2>FAQ</h2><dl><dt><strong>Does QuickBooks Online have a read-only API scope?</strong></dt><dd>No. QuickBooks Online has one accounting scope, com.intuit.quickbooks.accounting, and it covers reads and writes together. Intuit Developer Support's guidance for a read-only app is that it should make only GET requests (developer.intuit.com, checked October 2026). Read-only access therefore has to be enforced by whatever calls the API, such as a restriction in an MCP control plane, rather than by the scope itself.</dd><dt><strong>Can I make QuickBooks read-only by unticking a box on Elaichi's consent screen?</strong></dt><dd>No. On Elaichi's consent screen, "Run your connected tools" runs a connected app's read and write tools alike, and "Create and change data" governs Elaichi's own control-plane operations rather than the connected app's. Only a tool whose method is a delete needs the separate "Delete data and remove access" box. Read-only access to a connected app is written as a restriction: an allow rule naming its read tools, or blocks on its writes.</dd><dt><strong>Who can connect QuickBooks for a finance team?</strong></dt><dd>Intuit's UK help says the primary admin and company admins connect apps, and no US page was found stating otherwise, so a QuickBooks connection usually carries admin reach. In Elaichi that admin connects the company file once and shares the connection with the finance team at use. A shared connection runs on its owner's credential, so every member's call reaches QuickBooks as that admin account, while Elaichi records which member made each call that runs.</dd><dt><strong>How quickly does a new restriction take effect?</strong></dt><dd>A new restriction is not instant. A restriction change takes effect within about two minutes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>How do I confirm that a QuickBooks write tool is actually restricted?</strong></dt><dd>Sign in from a test account holding the restricted role and search for the tool by name. Connected tools are never listed, so the model finds them through search_tools and runs them through execute_tool. A tool withheld by a restriction cannot be run. Search names it, flagged restricted, with no schema. Reading the rule behind it takes someone holding restriction:view, such as an admin or the free read-only Auditor.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Ramp in Claude for finance, minus admin reach</title>
      <link>https://elaichi.ai/blog/finance-team-claude-ramp-spend/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/finance-team-claude-ramp-spend/</guid>
      <description>Ramp in Claude for a finance team, without giving every analyst an admin seat: one authorized connection, read-only scopes, restrictions on the finance role.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Only a Ramp Admin or Business Owner can authorize a Ramp developer app, so the connection a finance team shares carries that reach. Elaichi bounds it twice: a typed list of Ramp read scopes on the OAuth app, and an allow rule on the finance role naming the read tools. Claude then points at one endpoint, and each tool call that reaches execution is recorded with the Ramp account it actually reached.</aside>
<h2 id="who-can-authorize-a-ramp-app-and-what-the-finance-team-inherits">Who can authorize a Ramp app, and what the finance team inherits</h2>
<p>Finance wants Ramp in Claude: what did we spend with this vendor last quarter, which bills are still unapproved, who has not attached a receipt. The blocker arrives before the first question. Ramp's own pages name who can authorize a developer app. Only users with Developer API authorization permission can do it, typically Admin and Business Owner (<a href="https://docs.ramp.com/developer-api/v1/authorization">https://docs.ramp.com/developer-api/v1/authorization</a>, <a href="https://support.ramp.com/accessing-the-developer-api">https://support.ramp.com/accessing-the-developer-api</a>, checked October 2026). You are not handing five analysts an admin seat to get a spend question answered.</p>
<p>So one admin authorizes, and the team shares what that authorization produced. In Elaichi, a governed MCP control plane, one Ramp admin connects the Ramp account once. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The connection is then shared with the finance team at <code>use</code>. That is the grant that lets a person call something they do not own. It is distinct from <code>edit</code>, the share level that lets them change the connection. A shared connection runs on its owner's credential, so every call reaches Ramp as that admin account. The analysts never see or hold the secret, and they gain no new role inside Ramp.</p>
<p>What actually bounds a shared call is three layers, each narrower than the last, and none able to widen what the layer before it allows:</p>
<ol>
<li><strong>The admin's Ramp role</strong>: whatever Admin or Business Owner can see in Ramp, which Ramp sets and Elaichi cannot override.</li>
<li><strong>The OAuth app's scopes</strong>: the read/write list configured in Ramp's developer app, which bounds the credential itself.</li>
<li><strong>Elaichi's restrictions</strong>: the allow/block rules on the finance role, which bound which people can reach which tools.</li>
</ol>
<p>Ramp does not document that an OAuth app's calls are narrowed to the authorizing person's role. In practice, treat the connection as carrying the admin's full reach unless scopes and restrictions say otherwise, and put the boundary where you control it. In Elaichi that is layers 2 and 3: the scope list on the OAuth app, and restrictions on the finance role.</p>
<h2 id="setting-up-ramp-in-claude-does-the-connector-want-your-own-oauth-app">Setting up Ramp in Claude: does the connector want your own OAuth app?</h2>
<p>Only if the connector's page shows the card. Most OAuth connectors in Elaichi connect through an operator-set default OAuth app that every organization inherits. Where a connector needs the organization's own app instead, its page carries a card titled <strong>Add your OAuth application</strong>. An admin holding <code>connector:manage</code> fills it in. Org Owner and Org Admin hold that permission by default. If the card is not there, skip this section and connect the account directly.</p>
<p>When the card is there, the order matters:</p>
<ol>
<li>In Elaichi, open <strong>Connectors</strong> in the sidebar, open the Ramp connector, and press <strong>Add OAuth app</strong>. The <strong>Redirect URL</strong> field is read-only and has a copy button. Copy it now.</li>
<li>In Ramp, create a developer app. Ramp's pages give more than one menu path, so follow Ramp's current one (<a href="https://support.ramp.com/accessing-the-developer-api">https://support.ramp.com/accessing-the-developer-api</a>, checked October 2026). Paste Elaichi's Redirect URL wherever Ramp asks for a redirect URI. Ramp requires HTTPS and an exact match, so do not retype it.</li>
<li>Configure the app's scopes in Ramp. Start read-only, which is also Ramp's own advice (<a href="https://docs.ramp.com/developer-api/v1/authorization">https://docs.ramp.com/developer-api/v1/authorization</a>, checked October 2026).</li>
<li>Back in Elaichi, paste the <strong>Client ID</strong> and <strong>Client secret</strong>, type the scope list, and press <strong>Save OAuth app</strong>. The change is recorded as <code>connector.oauth_app.updated</code>.</li>
</ol>
<p>Then the Ramp Admin or Business Owner connects the account in Elaichi. That person owns the connection. Pick an owner who is staying. When an owner leaves, Elaichi's offboarding lists every connection they own. A shared connection the team depends on is deleted only if an admin asks for that. Otherwise the admin transfers it to another member, which keeps every share as it was. The Ramp side still needs its own deprovisioning.</p>
<h2 id="which-ramp-read-scopes-to-type-and-why-the-box-replaces-the-defaults">Which Ramp read scopes to type, and why the box replaces the defaults</h2>
<p>Type only the read scopes the team's questions need, and type the complete list. Elaichi's <strong>Scopes</strong> box is wholesale: left blank it keeps the scopes Elaichi requests by default, and a typed list replaces those defaults entirely. One scope per line, written exactly as Ramp writes it.</p>
<p>One caution follows from that. The console never shows the scopes Elaichi requests by default. So a typed list has to be complete. Include any non-resource scopes Ramp lists, such as <code>offline_access</code> if the app relies on refresh tokens. After saving, check that the connection still works once its first access token has expired.</p>
<p>Ramp's scopes come in <code>resource:read</code> and <code>resource:write</code> pairs, with no wildcard, and a token holds only the scopes it was issued with. For finance's read-only questions, the scope set generally looks like this. Confirm the exact names against Ramp's current authorization page before typing them:</p>
<table>
<thead>
<tr>
<th>Question the team asks</th>
<th>Likely Ramp read scope</th>
</tr>
</thead>
<tbody>
<tr>
<td>What did we spend with this vendor</td>
<td><code>transactions:read</code></td>
</tr>
<tr>
<td>Which bills are unapproved</td>
<td><code>bills:read</code></td>
</tr>
<tr>
<td>Who hasn't attached a receipt</td>
<td><code>receipts:read</code></td>
</tr>
<tr>
<td>What's outstanding in reimbursements</td>
<td><code>reimbursements:read</code></td>
</tr>
</tbody>
</table>
<p>Per Ramp, asking for a scope the app is not configured for fails at sign-in with <code>invalid_scope</code> (<a href="https://docs.ramp.com/developer-api/v1/authorization">https://docs.ramp.com/developer-api/v1/authorization</a>, checked October 2026). A call that needs a scope the token lacks gets a 403 from Ramp. Elaichi records that as a failed tool call with an error code. Nothing escalates to a broader scope automatically. The fix is always the same sequence: add the scope in Ramp, add it to Elaichi's list, reconnect. Copy the exact names from Ramp's authorization page rather than guessing from a pattern.</p>
<p>This is the hard edge of the whole setup. A write scope you never type cannot be talked back into existence by a prompt, a misreading, or a clever tool call. Adding approvals or reimbursement submission later is a deliberate act: a new scope in Ramp, the same scope added to Elaichi's list, and a reconnect.</p>
<h2 id="which-ramp-tools-stay-out-of-the-finance-role">Which Ramp tools stay out of the finance role</h2>
<p>Write one allow rule on the finance role naming Ramp's read tools. One consequence catches people out. Once the role holds an allow rule, every connector that no allow rule on the role names is denied for that role. That is not just Ramp's other tools. Allow rules on the same role add up. So give the finance role an allow rule for each other app it uses, naming a whole connector where that is fine. Otherwise the team loses those apps. The mental model is simple: <strong>scopes bound the credential, restrictions bound the people.</strong> Scopes are set once in Ramp and apply to everyone who shares the connection. Restrictions are set in Elaichi, target a role or a user, and can change without touching Ramp at all. A restriction change takes effect within about two minutes. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Two traps decide whether the rule does what you meant:</p>
<ul>
<li><strong>An allow rule that names nothing denies everything.</strong> In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Leaving the tool list blank locks out the whole finance team.</li>
<li><strong>An allow rule that names the Ramp connector as a whole <em>and</em> some of its tools reaches all of Ramp.</strong> The tool entries grant nothing once the connector-level entry is present. Name the tools, or name the connector, not both.</li>
</ul>
<p>Blocks always beat allows. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. So an analyst who asks Claude to approve a transaction finds an approve tool that cannot run.</p>
<p>One correction catches people out at the consent screen: unticking <strong>Create and change data</strong> does not make Ramp read-only. That checkbox governs Elaichi's own operations. For a connected app, <strong>Run your connected tools</strong> runs reads and writes alike, and only a delete costs the destructive scope. Read-only access to Ramp is the scope list plus a restriction, never a consent checkbox. The matching rules are worth reading once in <a href="/blog/block-matches-name-allow-matches-operation/">how blocks and allows resolve differently</a>. The wider pattern is in <a href="/blog/least-privilege-tool-calls-without-breaking-automation/">least privilege without breaking the work</a>.</p>
<h2 id="adding-the-one-endpoint-in-claude-and-what-the-trail-shows-afterward">Adding the one endpoint in Claude, and what the trail shows afterward</h2>
<p>There is one address for the whole organization: <code>POST https://api.elaichi.ai/mcp</code>. No per-user URL, no token to paste. On Claude Team and Enterprise, an Owner or Primary Owner adds it under Organization settings, then Connectors, Add, Custom, Web. Members then enable it under Customize, Connectors and sign in with their own grant. On Pro and Max it is Customize, Connectors, "+", Add custom connector (<a href="https://support.claude.com/en/articles/11175166">https://support.claude.com/en/articles/11175166</a>, checked October 2026).</p>
<p>Each analyst signs in once, picks the organization, and leaves <strong>Run your connected tools</strong> ticked. Delete is never pre-ticked. Claude's per-connector tool permissions land on Elaichi's <code>execute_tool</code>, a single permission that gates every connected tool at once, regardless of which app it belongs to. That is exactly why the per-tool boundary for Ramp has to live in Elaichi's restrictions and not in Claude's own settings. Claude's settings cannot distinguish a Ramp read from a Ramp write. The two places an admin approves apps are compared in <a href="/blog/approve-apps-employees-connect-to-claude/">approving apps for Claude across a company</a>.</p>
<p>Afterward, Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The audit trail is the append-only record of what ran. It names the Ramp account actually reached, the operation and tool, whether approval was needed, the outcome, and an error code. The entry holds no argument values, with one exception: the one path argument that names the object is recorded as the target id. So a transaction amount does not end up in the log. The entry carries the surface (<code>mcp</code>) and the client, and Claude's name is marked verified by its redirect URIs. A call from Claude is recorded with the person as the actor, not as an assistant. An Auditor seat to read it is free. <a href="/blog/what-an-ai-audit-log-must-capture/">What belongs in an agent's audit record</a> goes into the fields themselves.</p>
<h2 id="when-ramps-own-hosted-mcp-server-is-the-better-fit">When Ramp's own hosted MCP server is the better fit</h2>
<p>When each person only needs their own Ramp data. Ramp hosts its own MCP server at <code>https://mcp.ramp.com/mcp</code>, labeled "Ramp MCP is in Beta" in Ramp's docs, with OAuth sign-in. Employees see only their own data, and admin tools require Admin or Business Owner. Admins grant access at Company, Integrations, Ramp MCP, Manage Access (<a href="https://docs.ramp.com/developer-api/v1/ramp-mcp">https://docs.ramp.com/developer-api/v1/ramp-mcp</a>, <a href="https://support.ramp.com/ramp-mcp">https://support.ramp.com/ramp-mcp</a>, checked October 2026). Custom clients and gateways need their redirect URI allowlisted by Ramp first.</p>
<p>The two paths solve different problems, not the same problem with different branding:</p>
<table>
<thead>
<tr>
<th></th>
<th>Ramp's hosted MCP</th>
<th>Elaichi as control plane</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data scope per person</td>
<td>Each person's own Ramp role, enforced by Ramp</td>
<td>Whatever the admin's connection carries, narrowed by Elaichi's restrictions</td>
</tr>
<tr>
<td>Cross-app view (Ramp + Xero + Slack, etc.)</td>
<td>No, Ramp only</td>
<td>Yes, one address and one restriction set per role</td>
</tr>
<tr>
<td>Second vendor in the path</td>
<td>None</td>
<td>Elaichi sits between Claude and Ramp</td>
</tr>
<tr>
<td>Audit trail</td>
<td>Not described on Ramp's MCP pages</td>
<td>One trail across every connected app</td>
</tr>
<tr>
<td>Offboarding</td>
<td>Deprovision in Ramp or your IdP</td>
<td>removing or suspending a member revokes every live grant in the same transaction as the membership change, and the Ramp account still needs separate deprovisioning</td>
</tr>
<tr>
<td>Best fit</td>
<td>"Where are my own receipts," "what did I spend"</td>
<td>"What did the team spend with this vendor," shared operational questions no single analyst's Ramp role answers</td>
</tr>
</tbody>
</table>
<p>If the question is personal, "where are my own receipts," "what did I spend," Ramp's server is the better fit. There is no second vendor in the path. Elaichi is the better fit when the question is operational and shared. Use it when no single analyst's Ramp role covers the question. Use it when Ramp needs to sit beside Xero, Slack, or Salesforce on one address with restrictions written once per role. Use it when one audit trail has to cover every app a finance analyst touches in Claude.</p>
<p>For the wider shape of this, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is and who needs one</a>. The same playbook for a different ledger is in <a href="/blog/finance-team-claude-xero/">keeping Claude out of your Xero invoices</a>. The choice between a whole-app and a single-tool rule is worked through in <a href="/blog/per-tool-vs-per-app-restrictions/">six cases for per-tool restrictions</a>. The <a href="/connectors/ramp/">Ramp connector</a> sits with the rest of the catalog under <a href="/connectors/">connectors</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can a finance analyst use Ramp in Claude without a Ramp admin seat?</strong></dt><dd>Yes. Ramp documents that only users with Developer API authorization permission, typically Admin and Business Owner, can authorize a developer app (docs.ramp.com/developer-api/v1/authorization, checked October 2026). In Elaichi, that admin connects the Ramp account once and shares the connection with the finance team at use level. A shared connection runs on its owner's credential, so analysts call Ramp without holding a Ramp admin seat, and without ever seeing the credential.</dd><dt><strong>How do you make a Ramp connection read-only for a team?</strong></dt><dd>In two layers. First, configure only read scopes on the Ramp developer app, since Ramp scopes come in resource:read and resource:write pairs with no wildcard, and type that same complete list into Elaichi's Scopes box, because a typed list replaces Elaichi's defaults wholesale. Second, write a restriction on the finance role allowing only Ramp's read tools. Unticking "Create and change data" on Elaichi's consent screen does not do this: for a connected app, "Run your connected tools" runs reads and writes alike.</dd><dt><strong>How long does a Ramp restriction change take to apply in Elaichi?</strong></dt><dd>A role or restriction change takes effect within about two minutes. Role membership and restriction changes resolve through a short cache plus edge propagation on every surface, MCP clients and the console alike. Some changes are faster: revoking a share and disconnecting an account take effect on the caller's next request, because the grant and the connection are read fresh on every call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Should a company use Ramp's own hosted MCP server instead?</strong></dt><dd>Use Ramp's hosted server when each employee only needs their own data. It sits at https://mcp.ramp.com/mcp, is labeled a beta in Ramp's docs, signs in with OAuth, and scopes each person to their own Ramp role, with admin tools requiring Admin or Business Owner (docs.ramp.com/developer-api/v1/ramp-mcp, checked October 2026). A control plane such as Elaichi is the better fit when a team shares one admin-authorized view, when Ramp is one of several apps behind one address, or when one audit trail has to span all of them.</dd><dt><strong>Who can add the organization's own OAuth app to a connector in Elaichi?</strong></dt><dd>An admin holding the connector:manage permission, which Org Owner and Org Admin hold by default. The card is called "Add your OAuth application" on the connector's page, and it appears only where the connector needs the organization's own app or one is already stored. The Redirect URL field is read-only with a copy button; paste it wherever the provider asks for a redirect URI. Changes are recorded in the audit trail as connector.oauth_app.updated.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Find the MCP servers employees have installed</title>
      <link>https://elaichi.ai/blog/find-mcp-servers-employees-installed/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/find-mcp-servers-employees-installed/</guid>
      <description>No admin console lists the MCP servers employees have installed. The order that works: a device sweep, the vendor logs that exist, then a direct ask.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> The MCP servers employees have installed live in JSON and TOML files on their devices, and no client vendor documents an admin inventory of those files. The method that works is an MDM or EDR script that reads each client's config and collects only the server entries, then the three vendor admin logs that exist, then a short message to the teams using them. Elaichi is where the servers that reach company SaaS accounts go afterward: one organization-wide MCP endpoint behind OAuth, with connectors Elaichi authors or governs.</aside>
<h2 id="why-no-admin-console-lists-the-mcp-servers-employees-have-installed">Why no admin console lists the MCP servers employees have installed</h2>
<p>Most of the MCP servers employees have installed are lines in a file on a laptop, and no client vendor documents an admin inventory of those files. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A server is either a local process the client starts on the device, or a remote HTTPS address the client calls (<a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">modelcontextprotocol.io</a>, checked October 2026). Both are recorded the same way, as an entry in the client's own configuration file.</p>
<p>That is why network tooling finds so little. A local server never leaves the machine, so there is no request for a proxy to inspect. A remote one is an ordinary HTTPS call. For Claude's connectors, that call comes from Anthropic's cloud rather than the user's device, on every Claude client (<a href="https://claude.com/docs/connectors/custom/add-unlisted">claude.com/docs/connectors/custom/add-unlisted</a>, checked October 2026). Inline inspection still earns its place for other reasons. It is not how you build this list.</p>
<p>Vendor consoles report what connects through the vendor's own surface, which is a different set from what sits in a file. So the order is: read the files, then read the logs, then ask the people.</p>
<p>A note on sourcing: every claim below traces to a vendor's own documentation, linked and dated. "Checked [month, year]" marks when we last reconciled the claim against that page, not a publication date. Vendor docs change without notice, and the config path below moved when Windsurf became Devin Desktop. Re-verify against the live link before you build unattended automation on a specific path or key.</p>
<h2 id="which-file-holds-the-server-list-on-each-client">Which file holds the server list on each client?</h2>
<p>Each client keeps its MCP servers at a documented path, and usually there are two, one per user and one per project. These are the paths as of October 2026, read from each vendor's own page. This list covers the clients most likely to appear in a laptop fleet today: Claude Desktop, Claude Code, Cursor, VS Code with Copilot, Devin Desktop and Codex. JetBrains AI Assistant, Zed, and mobile or browser-based MCP clients aren't covered here; if your fleet includes them, find the equivalent path in that vendor's own docs before treating a sweep as complete.</p>
<ul>
<li><strong>Claude Desktop.</strong> <code>~/Library/Application Support/Claude/claude_desktop_config.json</code> on macOS, <code>%APPDATA%\Claude\claude_desktop_config.json</code> on Windows, with servers under the <code>mcpServers</code> key. Anthropic gives no Linux path. Server names also appear in the log directory, <code>~/Library/Logs/Claude</code> or <code>%APPDATA%\Claude\logs</code>, as one <code>mcp-server-SERVERNAME.log</code> per server (<a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">modelcontextprotocol.io</a>, checked October 2026).</li>
<li><strong>Claude Code.</strong> Local and user scope live in <code>~/.claude.json</code>. Project scope lives in <code>.mcp.json</code> at the repository root. On a device you can also run <code>claude mcp list</code> (<a href="https://code.claude.com/docs/en/mcp">code.claude.com/docs/en/mcp</a>, checked October 2026).</li>
<li><strong>Cursor.</strong> <code>~/.cursor/mcp.json</code> globally and <code>.cursor/mcp.json</code> per project (<a href="https://cursor.com/docs/mcp">cursor.com/docs/mcp</a>, checked October 2026).</li>
<li><strong>VS Code with GitHub Copilot.</strong> <code>.vscode/mcp.json</code> with a top-level <code>servers</code> key, plus a user-profile <code>mcp.json</code>. Both are now labeled deprecated in the Add Server flow, which steers new servers to <code>.mcp.json</code> at the project root and <code>~/.copilot/mcp-config.json</code>. Sweep both generations (<a href="https://code.visualstudio.com/docs/agent-customization/mcp-servers">code.visualstudio.com</a>, checked October 2026).</li>
<li><strong>Devin Desktop</strong>, which was Windsurf. <code>~/.config/devin/mcp_config.json</code>, or <code>%APPDATA%\devin\mcp_config.json</code> on Windows. Devin's docs still name the older <code>~/.codeium/windsurf/mcp_config.json</code>, so check both (<a href="https://docs.devin.ai/desktop/cascade/mcp">docs.devin.ai</a>, checked October 2026).</li>
<li><strong>Codex.</strong> <code>~/.codex/config.toml</code>, one <code>[mcp_servers.&#x3C;name>]</code> table per server, plus a project <code>.codex/config.toml</code> in trusted projects only. One file covers the ChatGPT desktop app, the Codex CLI and the IDE extension (<a href="https://learn.chatgpt.com/docs/extend/mcp">learn.chatgpt.com</a>, checked October 2026).</li>
</ul>
<p>Desktop extensions in Claude are local servers too, installed from Settings and then Extensions. No vendor page gives their path on disk, so the allowlist is the control for them, not a file sweep.</p>
<h3 id="quick-reference-paths-policy-and-log-coverage-by-client">Quick reference: paths, policy and log coverage by client</h3>
<table>
<thead>
<tr>
<th>Client</th>
<th>User/global config</th>
<th>Project config</th>
<th>Policy control</th>
<th>Admin log / audit coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td>Claude Desktop</td>
<td>macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code>; Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code> (<code>mcpServers</code> key)</td>
<td>n/a (extensions use an allowlist, not a file)</td>
<td>macOS domain <code>com.anthropic.claudefordesktop</code>; Windows <code>HKLM:\SOFTWARE\Policies\Claude</code></td>
<td>Per-server logs at <code>~/Library/Logs/Claude</code> or <code>%APPDATA%\Claude\logs</code></td>
</tr>
<tr>
<td>Claude.ai connectors</td>
<td>n/a, server-side</td>
<td>n/a</td>
<td>Enterprise admin console</td>
<td>Compliance API: <code>integration_user_connected</code> / <code>_disconnected</code>, <code>mcp_server_created</code>, <code>mcp_tool_policy_updated</code></td>
</tr>
<tr>
<td>Claude Code</td>
<td><code>~/.claude.json</code></td>
<td><code>.mcp.json</code> at repo root</td>
<td><code>allowedMcpServers</code> / <code>deniedMcpServers</code> in managed settings (deny wins)</td>
<td>OpenTelemetry <code>claude_code.mcp_server_connection</code>, server names only with <code>OTEL_LOG_TOOL_DETAILS=1</code></td>
</tr>
<tr>
<td>Cursor</td>
<td><code>~/.cursor/mcp.json</code></td>
<td><code>.cursor/mcp.json</code></td>
<td>Enterprise allowlist (does not push servers)</td>
<td>Enterprise audit log: <code>mcp_server_config</code>, <code>mcp_authentication</code>; <code>beforeMCPExecution</code> hook per call</td>
</tr>
<tr>
<td>VS Code + Copilot</td>
<td>user-profile <code>mcp.json</code> (deprecated), now <code>~/.copilot/mcp-config.json</code></td>
<td><code>.vscode/mcp.json</code> (deprecated), now <code>.mcp.json</code> at root</td>
<td><code>chat.mcp.access</code> (<code>all</code>/<code>registry</code>/<code>none</code>) + per-server allow/deny (deny wins)</td>
<td>Usage metrics report MCP use for Copilot CLI only</td>
</tr>
<tr>
<td>Devin Desktop</td>
<td><code>~/.config/devin/mcp_config.json</code>; legacy <code>~/.codeium/windsurf/mcp_config.json</code></td>
<td>n/a</td>
<td>Team admin on/off + allowlist (one allowlisted server blocks all others)</td>
<td>None documented</td>
</tr>
<tr>
<td>Codex (app/CLI/IDE)</td>
<td><code>~/.codex/config.toml</code></td>
<td><code>.codex/config.toml</code> (trusted projects only)</td>
<td><code>requirements.toml</code> approved <code>mcp_servers</code> list (empty key disables all)</td>
<td>None documented</td>
</tr>
</tbody>
</table>
<h2 id="how-to-collect-only-the-server-entries">How to collect only the server entries</h2>
<p>Parse each file and emit the server objects alone. Never ship the whole file to your inventory.</p>
<p>The reason is concrete. <code>~/.claude.json</code> holds the Claude Code sign-in session alongside its <code>mcpServers</code> object, so a script that uploads the file uploads a credential. Read the <code>mcpServers</code> object out and discard the rest. Do the same for <code>servers</code> in VS Code's files and the <code>[mcp_servers.*]</code> tables in Codex's TOML. Use a real JSON or TOML parser rather than a regular expression, and when a file will not parse, log the path and move on.</p>
<p>Per entry, record five fields: the device, the user, the client, the server name, and either its <code>url</code> or its <code>command</code> with arguments. For an <code>env</code> block, record the key names and not the values. Those values are often long-lived API tokens, and a sweep that copies them creates a second place they live.</p>
<p>Project files are the part most sweeps miss. <code>.mcp.json</code>, <code>.cursor/mcp.json</code>, <code>.vscode/mcp.json</code> and <code>.codex/config.toml</code> sit inside repository checkouts, not in the home directory, so the script needs a path glob across developer working directories. Run the whole sweep twice, a week apart. The delta tells you whether the list is growing, which matters more than the first snapshot.</p>
<h2 id="which-admin-logs-show-an-mcp-connection">Which admin logs show an MCP connection?</h2>
<p>Three exist today, and each covers connections made through the vendor's surface rather than files on disk.</p>
<p>Anthropic's Compliance API, on Enterprise, emits <code>integration_user_connected</code> and <code>integration_user_disconnected</code> with <code>integration_type</code> set to <code>mcp</code>, carrying the server's id and name. It also carries admin events such as <code>mcp_server_created</code> and <code>mcp_tool_policy_updated</code>. The Primary Owner enables it and there is no backfill, so turn it on before you need the history (<a href="https://platform.claude.com/docs/en/api/compliance/activities">platform.claude.com</a>, checked October 2026). It covers connectors on the claude.ai side, not local config files.</p>
<p>Claude Code can emit <code>claude_code.mcp_server_connection</code> over OpenTelemetry, with server names present only when <code>OTEL_LOG_TOOL_DETAILS=1</code> (<a href="https://code.claude.com/docs/en/monitoring-usage">code.claude.com</a>, checked October 2026). Cursor's Enterprise audit log carries <code>mcp_server_config</code> and <code>mcp_authentication</code> events (<a href="https://cursor.com/docs/enterprise/compliance-and-monitoring">cursor.com/docs/enterprise/compliance-and-monitoring</a>, checked October 2026). Cursor does not say that an edit to a member's own <code>mcp.json</code> emits either, so treat it as coverage of connections rather than of files. Cursor also documents MDM-deployed hooks, where <code>beforeMCPExecution</code> sees the server name and its URL or command on every call and can allow, deny or ask (<a href="https://cursor.com/docs/hooks">cursor.com/docs/hooks</a>, checked October 2026). GitHub's usage metrics report MCP use for Copilot CLI only (<a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/reference/copilot-usage-metrics/copilot-usage-metrics">docs.github.com</a>, checked October 2026). OpenAI and Devin document nothing comparable, so the file sweep is the whole answer for Codex and Devin Desktop.</p>
<h2 id="what-to-ask-people-directly">What to ask people directly</h2>
<p>Send a short message to the teams most likely to have built something, and make it a question about their work rather than a compliance notice. Scripts miss anything written outside a standard directory. An engineer who wrote a local server to read a staging database will say so if nothing bad happens when they do.</p>
<p>Four questions is enough. Which MCP servers do you have configured, in any client. Which of them reach a company system, as opposed to local files. Which did you write yourself. Which would break your week if it stopped working on Friday.</p>
<p>That last question sorts the list. It separates a tool somebody tried once from a tool that is now part of a process, and the second kind has to be replaced rather than removed. State up front that the goal is to keep the useful ones working. An audit that reads as punishment pushes the next one further out of sight.</p>
<h2 id="keep-replace-remove-sorting-the-inventory">Keep, replace, remove: sorting the inventory</h2>
<p>Sort every entry into one of three buckets, and resist inventing a fourth.</p>
<p><strong>Keep</strong> is a local server that touches nothing but the developer's own machine and holds no company credential. A filesystem reader over a local checkout is the usual case. Record it, scope it so it cannot reach a production environment, and move on.</p>
<p><strong>Replace</strong> is any server that reaches a company SaaS account: the Jira server with a personal API token in an <code>env</code> block, the Slack server somebody pasted a bot token into, the internal API wrapper running on one laptop. These are the entries a leaver takes with them, and they sit outside whatever sign-in rules govern everything else on the device, which is the practical case for <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth rather than API keys</a>.</p>
<p>The replace pattern has the same shape regardless of vendor: one shared endpoint behind OAuth, so no server URL or token lives in a per-user config file; a catalog of maintained connectors, so engineering time isn't spent patching a Jira or Slack MCP server; and a restriction layer, a rule naming which connectors and which individual tools a role or person may reach, enforced at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file, not only at connect.</p>
<p>Disclosure: Elaichi, which publishes this post, is one implementation of that pattern. It serves 600+ connectors through a single organization-wide endpoint, <code>POST https://api.elaichi.ai/mcp</code>, behind OAuth, with no per-user URLs and no embedded tokens. A restriction change takes effect within about two minutes. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). If you're evaluating this category rather than this vendor, four questions apply to any product in it: single endpoint or per-user URLs, who authors and maintains the catalog, where restrictions are enforced (connect only, or also at execute), and how fast a change propagates.</p>
<p><strong>Remove</strong> is everything with no owner, plus anything built on a shared long-lived token. Deleting the config entry is not the whole job. Rotate the credential it held, because the entry was only one copy of it.</p>
<p>Write the limit down next to the list. A governed endpoint controls access through itself and nothing upstream of it. It does not govern calls a client makes to a server directly. GitHub's own MCP server, for instance, stays governed by GitHub's policy and your identity provider, regardless of catalog. Removing access through the gateway also ends there: the person's account inside each downstream app still exists and is deprovisioned through that app or your identity provider, which is the harder half of <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding when an agent holds access</a>.</p>
<h2 id="which-managed-policy-keeps-the-list-from-growing-again">Which managed policy keeps the list from growing again</h2>
<p>Each client ships its own, and each binds only that client. Set them after the sweep, so you know in advance what the policy will break.</p>
<p>Claude Desktop reads device policy from the macOS domain <code>com.anthropic.claudefordesktop</code> and from <code>HKLM:\SOFTWARE\Policies\Claude</code> on Windows, where <code>isLocalDevMcpEnabled</code>, <code>isDesktopExtensionEnabled</code> and <code>isDesktopExtensionDirectoryEnabled</code> all default to true. The Desktop extension allowlist in Organization settings is off by default, and turning it on removes existing installs (<a href="https://support.claude.com/en/articles/12622667-enterprise-configuration-for-claude-desktop">support.claude.com</a>, checked October 2026). Claude Code uses <code>allowedMcpServers</code> and <code>deniedMcpServers</code> in managed settings, where the denylist always wins and an unset allowlist allows everything. Anthropic states that matching by <code>serverName</code> is not a security control; the reason is that users choose the names, since the name is the key a person types in their own config. Match on <code>serverUrl</code> or <code>serverCommand</code> instead (<a href="https://code.claude.com/docs/en/managed-mcp">code.claude.com</a>, checked October 2026). A newly blocked server disappears from <code>/mcp</code> with no reason shown, so tell people before you apply it.</p>
<p>VS Code has <code>chat.mcp.access</code>, set to <code>all</code>, <code>registry</code> or <code>none</code>, plus per-server allow and deny lists where deny beats allow (<a href="https://code.visualstudio.com/docs/enterprise/manage-ai-settings">code.visualstudio.com</a>, checked October 2026). Cursor's allowlist is Enterprise only and does not push servers to anyone (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">cursor.com/docs/enterprise/model-and-integration-management</a>, checked October 2026). Devin Desktop lets a team admin turn MCP off or allowlist servers, and once any server is allowlisted every other server is blocked for the team (<a href="https://docs.devin.ai/desktop/cascade/mcp">docs.devin.ai</a>, checked October 2026). Codex reads an approved <code>mcp_servers</code> list from <code>requirements.toml</code>, where a key that is present but empty disables every MCP server (<a href="https://learn.chatgpt.com/docs/enterprise/managed-configuration">learn.chatgpt.com</a>, checked October 2026).</p>
<h2 id="when-the-inventory-is-the-whole-job">When the inventory is the whole job</h2>
<p>If the sweep returns four local servers on two laptops and none of them holds a company credential, you are done. Set the client policies, keep the script on a monthly schedule, and spend the budget elsewhere. A governed endpoint earns its place when people are reaching company SaaS accounts from an assistant, not when two developers are reading local files.</p>
<p>The decision changes when the same list shows a personal token in a config file, or a server nobody can name the owner of, or one app connected from three different clients. At that point the work is consolidation, and <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting</a> no longer holds.</p>
<p>For the replacement step in detail, see how to <a href="/blog/replace-personal-mcp-servers/">swap personal servers on laptops for one endpoint</a>. For what the browser-side evidence does and does not prove, read <a href="/blog/shadow-ai-it-admin-browser-extension-log/">the shadow AI browser extension log</a>, and for the layer above it, <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">what CASB and DLP can see</a>. The architecture behind the single address is covered in <a href="/blog/what-is-an-mcp-control-plane/">the MCP control plane explainer</a>. Check which servers on your list have a maintained equivalent in the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Where does each AI client store its MCP server list?</strong></dt><dd>As of October 2026: Claude Desktop uses ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and %APPDATA%\Claude\claude_desktop_config.json on Windows, under the mcpServers key. Claude Code uses ~/.claude.json for local and user scope and .mcp.json at a repository root for project scope. Cursor uses ~/.cursor/mcp.json and .cursor/mcp.json. VS Code with Copilot uses .vscode/mcp.json and a user-profile mcp.json, both now deprecated in favor of .mcp.json at the project root and ~/.copilot/mcp-config.json. Devin Desktop, formerly Windsurf, uses ~/.config/devin/mcp_config.json or %APPDATA%\devin\mcp_config.json, with the older ~/.codeium/windsurf/mcp_config.json still named in its docs. Codex uses ~/.codex/config.toml with one [mcp_servers.<name>] table per server.</dd><dt><strong>Can an admin console show which MCP servers employees added on their own laptops?</strong></dt><dd>No client vendor documents an admin inventory of the servers in members' local configuration files. Admin consoles report servers that connect, or are used, through the vendor's own surface. Anthropic's Compliance API emits integration_user_connected events with integration_type mcp, Claude Code can emit claude_code.mcp_server_connection over OpenTelemetry, and Cursor's Enterprise audit log carries mcp_server_config and mcp_authentication events. Finding local servers means reading the configuration files on each device with an MDM or EDR script.</dd><dt><strong>Is it safe for an inventory script to upload the whole config file?</strong></dt><dd>No. Parse the file and collect only the server entries. Claude Code's ~/.claude.json holds the sign-in session alongside its mcpServers object, so uploading the whole file uploads a credential. For an env block inside a server entry, record the key names and not the values, since those values are often long-lived API tokens.</dd><dt><strong>Does removing an MCP server revoke the person's access to the third-party app?</strong></dt><dd>No. Removing a server or a connector ends access through the AI client and nothing more. The person's account inside each app still exists, and it is deprovisioned in that app or through your identity provider. Rotate any credential the server config held, because deleting the entry does not invalidate the token it contained.</dd><dt><strong>What should replace an MCP server that holds a personal API token?</strong></dt><dd>A governed endpoint where the credential is not in the client at all. Elaichi serves every connected SaaS account through one organization-wide MCP endpoint at https://api.elaichi.ai/mcp, behind OAuth, with no per-user URL and no token to paste into a config file. Each member connects once and signs in with their own grant, and revoking that grant, removing the member or suspending them takes effect on the next call.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-08T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>Keep BambooHR salary data out of AI assistants</title>
      <link>https://elaichi.ai/blog/hr-team-bamboohr-salary-data/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/hr-team-bamboohr-salary-data/</guid>
      <description>Two layers keep BambooHR salary data away from Claude and ChatGPT: the access level behind the API key, and an allow rule per role in Elaichi.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Keeping BambooHR salary data out of an AI assistant takes two layers. The outer wall is BambooHR itself, where an API key acts as the user who created it, so create the key from an account whose access level hides compensation. The inner layer is a restriction in Elaichi, written per role as an allow rule naming only the read tools that role needs, because a shared connection otherwise gives every grantee the key's full reach across the connector's 406 tools.</aside>
<h2 id="how-do-you-keep-bamboohr-salary-data-out-of-an-ai-assistant">How do you keep BambooHR salary data out of an AI assistant?</h2>
<p>HR wants Claude to answer the routine questions: who reports to whom, who is on leave next week, when a new hire starts. Someone in finance points out that the same connection could read pay bands and payroll deductions. Both positions are reasonable, and the argument stalls there.</p>
<p>Keeping BambooHR salary data out of the assistant takes two layers, and neither one alone is enough:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>What it controls</th>
<th>Where it lives</th>
<th>Fails open or closed if misconfigured?</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1. API key identity</strong></td>
<td>Whether compensation fields exist in BambooHR's response at all</td>
<td>BambooHR access levels</td>
<td>Fails open: a key from a high-access user returns pay fields wherever an allowed read includes them</td>
</tr>
<tr>
<td><strong>2. Allow rule (restriction)</strong></td>
<td>Which of the 406 BambooHR tools a role can call</td>
<td>Elaichi, per role</td>
<td>Fails closed for tools the rule does not name; with no rule at all, the role reaches everything</td>
</tr>
</tbody>
</table>
<p>The order matters. Build layer one first, because it holds even if someone later misconfigures layer two. A bad allow rule can only expose tools the API key is itself permitted to run. It can never expose a field BambooHR already hides from that key.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi is a governed MCP control plane. Every company account is connected once and served through one organization-wide endpoint. Restrictions are enforced per role before any tool reaches the model.</p>
<h2 id="layer-one-which-bamboohr-user-does-the-api-key-act-as">Layer one: which BambooHR user does the API key act as?</h2>
<p>An API key in BambooHR carries its creator's reach. BambooHR's own documentation puts it plainly: "The API can only view or update data that the user can access" (<a href="https://help.bamboohr.com/s/article/587841">BambooHR help</a>, checked October 2026). The question is not what the key is allowed to do. It is who made it.</p>
<p>Two details decide whether compensation leaks:</p>
<ol>
<li>Pay data lives in the <code>compensation</code> table and in the <code>payRate</code>, <code>payType</code> and <code>paidPer</code> fields (<a href="https://documentation.bamboohr.com/docs/table-name-fields">BambooHR table and field names</a>, checked October 2026).</li>
<li>Get Employee drops fields the caller cannot view while returning no error (<a href="https://documentation.bamboohr.com/reference/get-employee">BambooHR Get Employee</a>, checked October 2026). A model asking for an employee record gets a shorter record and no sign that anything was withheld.</li>
</ol>
<p>That silent drop is the behavior you want. It is also the behavior that makes testing necessary. A 200 response with a short record looks identical to success whether or not compensation was ever in scope. Steps to verify:</p>
<ol>
<li>In BambooHR, confirm the access level that will own the API key does <strong>not</strong> have compensation visibility, and that its field settings reflect that.</li>
<li>Create the API key from a user account at that access level.</li>
<li>Call Get Employee for a salaried employee whose pay rate you already know.</li>
<li>Read the response. If <code>payRate</code> comes back, the key belongs to the wrong user. Fix the access level, not the restriction.</li>
</ol>
<p>BambooHR's OAuth scopes separate <code>employee</code> from <code>employee:compensation</code> and <code>sensitive_employee:protected_info</code>, which covers SSN, SIN and birthday (<a href="https://documentation.bamboohr.com/reference/get-employee">BambooHR Get Employee</a>, checked October 2026). Elaichi's connector takes an API key rather than an OAuth app. So the access level behind that key, not an OAuth scope, is the control you have at this layer.</p>
<h2 id="layer-two-what-does-an-allow-rule-for-an-hr-reader-name">Layer two: what does an allow rule for an HR reader name?</h2>
<p>An allow rule on the role, naming the specific read tools that role uses, and nothing else. Elaichi's <code>bamboohr</code> connector carries 406 tools: 182 have names starting with <code>list_</code> or <code>get_</code>, and most of the other 224 create, update, delete or bulk-change records. The full, current list is on the <a href="/connectors/bamboohr/">BambooHR connector page</a>, rather than reproduced here, since tool counts change as BambooHR's API surface grows.</p>
<p>The pay-related tools are easy to spot and easy to miss one of:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>What it returns</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>list_all_bamboohr_compensation_planning_cycles</code></td>
<td>Compensation review cycles and their status</td>
</tr>
<tr>
<td><code>list_all_bamboohr_pay_grades_and_bands_pay_bands</code></td>
<td>Pay grade/band ranges</td>
</tr>
<tr>
<td><code>get_single_bamboohr_compensation_total_reward_by_id</code></td>
<td>Total rewards statement for one employee</td>
</tr>
<tr>
<td><code>list_all_bamboohr_payroll_deductions</code></td>
<td>Payroll deduction records</td>
</tr>
</tbody>
</table>
<p>A block list that names those four leaves every one of the other 402 tools reachable. With 406 tools, that is not a boundary. It is a guess. <a href="/blog/it-team-claude-intune-devices/">Intune runs the same arithmetic</a>: 198 tools, 69 of them reads, and six blocks do not hold a role to reading.</p>
<p>So write an allow rule instead of a block rule. Two properties of Elaichi restrictions shape how it has to look:</p>
<ul>
<li><strong>A restriction targets a role or a single user.</strong> In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</li>
<li><strong>An allow rule is the target's whole allowlist across every connector</strong>, not just the app it mentions. Once the HR role holds one allow rule, every connector its allow rules do not name is denied. Add an allow rule naming each of the role's other apps whole, or HR loses Slack and Google Calendar once the BambooHR rule takes effect.</li>
</ul>
<p>Two traps to know before writing the rule:</p>
<ol>
<li>An allow rule that names the <code>bamboohr</code> connector whole <strong>and</strong> also lists some of its tools reaches all of it. The tool entries grant nothing additional once the connector itself is named.</li>
<li>An allow rule naming nothing at all denies everything. This is the strictest thing the system can express.</li>
</ol>
<p>Allow rules match the operation pinned against the catalog at write time. Blocks match the tool name or the operation. The mechanical difference is covered in <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match names and allows do not</a>. A restriction change takes effect within about two minutes, on every surface. Custom roles are a Gold-plan feature, so a dedicated HR reader role requires that plan.</p>
<p>The role layer is not optional, because a shared connection runs on its owner's credential. Share the BambooHR connection with the HR team at <code>use</code>, and every grantee's call reaches BambooHR as the account behind that key. Those grantees never see the key itself: reading an account's configuration back returns the list of dot-paths that were encrypted, and none of their values. The restriction is what makes one shared connection serve different people differently. The <a href="/blog/per-tool-vs-per-app-restrictions/">per-tool or per-app decision</a> runs through the same reasoning for other apps.</p>
<p><strong>Checklist for locking down an HR reader role:</strong></p>
<ol>
<li>API key created from a BambooHR access level without compensation visibility (layer one, verified by test call)</li>
<li>Custom role created in Elaichi for HR readers</li>
<li>Allow rule naming only <code>list_*</code>/<code>get_*</code> BambooHR tools the role actually needs (not all 182)</li>
<li>Pay-related tools (table above) confirmed absent from the allow list</li>
<li>Allow rules added for the role's other connectors (Slack, Google Calendar, etc.), named whole, so they aren't silently denied</li>
<li>Connection shared with the HR team at <code>use</code></li>
<li>Test call made as a role member to confirm pay tools are unreachable and routine tools work</li>
</ol>
<h2 id="what-a-withheld-bamboohr-tool-looks-like-to-the-model">What a withheld BambooHR tool looks like to the model</h2>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no description or schema. The model has no schema to fill in and nothing it can run.</p>
<p>Connected tools are never listed in <code>tools/list</code>, however few there are. The model finds one with <code>search_tools</code> and runs it with <code>execute_tool</code>, and those two are the only way in. A BambooHR tool missing from a list is therefore usually a permission gap rather than a bug. <a href="/blog/mcp-tools-not-showing/">MCP tools not showing up</a> walks the diagnostic ladder in order.</p>
<p>One consequence of that shape: <code>search_tools</code> is annotated read-only, while <code>execute_tool</code> is annotated destructive and open-world, because it runs whatever connected tool it is handed. A client that prompts on anything not marked read-only will prompt on every BambooHR call, reads included. This is a client-side UX behavior, not something the restriction layer controls.</p>
<h2 id="should-you-use-bamboohrs-own-mcp-server-instead">Should you use BambooHR's own MCP server instead?</h2>
<p>If BambooHR is the only app you need in the assistant, yes. BambooHR runs an official MCP server, in beta, at <code>{subdomain}.bamboohr.com/api/mcp</code>, and it powers BambooHR's own Claude and ChatGPT connectors. An admin gate decides who may use it. BambooHR says it enforces BambooHR's existing permissions, omitting restricted fields without warning (<a href="https://documentation.bamboohr.com/docs/mcp-server">BambooHR MCP server docs</a>, checked October 2026). Ask BambooHR answers from data the user can access, and HR can read the chats (<a href="https://help.bamboohr.com/s/article/1881525">BambooHR help</a>, checked October 2026).</p>
<p>Per-person permissions, enforced by the system that owns the data, with no second vendor in the path. That is a genuinely good answer for a single app, and the silent field omission matches the API behavior either way.</p>
<p>What BambooHR's own pages do not claim is the part that decides the rest of the question:</p>
<ul>
<li>One address covering apps from different vendors (BambooHR, Jira, Zendesk, a payroll provider) rather than one MCP server per app.</li>
<li>Restrictions written once for a role, applying across all of those apps rather than configured separately in each vendor's admin panel.</li>
<li>One audit trail spanning them, instead of one log per vendor.</li>
<li>Ending a person's access to all of them in one action.</li>
</ul>
<p>If HR also needs Jira, Zendesk and a payroll provider in the same assistant, those four gaps are the reason to put a control plane in front. If it does not, adding one is unnecessary overhead. Removal in Elaichi ends access through Elaichi and nothing more; the person's BambooHR account still exists and must be deprovisioned on BambooHR's side separately.</p>
<p><strong>Decision rule:</strong> for a single-app HR assistant, BambooHR's own MCP server. For an assistant spanning HR, support and project tools under one role model, a control plane in front of all of them.</p>
<h2 id="adding-one-endpoint-in-claude-or-chatgpt">Adding one endpoint in Claude or ChatGPT</h2>
<p>Every connected account is served through one organization-wide endpoint: <code>POST https://api.elaichi.ai/mcp</code>. There are no per-user URLs and no embedded tokens. An admin adds the address once where the client allows it. Each member then signs in with their own OAuth grant. OAuth is the browser sign-in that issues a client its access, with no key to paste.</p>
<p>In Claude Team and Enterprise, an Owner or Primary Owner adds it under Organization settings, Connectors, Add, Custom, Web. Members then connect it under Customize, Connectors (<a href="https://support.claude.com/en/articles/11175166">Anthropic support</a>, checked October 2026). In ChatGPT, custom MCP apps with write actions are in beta on Business, Enterprise and Edu. Only Admins and Owners publish one (<a href="https://help.openai.com/en/articles/12584461">OpenAI help</a>, checked October 2026). OpenAI now manages apps under Plugins in the Admin Console, so follow the current path in the ChatGPT guide below. Step-by-step versions are in <a href="/blog/connect-elaichi-to-claude/">connecting Elaichi to Claude</a> and <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>.</p>
<p>On the consent screen, every scope the client asked for is pre-ticked except delete, which is never pre-ticked. With "Run your connected tools" ticked, a second step offers All my tools or Only the ones I pick. Read one line carefully here: for a connected app's tools, "Run your connected tools" covers reads and writes alike. Leaving "Create and change data" unticked does <strong>not</strong> make BambooHR read-only, because that checkbox governs Elaichi's own operations, not the connector's. Read-only BambooHR access is a restriction (layer two above), not a consent-screen setting. A finance team reaches the same conclusion in <a href="/blog/finance-team-claude-quickbooks-read-only/">QuickBooks read-only for a finance team</a>.</p>
<h2 id="what-the-audit-trail-records-for-a-bamboohr-call">What the audit trail records for a BambooHR call</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account actually reached. Each entry records the operation and tool, the connection, the classification, whether it was approved, the outcome, and an error code. The entry holds no argument values, with one exception: the one path argument that names the object is recorded as the target id.</p>
<p>For HR data that default is the right one, and it is also a limit. The log proves that a given member ran an employee lookup through Claude at a given time. It records the object-naming path argument as the target id and nothing else about the arguments, so the fields requested and the values returned are not in the log. An investigation that needs that detail has to look on BambooHR's side.</p>
<p>The error text has a firewall around it. What the caller sees is derived from BambooHR's response body. What is written to the audit trail never is. Audit records are organization-visible and can be forwarded to a customer's own destination. A call from Claude or ChatGPT is recorded with <code>actor_kind</code> of <code>user</code>, the surface <code>mcp</code>, and the OAuth client named. Claude and ChatGPT are among the clients whose name is marked verified by their redirect URIs. The trail is append-only. A compliance reviewer reads it on the free Auditor seat, which lacks <code>tool:execute</code>. So an Auditor cannot call BambooHR at all, only read what others called. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the record shape in full.</p>
<h2 id="who-owns-the-bamboohr-connection-when-its-creator-leaves">Who owns the BambooHR connection when its creator leaves?</h2>
<p>Someone has to, and it will not resolve itself. Elaichi's offboarding preflight lists every connection the departing member owns. A shared connection stays in place unless the admin names an action. It can be transferred to one other active member or deleted, never to the admin running the removal. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>A transfer changes one thing: the owner. The credential behind the connection is still the original person's sign-in to the app. For BambooHR that credential is an API key tied to their BambooHR user. Plan for it to stop working when that account is deactivated, which would take the whole HR team's access with it. Every toolbox entry the departing owner pinned to that connection also stops resolving after a transfer. That holds for everyone including the new owner, until someone re-pins it.</p>
<p>So plan the swap before the leaving date:</p>
<ol>
<li>Issue a new API key from a BambooHR account that is staying, at the same compensation-hiding access level.</li>
<li>Connect BambooHR again in Elaichi with that key, owned by a member who is staying, and share it with the HR team at <code>use</code>.</li>
<li>During the leaver's offboarding, delete the old connection or transfer it to another active member.</li>
</ol>
<p>A private connection pinned into a toolbox its owner shared is marked <code>needs_resolution</code> and waits for an administrator's decision. That is one more reason to pick a long-tenured owner at the start rather than transfer reactively. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding AI access</a> covers the rest of the preflight.</p>
<h2 id="related-questions">Related questions</h2>
<p><strong>Can ChatGPT see my BambooHR salary data if it's connected via MCP?</strong> Only if the credential behind the connection belongs to a user whose BambooHR access level includes compensation. A restriction can withhold the pay tools. But an employee read can still return pay fields if the key's user can see them. That is why layer one comes first.</p>
<p><strong>Is MCP inherently unsafe for HR data?</strong> No. MCP is a protocol for tool discovery and invocation; it has no opinion on field-level permissions. Safety depends entirely on what the underlying API key can see, which is BambooHR's access level. It also depends on what the control plane in front of it allows, the restriction. The protocol itself neither adds nor removes risk.</p>
<p><strong>Does restricting tools in Elaichi affect BambooHR's own UI or reports?</strong> No. Restrictions apply only to calls made through Elaichi's MCP endpoint. A user's direct BambooHR login and its existing access level are unaffected.</p>
<hr>
<p>The tool list for this connector is on the <a href="/connectors/bamboohr/">BambooHR connector page</a>. For the shape of the thing you are building, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For the same playbook against a payroll system, see <a href="/blog/hr-team-claude-gusto-payroll/">keeping payroll data in HR with Gusto</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does a BambooHR API key see salary data?</strong></dt><dd>It sees whatever the BambooHR user who created it can see. BambooHR states that the API can only view or update data that the user can access ([BambooHR help](https://help.bamboohr.com/s/article/587841), checked October 2026), and Get Employee drops fields the caller cannot view without returning an error. Pay data sits in the compensation table and the payRate, payType and paidPer fields, so a key created by an account whose access level hides those fields returns records without them.</dd><dt><strong>Can a consent checkbox make BambooHR read-only in Claude or ChatGPT?</strong></dt><dd>No. On Elaichi's consent screen, "Run your connected tools" covers a connected app's reads and writes alike, and only a tool whose method is a delete needs the destructive scope on top. "Create and change data" governs Elaichi's own operations, not the connected app. Read-only access to BambooHR is written as a restriction in Elaichi, either an allow rule naming the read tools a role needs or blocks on the write tools. A restriction change takes effect within about two minutes.</dd><dt><strong>Why use an allow rule instead of blocking BambooHR's pay tools?</strong></dt><dd>Because Elaichi's BambooHR connector carries 406 tools, and a block list leaves every tool it does not name reachable. An allow rule names what a role may reach and denies the rest. One caution: in Elaichi an allow rule is the target's whole allowlist across every connector, so a role that also uses other apps needs an allow rule naming each of those connectors whole, or it loses them. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</dd><dt><strong>Does BambooHR have its own MCP server?</strong></dt><dd>Yes. BambooHR runs an official MCP server in beta at {subdomain}.bamboohr.com/api/mcp, which powers its Claude and ChatGPT connectors. An admin gate decides who may use it, and BambooHR says it enforces the company's existing BambooHR permissions, omitting restricted fields without warning ([BambooHR MCP server docs](https://documentation.bamboohr.com/docs/mcp-server), checked October 2026). For a company whose assistant only needs BambooHR, that is a sound choice with no second vendor involved.</dd><dt><strong>What happens to a BambooHR connection when the person who created the API key leaves?</strong></dt><dd>The key belongs to their BambooHR user, so it keeps working until BambooHR's side is handled and should be expected to stop working when their BambooHR account is deactivated. Elaichi's offboarding preflight lists every connection the departing member owns. A shared connection can go to one other active member or be deleted when the admin names that action, and never to the admin running the removal. A transfer changes only the owner, so before the leaving date connect BambooHR again with a key from a staying account at the same access level, and share that connection.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Keep payroll data in HR with Gusto in Claude</title>
      <link>https://elaichi.ai/blog/hr-team-claude-gusto-payroll/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/hr-team-claude-gusto-payroll/</guid>
      <description>Gusto in Claude runs on Gusto&apos;s own MCP server. One admin connects it in Elaichi, HR gets a Gusto-only toolbox, and roles decide who reaches which tool.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Gusto in Claude runs on Gusto's own MCP server, which reads payroll and people data and can log time, onboard people and run payroll, with Gusto asking for confirmation on every write. In Elaichi, a primary or global Gusto admin connects it once, the HR team gets a toolbox holding only Gusto tools, and restrictions per role decide which Gusto tools each person can reach. Every call that runs is recorded with the person who made it, even on a shared connection.</aside>
<p>An HR lead wants Gusto in Claude. The ask is reasonable: stop exporting a CSV every time a manager wants a headcount, and stop rebuilding the payroll checklist by hand. The worry is also reasonable. Payroll and salary data should reach the people who run payroll, and nobody else who happens to use the same AI client.</p>
<p>This playbook covers Gusto's own MCP server, run through Elaichi. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<h2 id="what-can-gusto-in-claude-do-through-gustos-own-mcp-server">What can Gusto in Claude do through Gusto's own MCP server?</h2>
<p>Gusto's MCP server reads live payroll and people data, and it acts. Gusto lists logging time, onboarding an employee or contractor, and preparing and running payroll (<a href="https://gusto.com/product/integrations/gusto-mcp">gusto.com</a>, checked October 2026). Gusto also says every write comes back for confirmation before anything moves.</p>
<p>Gusto builds and runs this server. In Elaichi it is a native MCP connector: Gusto's tools, with Elaichi handling sign-in, access and audit in front of them. Elaichi does not write or fix these tools. Reports about how a tool behaves go to Gusto at <a href="https://support.gusto.com/">support.gusto.com</a>.</p>
<p>Gusto's server decides which tools each account gets. The <a href="/connectors/gusto-mcp/">Gusto connector page</a> lists no fixed tool set for that reason. The tools you govern are the ones Gusto's server lists to your connection, and you read them on that connection's page in Elaichi.</p>
<p>Gusto's confirmation step deserves a plain reading. The confirmation goes to the person in the chat. Through a shared toolbox, that person may not be the admin whose Gusto account the call runs on. Decide who may confirm a payroll run before anyone shares anything.</p>
<h2 id="who-can-connect-gusto-and-what-does-the-connection-see">Who can connect Gusto, and what does the connection see?</h2>
<p>Only a primary or global Gusto admin can connect the server. Gusto says a connected assistant reads the Gusto data the authorizing user can already see, and nothing beyond it (<a href="https://gusto.com/product/agents">gusto.com</a>, checked October 2026). An admin's view is wide, so the connection is wide.</p>
<p>Gusto gives one lever at sign-in. OAuth (the browser sign-in that grants an app access without a password) asks the admin to choose which categories of Gusto data to share. Pick only what HR needs. That choice is the ceiling for every person who later uses the connection, and Elaichi can narrow below it but never above it.</p>
<p>In Elaichi, the credential stays with Elaichi's separate credential service. The AI client holds only an Elaichi token. A connection someone shares runs on its owner's account, so every Gusto call through it reaches Gusto as that admin.</p>
<h2 id="should-hr-share-the-gusto-connection-or-a-gusto-toolbox">Should HR share the Gusto connection or a Gusto toolbox?</h2>
<p>Share a toolbox, and keep the connection private to the admin. A toolbox is a named set of tools pinned to connections. One that holds only Gusto tools gives the HR team exactly those tools and nothing else from the admin's account.</p>
<p>The two choices differ in reach:</p>
<table>
<thead>
<tr>
<th>Share</th>
<th>What an HR member reaches</th>
</tr>
</thead>
<tbody>
<tr>
<td>The connection, at use</td>
<td>Every tool Gusto's server lists to that connection, minus their restrictions</td>
</tr>
<tr>
<td>A Gusto-only toolbox, at use</td>
<td>Only the tools in the toolbox, minus their restrictions</td>
</tr>
</tbody>
</table>
<p>A use grantee runs a toolbox's tools without holding any access to the connection behind them. Elaichi still checks that person's own restrictions on every call. Revoking the share takes effect on their next call.</p>
<p>A member who is also a Gusto admin can connect their own account instead. That route suits an admin who uses Gusto in Claude alone. It does not work for a coordinator who is not a Gusto admin, because Gusto requires a primary or global admin to connect.</p>
<h2 id="how-do-roles-and-restrictions-split-gusto-tools-inside-hr">How do roles and restrictions split Gusto tools inside HR?</h2>
<p>Restrictions on roles decide which Gusto tools each person can reach. A restriction is a rule on a role or on one member, naming whole connectors or single tools. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. There is no team target, so HR needs roles of its own, such as an HR coordinator role and a payroll role, built as custom roles on Gold.</p>
<p>A workable split for most HR teams:</p>
<ul>
<li><strong>Every role outside HR.</strong> Restrict the Gusto connector whole. That also stops another Gusto admin elsewhere in the company from connecting their own account through Elaichi.</li>
<li><strong>HR coordinator.</strong> Restrict the payroll-run tools and any compensation reads Gusto lists to your account.</li>
<li><strong>Payroll.</strong> Keep the full Gusto toolbox.</li>
</ul>
<p>A restricted tool is not offered to the member's AI client, and a call to it is refused. A member's own rule can only narrow what their role allows; it never widens or replaces the role's rules. A change takes effect within about two minutes. The trade-offs between naming a whole app and naming one tool are worked through in <a href="/blog/per-tool-vs-per-app-restrictions/">per-tool versus per-app rules</a>.</p>
<h2 id="why-does-elaichi-treat-an-unmarked-gusto-tool-as-destructive">Why does Elaichi treat an unmarked Gusto tool as destructive?</h2>
<p>An MCP server can mark each tool as read-only or as non-destructive. For a native MCP connector, Elaichi counts any tool the server marks as neither as destructive. That is the default for every vendor's server, not a judgment about Gusto.</p>
<p>A destructive tool needs more from the AI client's grant (the access a person approves for one client). The person must tick "Delete data and remove access" at Elaichi's consent screen, as well as "Run your connected tools". That box is never ticked by default. It also covers deleting things in Elaichi itself, so tick it only where the HR chat needs those Gusto tools.</p>
<p>An admin can review each Gusto tool's tier in the console and lower it per tool. The console shows whether a tier came from Gusto's own label, from the default or from an override.</p>
<h2 id="can-you-follow-gustos-use-in-isolation-advice-through-elaichi">Can you follow Gusto's "use in isolation" advice through Elaichi?</h2>
<p>Partly. Gusto's guidelines ask you to use its MCP server in isolation, with no other MCP servers in the same client session. They also ask for trusted clients only, manual confirmation for all tool use, checked outputs and an opt-out of model training (<a href="https://gusto.com/product/integrations/gusto-mcp">gusto.com</a>, checked October 2026).</p>
<p>Elaichi serves many apps through one endpoint, <a href="https://api.elaichi.ai/mcp">https://api.elaichi.ai/mcp</a>. Isolation is something you set up per client grant:</p>
<ul>
<li><strong>What helps.</strong> At consent, each HR member picks Only the ones I pick and selects the Gusto toolbox. That grant reaches only that toolbox's connected tools, and never falls back to all of the person's tools.</li>
<li><strong>What Elaichi still adds.</strong> Elaichi's own operations stay available to that grant, according to the scopes the person ticked. Leave "Create and change data" unticked if the HR chat does not need it.</li>
<li><strong>What Elaichi cannot see.</strong> Other connectors the person turned on in Claude sit outside Elaichi. Claude lets a person switch connectors on or off for each chat (<a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">support.claude.com</a>, checked October 2026). Turn the others off for Gusto work.</li>
</ul>
<p>For manual confirmation, set Claude's tool permission on Elaichi's execute_tool to Needs approval. That one setting covers every connected-tool call made through execute_tool, so it cannot tell Gusto from another app. Model-training settings live in the AI client, and Elaichi does not change them.</p>
<p>Gusto's trusted-client examples are Claude, Gemini and Cursor. Its guidelines do not mention a layer in between. Routing through Elaichi adds a party that holds the Gusto credential, and your security review should weigh that.</p>
<h2 id="what-does-the-audit-log-record-for-each-gusto-call">What does the audit log record for each Gusto call?</h2>
<p>The audit log (the organization's append-only record of actions) gets one row for each Gusto call that reaches execution. The row names the person who made the call, the tool, the connection it reached, the AI client and whether it worked. On a shared toolbox, it names the HR member, not only the admin whose account Gusto saw.</p>
<p>A call refused before execution, such as a restricted tool or a missing consent scope, writes no row. The row keeps no argument values, apart from the one path argument that names the object, recorded as the target id. So a pay rate passed as an argument is not written to the log.</p>
<h2 id="when-should-hr-connect-gusto-directly-or-not-at-all">When should HR connect Gusto directly, or not at all?</h2>
<p>Connect Gusto's server directly when one or two Gusto admins will use it themselves, in one client, with no other apps. Gusto's guidelines are written for that shape. A direct connection skips Elaichi entirely, so Elaichi governs none of those calls, and nothing is lost if nobody else needs access.</p>
<p>Elaichi earns its place when non-admins need Gusto, when HR also works in other apps through Claude, ChatGPT, Cursor or any MCP client, or when the company wants one audit trail. The wider argument is in <a href="/blog/vendor-mcp-servers-through-elaichi/">running vendor MCP servers through Elaichi</a>.</p>
<p>Do not connect Gusto at all in three cases:</p>
<ul>
<li>The company will not accept an admin-level connection used by people who are not admins.</li>
<li>The team will not keep confirmations manual, in Gusto and in the client.</li>
<li>The data categories Gusto offers at sign-in are wider than anyone outside payroll should reach.</li>
</ul>
<h2 id="what-happens-to-the-gusto-connection-when-its-admin-leaves">What happens to the Gusto connection when its admin leaves?</h2>
<p>The HR setup keeps working only if you plan the handover. Elaichi's offboarding preview lists every connection the departing admin owns and the toolboxes that pin it. Transfer the HR toolbox to an admin who is staying. A transfer changes the owner and keeps every share.</p>
<p>The toolbox's entries still run on the departing admin's Gusto sign-in. Before that Gusto account is deprovisioned, have the staying admin connect Gusto with their own account and point the toolbox's entries at the new connection. Then deprovision the old account in Gusto or through your identity provider. The general version of this problem is in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding when the agent holds access</a>, and other HR setups, such as <a href="/blog/hr-team-claude-rippling-employees/">Rippling in Claude</a>, are on the <a href="/use-cases/">use cases page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Gusto in Claude run payroll?</strong></dt><dd>Yes, through Gusto's own MCP server. Gusto says the server can prepare and run payroll, log time, and onboard employees and contractors, and that every write comes back for confirmation before anything moves ([gusto.com](https://gusto.com/product/integrations/gusto-mcp), checked October 2026). In Elaichi, payroll-run tools can be restricted to the roles that should hold them.</dd><dt><strong>Who can connect Gusto to an AI assistant?</strong></dt><dd>Only a Gusto admin. Gusto's MCP page lists primary or global admin permissions as a requirement, and Gusto says a connected assistant reads what the authorizing user can already see ([gusto.com](https://gusto.com/product/agents), checked October 2026). A connection made by an admin therefore reaches admin-level data, within the data categories picked at sign-in.</dd><dt><strong>How do you stop HR coordinators from running payroll through Gusto in Claude?</strong></dt><dd>Give them a role of their own in Elaichi and write a restriction on that role naming Gusto's payroll-run tools. A restricted tool is not offered to their AI client and is refused if called. The rule takes effect within about two minutes. A person's own rule can only narrow what their role allows, never widen it.</dd><dt><strong>Does Elaichi write or fix the Gusto MCP tools?</strong></dt><dd>No. Gusto builds and runs the MCP server and its tools. Elaichi handles sign-in, access and audit in front of it, and reports about how a tool behaves go to Gusto's support team at support.gusto.com.</dd><dt><strong>Is a Gusto call recorded when HR uses a shared connection?</strong></dt><dd>Yes. Each Gusto call that reaches execution writes one audit row naming the person who made it, the tool, the connection, the AI client and the outcome. The row holds no argument values except the one path argument that names the object, recorded as the target id.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>IT admin controls for MCP connectors, compared</title>
      <link>https://elaichi.ai/blog/it-admin-controls-mcp-connectors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/it-admin-controls-mcp-connectors/</guid>
      <description>What the IT admin controls for MCP connectors cover in Claude, ChatGPT and Cursor, and the three gaps none of those consoles closes.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Claude, ChatGPT and Cursor each ship admin controls for MCP connectors, and each one governs only its own client. None of them writes a rule that holds in all three, none sees the individual tools behind a single endpoint, and none produces one audit trail across clients. Elaichi splits the work: use each client console to allow only approved connectors and to govern laptops, then write the per-app and per-tool rules once in Elaichi.</aside>
<h2 id="what-do-the-three-admin-consoles-control">What do the three admin consoles control?</h2>
<p>Each vendor console governs connectors on its own client and nothing else. The switches differ, the plan requirements differ, and so does the vocabulary.</p>
<p>You approved Claude for support, ChatGPT for marketing and Cursor for engineering. Each one now has an admin page for connectors, and none of those pages knows the other two exist. So IT admin controls for MCP connectors is really three questions, answered in three places. MCP (Model Context Protocol) is the protocol an AI client speaks to reach tools outside itself, and a connector is a server it talks to.</p>
<p>This comparison covers Claude, ChatGPT and Cursor. Microsoft Copilot's MCP governance runs through Power Platform data policies, advanced connector policies and the Microsoft 365 admin center. That stack is compared in <a href="/blog/copilot-studio-vs-mcp-gateway/">Copilot Studio vs an MCP gateway</a>. If you run a mixed fleet that includes Copilot, treat the table below as partial.</p>
<p>Everything below is read from each vendor's own documentation, checked October 2026. Date anything you copy out of it, because these consoles move.</p>
<table>
<thead>
<tr>
<th>Control</th>
<th>Claude (Team, Enterprise)</th>
<th>ChatGPT (Business, Enterprise, Edu)</th>
<th>Cursor</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who adds a custom MCP server</td>
<td>Owner or Primary Owner; on Enterprise also a custom role with Libraries (Manage)</td>
<td>Admins and Owners publish; on Enterprise and Edu, RBAC can let members build drafts</td>
<td>Team admins distribute shared servers; individuals add their own by URL</td>
</tr>
<tr>
<td>Allowlist of approved servers</td>
<td>Directory connectors stay off until an Owner adds them</td>
<td>Per-app on or off for the workspace</td>
<td>Policy allowlist, Enterprise only</td>
</tr>
<tr>
<td>Different apps for different teams</td>
<td>Enterprise custom roles narrow further</td>
<td>Enterprise and Edu only, through custom roles</td>
<td>Team Marketplace distributes; policy is Enterprise</td>
</tr>
<tr>
<td>Per-tool approval</td>
<td>Always allow, Needs approval or Blocked, per tool or group</td>
<td>Per-app Actions switch read and write actions separately</td>
<td>Approval prompt before tool use, on by default</td>
</tr>
<tr>
<td>Members can request one</td>
<td>Team members see Request on directory connectors</td>
<td>No request flow documented for custom apps</td>
<td>Not documented</td>
</tr>
<tr>
<td>Reaches servers on laptops</td>
<td>Anthropic says connector permissions do not govern locally run servers</td>
<td>Not documented</td>
<td>MDM-deployed hooks see each call</td>
</tr>
</tbody>
</table>
<p>Sources, all checked October 2026: Anthropic's <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">custom connector</a> and <a href="https://claude.com/docs/connectors/directory">directory</a> pages, OpenAI's <a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">admin controls for plugins and apps</a>, and <a href="https://cursor.com/docs/mcp">cursor.com/docs/mcp</a>.</p>
<h2 id="what-can-an-owner-enforce-in-claudes-console">What can an Owner enforce in Claude's console?</h2>
<p>Claude's console governs what an Owner added, on Anthropic's surface only. Directory connectors stay off until an Owner or Primary Owner adds them under Organization settings, then Browse connectors, then Add to your team. Adding connects nobody. Each member still signs in with their own account.</p>
<p>Custom connectors, which is what a remote MCP server is, are added by Owners and Primary Owners. On Enterprise a custom role holding Libraries (Manage) can add one as well. Ordinary members cannot add one; they enable what was added. The order these steps belong in across a whole company is set out in <a href="/blog/roll-out-claude-and-chatgpt-to-employees/">the Claude and ChatGPT rollout sequence</a>.</p>
<p>On Team, members see a Request button on a directory connector. Owners find those requests under Requested by your team in Organization settings, and on the Requests tab in Notifications (<a href="https://claude.com/docs/connectors/directory">claude.com/docs/connectors/directory</a>, checked October 2026). Anthropic's page does not say Enterprise members get the same button, so do not plan around it.</p>
<p>Tool permissions are the sharp control. Per connector, per group or per tool, an Owner sets Always allow, Needs approval or Blocked. Anthropic states the limit in its own words on the <a href="https://support.claude.com/en/articles/13930452-manage-custom-roles-on-enterprise-plans">custom roles page</a> (checked October 2026). These permissions do not govern connectors a member runs locally on their own machine. That gap is worth treating as critical rather than cosmetic. A Blocked connector in the console does nothing to a copy of the same server a developer points Claude Desktop at locally. Device policy, covered below, is the only lever that reaches it.</p>
<h2 id="what-does-chatgpts-console-control-for-mcp-apps">What does ChatGPT's console control for MCP apps?</h2>
<p>ChatGPT's controls are per app, and on the right plans per role. Apps, formerly called connectors, are managed at Admin Console, then the workspace, then Plugins (<a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">help.openai.com</a>, checked October 2026). The older Workspace settings route is still reachable through Manage Legacy Apps. Labels moved during 2026, so date any menu path you write down.</p>
<p>Each app is on or off for the whole workspace. Business apps start on, and new Enterprise and Edu workspaces start with a selected set on. Giving different teams different apps is Enterprise and Edu only, through custom roles under Permissions and roles, then Custom roles, then Plugins and connected data. Roles add up, so any role granting a permission grants it, and changes take up to five minutes (<a href="https://help.openai.com/en/articles/11750701-managing-feature-access-with-role-based-access-control-in-chatgpt">help.openai.com</a>, checked October 2026).</p>
<p>Within an app, Actions turn read and write actions on separately. New actions decides what happens when the app gains more. Plugin permissions decide when ChatGPT asks first: Always ask, Allow read actions, Allow low-risk actions, and per app, Allow all actions. Members of a managed workspace never get a lasting Always allow (<a href="https://help.openai.com/en/articles/20001495-managing-app-permissions-in-chatgpt">help.openai.com</a>, checked October 2026).</p>
<p>Custom MCP apps are published by Admins and Owners only, and on Business only admins use developer mode. A published app runs on a frozen snapshot of its tools, so new actions arrive disabled until an admin refreshes them. OpenAI does not verify custom apps (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">help.openai.com</a>, checked October 2026). The frozen snapshot is a real failure mode. If a connector publisher adds a destructive new tool after the app was published, ChatGPT members cannot reach it until an admin refreshes the app. That is a safety net, and it also keeps a legitimately useful new read-only tool invisible for the same reason.</p>
<p>One consequence matters for any single-endpoint setup. Elaichi's connected tools are never listed individually; the model finds one with <code>search_tools</code> and runs it with <code>execute_tool</code>. ChatGPT therefore sees one app with a handful of tools, and its per-action switches cannot tell a Salesforce read from a Zendesk delete. Setting the Elaichi app to read actions only does not make the apps behind it read-only. Narrowing ChatGPT's own app list is covered in <a href="/blog/restrict-chatgpt-enterprise-connectors/">restricting ChatGPT Enterprise connectors</a>.</p>
<h2 id="what-can-a-cursor-team-admin-enforce">What can a Cursor team admin enforce?</h2>
<p>Cursor separates distribution from policy and says so plainly. "MCP distribution and MCP policy are configured separately. Team admins can distribute shared MCP servers. Enterprise admins can configure MCP policy" (<a href="https://cursor.com/docs/mcp">cursor.com/docs/mcp</a>, checked October 2026). That distinction generalizes beyond Cursor. In every console here, "who can make a server available" and "what that server is allowed to do once available" are separate permission axes. They are often on different plan tiers.</p>
<p>Shared Team MCP servers live under Dashboard, then Plugins and MCPs, and are available to Cloud Agents. Add to Team Marketplace makes one available in the Agent Window, the IDE and the CLI.</p>
<p>The policy allowlist is Enterprise only, and Cursor is explicit about what it does not do. Adding a server to the allowlist does not push it to users' machines. Team members still need to configure the server in their own Cursor settings. Individuals add a remote server by <code>url</code> in <code>.cursor/mcp.json</code> for a project or <code>~/.cursor/mcp.json</code> globally. Cursor supports OAuth for servers that require it, and asks for approval before using MCP tools by default.</p>
<p>For what the console cannot reach, Cursor documents hooks. An MDM-deployed <code>beforeMCPExecution</code> hook sees the server name and the URL or command on every call. It can allow, deny or ask (<a href="https://cursor.com/docs/hooks">cursor.com/docs/hooks</a>, checked October 2026). A device the hooks file never reached runs without the hook, so monitor MDM delivery.</p>
<h2 id="which-servers-sit-on-laptops-and-who-can-see-them">Which servers sit on laptops, and who can see them?</h2>
<p>Nobody's console lists them. No client vendor documents an admin inventory of the servers sitting in members' local config files. Admin consoles report only what connects through the vendor's own surface. Finding local servers means reading the files on each device with an MDM or EDR script.</p>
<p>The paths, all checked October 2026. Claude Desktop keeps servers in <code>claude_desktop_config.json</code> under <code>~/Library/Application Support/Claude/</code> or <code>%APPDATA%\Claude\</code> (<a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">modelcontextprotocol.io</a>). Claude Code uses <code>~/.claude.json</code> and a project <code>.mcp.json</code>; <code>~/.claude.json</code> also holds the sign-in session, so read only its <code>mcpServers</code> objects (<a href="https://code.claude.com/docs/en/mcp">code.claude.com</a>). Cursor uses <code>~/.cursor/mcp.json</code> and <code>.cursor/mcp.json</code> (<a href="https://cursor.com/docs/mcp">cursor.com/docs/mcp</a>). Codex uses <code>~/.codex/config.toml</code> (<a href="https://learn.chatgpt.com/docs/extend/mcp">learn.chatgpt.com</a>). VS Code with GitHub Copilot now steers new servers to <code>.mcp.json</code> at the project root and <code>~/.copilot/mcp-config.json</code> (<a href="https://code.visualstudio.com/docs/agent-customization/mcp-servers">code.visualstudio.com</a>). The longer version of this hunt is in <a href="/blog/find-mcp-servers-employees-installed/">find the MCP servers employees have installed</a>.</p>
<p>Device policy is where you close the gap. Claude Desktop reads <code>com.anthropic.claudefordesktop</code> on macOS and <code>HKLM:\SOFTWARE\Policies\Claude</code> on Windows, where <code>isLocalDevMcpEnabled</code> and the two desktop extension keys default to true (<a href="https://support.claude.com/en/articles/12622667-enterprise-configuration-for-claude-desktop">support.claude.com</a>, checked October 2026). Claude Code managed settings filter with <code>allowedMcpServers</code> and <code>deniedMcpServers</code>. The denylist always wins, and <code>managed-mcp.json</code> takes exclusive control. Anthropic warns that matching by <code>serverName</code> is not a security control, because users choose the names (<a href="https://code.claude.com/docs/en/managed-mcp">code.claude.com</a>, checked October 2026). VS Code ships <code>chat.mcp.access</code>, delivered as the <code>ChatMCP</code> policy, taking <code>all</code>, <code>registry</code> or <code>none</code>. Per-server allow and deny lists sit alongside it, where deny beats allow (<a href="https://code.visualstudio.com/docs/enterprise/manage-ai-settings">code.visualstudio.com</a>, checked October 2026). Devin Desktop, formerly Windsurf, blocks every other server for the team once any server is allowlisted (<a href="https://docs.devin.ai/desktop/cascade/mcp">docs.devin.ai</a>, checked October 2026).</p>
<h2 id="where-it-admin-controls-for-mcp-connectors-stop-short">Where IT admin controls for MCP connectors stop short</h2>
<p>Every console above governs its own client competently. Three jobs sit outside all of them.</p>
<p><strong>One rule that holds in all three clients.</strong> A tool restricted in Claude is not restricted in ChatGPT. An Enterprise allowlist in Cursor says nothing about what a member reaches in the ChatGPT web app. Each decision is written three times, by three admins, in three vocabularies, and starts drifting the day it is written. It fails silently: nothing errors, nothing logs a conflict, the same person simply has different access depending on which app they open.</p>
<p><strong>Per-tool rules for the apps behind one endpoint.</strong> Route your clients through a single MCP endpoint and each client sees that endpoint's tools, not the connected tools underneath. For an aggregator like Elaichi that is <code>search_tools</code> and <code>execute_tool</code>. A Claude tool permission set on <code>execute_tool</code> covers every connected tool at once. That is the right granularity for the endpoint and the wrong granularity for Jira versus Salesforce. This only matters if you've put an aggregating endpoint in front of your clients. If every connector is added directly in each console, this gap doesn't apply to you. The choice between those two levels is unpacked in <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool or the whole app</a>.</p>
<p><strong>One audit trail across clients.</strong> Anthropic's Compliance API records connector connects and disconnects for Enterprise, with no backfill (<a href="https://platform.claude.com/docs/en/api/compliance/activities">platform.claude.com</a>, checked October 2026). OpenAI's Compliance Logs Platform is Enterprise and Edu only, keeps files 30 days, and documents no tool-name field (<a href="https://chatgpt.com/public/admin/api-reference">chatgpt.com admin API reference</a>, checked October 2026). Cursor's Enterprise audit log carries <code>mcp_server_config</code> and <code>mcp_authentication</code> events (<a href="https://cursor.com/docs/enterprise/compliance-and-monitoring">cursor.com</a>, checked October 2026). Three formats, three retention windows, three sets of ids, and nothing joins them into an answer about last week's Salesforce changes. This doesn't block anything in real time. It does mean a post-incident investigation across clients requires manually correlating three exports by timestamp and user email, not by a shared id. The shape of the record you actually need is in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="disclosure-and-where-the-vendor-neutral-part-of-this-post-ends">Disclosure, and where the vendor-neutral part of this post ends</h2>
<p>Everything above is sourced to vendor documentation, dated, and checked against each vendor's documentation in October 2026. Everything below describes how Elaichi, the product this blog is published by, addresses the three gaps above. It is not vendor-neutral, and it is not independently audited. Read it as one vendor's design decision, not as documentation with the same evidentiary status as the Anthropic, OpenAI and Cursor links above.</p>
<h2 id="splitting-the-work-consoles-for-devices-endpoint-for-rules">Splitting the work: consoles for devices, endpoint for rules</h2>
<p>The client console decides which connectors exist on that client and what runs on employee laptops. A separate control plane like Elaichi decides what the approved connector may reach, once, for every client. That is the general shape of the fix for the three gaps above, independent of which vendor implements it.</p>
<p>In the client console, allow only the connectors you approved and govern local servers. That means Claude's device policy keys and Claude Code managed settings, Cursor's Enterprise allowlist plus an MDM hook, VS Code's <code>chat.mcp.access</code>, and ChatGPT's per-app switches. Nobody can do that part for you, because the files sit on the devices.</p>
<p>In Elaichi specifically, a restriction names whole connectors, single tools, or both. It targets a role or a user, which is why <a href="/blog/designing-roles-for-ai-agents/">each role is written as one complete job</a>. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A user-targeted rule can only narrow what the role allows, and blocks always beat allows. To let one person past a role block, they file an access request and an admin approves it. An allow rule is the target's whole allowlist across every connector, so every app the rule does not name is denied for that role. Holding one app to reads without touching the rest is done with blocks on that app's write tools.</p>
<p>A restricted tool is withheld from <code>tools/list</code> and cannot be called. <code>search_tools</code> names it, flagged restricted, with no schema, so the model has nothing it can run. Role and restriction changes take effect about two minutes, on the MCP endpoint, the console and the REST API alike. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>One organization-wide endpoint serves Claude, ChatGPT, Cursor and any other MCP client, so the rule is written once. Each member still connects and signs in with their own OAuth grant. That grant is the browser consent that hands their client a scoped permission to act as them. The audit trail records the surface and the OAuth client each call came through. The client's name is marked verified when its redirect URIs prove it, which covers Claude, ChatGPT and Cursor. A client signing in through a loopback address, such as Claude Code or Codex CLI, shows the name it registered with, marked unverified.</p>
<h2 id="when-the-client-consoles-are-enough">When the client consoles are enough</h2>
<p>Skip the second layer when there is nothing underneath it to govern. If your agents only reach servers your own engineers wrote, the client consoles plus device policy are the whole control set. A second vendor buys you nothing.</p>
<p>If you have standardized on Cloudflare Access, Cloudflare's MCP server portals put remote HTTP MCP servers behind one endpoint. That endpoint sits inside the access layer you already run, with per-server sign-in for users (<a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">developers.cloudflare.com</a>, checked October 2026). This is a different shape from Elaichi. Cloudflare fronts whichever servers you or your vendors run, as you add them to a portal. Elaichi serves 600+ connectors, authoring most of them and governing vendors' own MCP servers for the rest, so there are no servers for you to run or list.</p>
<p>Pick based on what your agents reach, not on vendor preference. Servers you wrote point toward a fronting layer like Cloudflare Access; SaaS accounts your staff already hold point toward a managed-connector layer like Elaichi. The architecture behind that split is in <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. The per-client version of the same argument is in <a href="/blog/elaichi-vs-native-ai-connectors/">Claude and ChatGPT connectors against one endpoint</a>. The apps the rules apply to are listed at <a href="/connectors/">/connectors/</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can one admin console govern MCP connectors in Claude, ChatGPT and Cursor at once?</strong></dt><dd>No. Each vendor's admin console governs only its own client. Claude Team and Enterprise control the connectors an Owner added plus per-tool approval states; ChatGPT Business, Enterprise and Edu control per-app switches and read or write actions; Cursor's policy allowlist is Enterprise only and does not push servers to machines. A rule written in one console does not reach the other two, so a company-wide rule has to live at the server the clients connect to. All checked October 2026.</dd><dt><strong>Does Claude's per-tool permission cover connectors a member installs locally?</strong></dt><dd>No. Anthropic's custom roles page states that connector tool permissions do not govern connectors a member runs locally on their own machine (checked October 2026). Local servers are governed separately: Claude Desktop device policy keys such as isLocalDevMcpEnabled, and for Claude Code the allowedMcpServers and deniedMcpServers managed settings, where the denylist always wins.</dd><dt><strong>Will setting a ChatGPT app to read actions only make the apps behind it read-only?</strong></dt><dd>Not when the app is a single MCP endpoint. ChatGPT's per-action switches apply to the tools the app advertises. Elaichi advertises search_tools, execute_tool and its own control-plane operations, and connected tools are never listed individually, so one switch covers every connected app at once. Read-only access to a specific connected app is written in Elaichi as a restriction: blocks on that app's write tools, or an allow rule naming its read tools. An allow rule is the role's whole allowlist across every connector, so blocks on that app's write tools are the way to hold one app to reads without touching the rest.</dd><dt><strong>How do I find the MCP servers employees already configured?</strong></dt><dd>By reading the config files on each device with an MDM or EDR script. No client vendor documents an admin inventory of servers sitting in members' local config files; admin consoles report only servers that connect through the vendor's own surface. The paths include ~/.cursor/mcp.json for Cursor, ~/.claude.json and .mcp.json for Claude Code, ~/.codex/config.toml for Codex, and claude_desktop_config.json for Claude Desktop.</dd><dt><strong>How long does a restriction change in Elaichi take to apply?</strong></dt><dd>A role or restriction change takes effect about two minutes. Both resolve through a 60-second cache plus edge propagation, on the MCP endpoint, the console and the REST API alike. Some changes are faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Intune in Claude for help desk lookups only</title>
      <link>https://elaichi.ai/blog/it-team-claude-intune-devices/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/it-team-claude-intune-devices/</guid>
      <description>Intune in Claude for a help desk is one allow rule, not six blocks: the msintune connector carries 198 tools and only 69 of them read.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi's msintune connector carries 198 tools, and only 69 of them read. Blocking the six obvious device actions leaves every other write reachable, so hold the help desk role with an allow rule naming the read tools it needs, plus allow rules for the other apps that role uses. Connect Intune with the narrowest Microsoft account that covers those reads, because msintune calls reach Microsoft Graph as the connecting account.</aside>
<h2 id="what-a-help-desk-ticket-actually-needs-from-intune">What a help desk ticket actually needs from Intune</h2>
<p>A technician picks up a ticket: this laptop never applied the new Wi-Fi profile. The answer sits in Microsoft Intune. Which devices does the person have, is each one compliant, which configuration profiles landed, what apps were detected. Five read calls and the ticket closes. Putting Intune in Claude is worth doing for exactly that loop. The risk is everything else that arrives with it.</p>
<p><a href="/connectors/msintune/">Elaichi's <code>msintune</code> connector</a> carries 198 tools. Sixty-nine have names starting with <code>list_</code> or <code>get_</code>, and they read, including <code>list_all_msintune_managed_devices</code>, <code>get_single_msintune_managed_device_by_id</code>, <code>list_all_msintune_device_compliance_policies</code>, <code>list_all_msintune_device_configurations</code> and <code>list_all_msintune_detected_apps</code>. Most of the other 129 create, update or delete records, or run actions on devices: wipe, retire, remote lock, script deployment and more.</p>
<p>Elaichi serves 600+ connectors through one organization-wide MCP endpoint. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The design question for any connected app is the same: which of a connector's tools may a given role reach, and how is that decision enforced so it cannot quietly widen over time? For Intune specifically, that means deciding on the 69 read tools. Write the decision down once, rather than re-deciding it per technician or per incident.</p>
<h2 id="general-principle-allowlists-survive-denylists-decay">General principle: allowlists survive, denylists decay</h2>
<p>Before the Intune specifics, the underlying rule generalizes to any tool-calling AI connector, not just MCP or Elaichi:</p>
<ul>
<li><strong>A denylist only covers what you named.</strong> Every tool you didn't think to block on the day you wrote the rule stays reachable. Tools a connector gains later are reachable by default unless the denylist is re-audited on every connector update.</li>
<li><strong>An allowlist is closed by construction.</strong> Naming the tools a role <em>may</em> use means everything else is denied, including tools that don't exist yet. This is the standard <a href="/blog/least-privilege-tool-calls-without-breaking-automation/">default-deny posture applied to tool calls</a>.</li>
<li><strong>The two produce different failure modes.</strong> A denylist fails open (new or unnamed tools leak through). An allowlist fails closed (a technician hits a wall and has to file a request). Some workflows carry a high downside from an unreviewed write, such as device wipe, user deletion or remote lock. For those, fail-closed is the only defensible default.</li>
</ul>
<p>This is a restatement of a well-known security principle (default-deny beats default-allow), not something specific to Elaichi.</p>
<h2 id="why-blocking-wipe-and-retire-is-not-read-only">Why blocking wipe and retire is not read-only</h2>
<p>Six blocks is the obvious move, and it does not produce a read-only role. A block rule covers only the tools it names.</p>
<p>The six that come to mind: <code>msintune_managed_devices_wipe</code>, <code>msintune_managed_devices_retire</code>, <code>msintune_managed_devices_remote_lock</code>, <code>msintune_managed_devices_reset_passcode</code>, <code>msintune_managed_devices_bypass_activation_lock</code> and <code>delete_a_msintune_managed_device_by_id</code>. Block all six and the role still holds <code>msintune_managed_devices_execute_action</code>. That tool runs a named remote action on one or more devices via two arguments, <code>actionName</code> and <code>deviceIds</code>. Blocks on the six named tools do not cover it. A block matches a tool's name or its pinned operation, and this is a different operation.</p>
<p>Still reachable after those six blocks:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Effect</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>msintune_managed_devices_clean_windows_device</code></td>
<td>Cleans a Windows device, with a choice to keep or remove user data</td>
</tr>
<tr>
<td><code>msintune_managed_devices_reboot_now</code></td>
<td>Reboots the device</td>
</tr>
<tr>
<td><code>msintune_managed_devices_shut_down</code></td>
<td>Shuts the device down</td>
</tr>
<tr>
<td><code>msintune_managed_devices_disable</code></td>
<td>Disables a managed device</td>
</tr>
<tr>
<td>create/assign device management scripts</td>
<td>Creates scripts and assigns them to groups of devices</td>
</tr>
<tr>
<td><code>delete_a_msintune_user_by_id</code></td>
<td>Deletes a Microsoft Entra ID user, not just a device</td>
</tr>
</tbody>
</table>
<p>A denylist is a list of the writes somebody thought of on the day it was written. It is not, and cannot become, a complete inventory of what a connector can do. The wider trade-off between blocking individual tools and blocking an entire app is in <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool against the whole app</a>.</p>
<h2 id="writing-the-allow-rule-for-intune-in-claude">Writing the allow rule for Intune in Claude</h2>
<p>Intune in Claude becomes a lookup tool when the help desk role holds an allow rule. That rule names the five read tools above, not a stack of blocks. A restriction in Elaichi states which connectors and tools a role or a user may reach. Name the five, and every other <code>msintune</code> tool is denied for that role by default.</p>
<p>One property catches people out: <strong>an allow rule is the target's entire allowlist across every connector, not just the app it mentions.</strong> Allow rules on the same role union together: the role's allowlist is the sum of every allow rule attached to it. If the help desk role also uses Slack and Jira, you must write a separate allow rule naming each of those connectors in full. Without them, the role loses Slack and Jira as soon as the Intune-only allow rule takes effect. The presence of any allow rule switches that role from default-allow to default-deny across the board.</p>
<p>Two mechanical details matter before you save the rule:</p>
<ul>
<li><strong>A restricted tool is withheld, not just refused.</strong> It is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema.</li>
<li><strong>A restriction change is not instant.</strong> It takes effect within about two minutes. Blocks match a tool's name or its pinned operation; allows match the pinned operation only. That asymmetry is the subject of <a href="/blog/block-matches-name-allow-matches-operation/">why allows bind the operation</a>.</li>
</ul>
<h2 id="which-microsoft-account-should-hold-the-intune-connection">Which Microsoft account should hold the Intune connection?</h2>
<p>Connect with the narrowest Microsoft account that covers the required reads. The <code>msintune</code> connector signs in with OAuth as a person, so every call reaches <a href="https://learn.microsoft.com/en-us/intune/intune-service/developer/intune-graph-apis">Microsoft Graph</a> as that account (checked October 2026). A shared connection runs on its owner's credential. Every technician's lookup reaches Graph as the connecting account, regardless of what Microsoft role that individual technician holds personally. The opposite shape, where <a href="/blog/sales-team-chatgpt-salesforce-accounts/">each person connects their own account</a>, is the right one when the app's own permissions should decide what each caller sees.</p>
<p>That account's Intune role is the outer limit; Elaichi's restrictions narrow access from there, never widen it. Compare the three systems that stack on top of each other:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Narrowest safe option</th>
<th>What it permits</th>
<th>What it still permits beyond "read-only"</th>
</tr>
</thead>
<tbody>
<tr>
<td>Microsoft built-in role</td>
<td>Read Only Operator</td>
<td>View devices, policies, configs</td>
<td>Retrieve a FileVault recovery key (a remote action)</td>
</tr>
<tr>
<td>Microsoft built-in role (common mistake)</td>
<td>Help Desk Operator</td>
<td>Wipe, retire, remote lock and reset passcode</td>
<td>Device actions; not read-only</td>
</tr>
<tr>
<td>Microsoft Graph permission</td>
<td><code>DeviceManagementManagedDevices.Read.All</code></td>
<td>Read device records</td>
<td>Nothing beyond reading device records</td>
</tr>
<tr>
<td>Microsoft Graph permission</td>
<td><code>.ReadWrite.All</code></td>
<td>Reads, plus delete device records, bypass Activation Lock</td>
<td>Deletion and lock bypass</td>
</tr>
<tr>
<td>Microsoft Graph permission</td>
<td><code>.PrivilegedOperations.All</code></td>
<td>Wipe, retire, remote lock, reset passcode, Lost Mode</td>
<td>All privileged device actions</td>
</tr>
<tr>
<td>Elaichi restriction</td>
<td>Allow rule naming 5 read tools</td>
<td>Exactly those 5 calls</td>
<td>Nothing, whatever Graph permissions the account holds</td>
</tr>
</tbody>
</table>
<p>Never connect as a Global Administrator, whose reach goes far beyond Intune.</p>
<p>The account you connect with is a ceiling the Elaichi allow rule sits under, never a floor it can raise. A delegated app cannot exceed the signed-in user's own permissions (<a href="https://learn.microsoft.com/en-us/graph/permissions-overview">Graph permissions overview</a>, checked October 2026). All three Graph permissions above need an administrator's consent whether the call is delegated or app-only (<a href="https://learn.microsoft.com/en-us/intune/intune-service/developer/intune-graph-apis">Intune Graph APIs</a>, checked October 2026; <a href="https://learn.microsoft.com/en-us/intune/fundamentals/role-based-access-control/ref-built-in-roles">built-in roles reference</a>, checked October 2026). Pairing Read Only Operator with the five-tool allow rule gives two independent layers that both have to agree before a write can happen.</p>
<h2 id="multi-admin-approval-as-a-second-signature-on-device-actions">Multi Admin Approval as a second signature on device actions</h2>
<p>Multi Admin Approval is Intune's own opt-in second-signature control. It applies to calls made through Graph, delegated and app-only alike, not just the Intune admin center UI. It is configured as an access policy scoped to a specific resource type. The device actions policy covers wipe, retire and delete only. It is a backstop against the three worst outcomes, not a general write gate across all 129 non-read tools (<a href="https://learn.microsoft.com/en-us/intune/fundamentals/role-based-access-control/multi-admin-approval">Multi Admin Approval</a>, checked October 2026). Separate access policies can protect scripts, apps, and compliance and configuration policies.</p>
<p>It applies to changes only, never to reads, so a help desk role doing lookups never triggers it. A protected call does not queue silently: it fails immediately and returns an approval request. The action runs only after a second administrator approves it in the Intune admin center and the original request is resubmitted with the approval code. Applications cannot approve their own requests. Changes to the access policies themselves always require a second administrator's sign-off, so one administrator cannot switch it off alone.</p>
<p>Multi Admin Approval and an Elaichi allow rule solve different problems. The allow rule stops a role from ever seeing the wipe tool. Multi Admin Approval adds a second human in the loop. It covers the rare case where a role that does have wipe access tries to use it.</p>
<h2 id="adding-the-endpoint-in-claude-and-what-consent-decides">Adding the endpoint in Claude, and what consent decides</h2>
<p>On Claude Team and Enterprise, an Owner or Primary Owner adds Elaichi once, at Organization settings, Connectors, Add, Custom, Web (<a href="https://claude.com/docs/connectors/custom/add-unlisted">Anthropic's documentation</a>, checked October 2026). The address is <code>https://api.elaichi.ai/mcp</code> for every organization. Members then connect it individually under Customize, Connectors, each with their own OAuth grant.</p>
<p>The consent screen is not where read-only access comes from. For a connected app's tools, the "Run your connected tools" checkbox enables reads and writes equally. Only a tool whose underlying method is a delete additionally requires the delete checkbox. "Create and change data" left unticked governs Elaichi's own internal operations, not Intune's write tools at all. Read-only Intune access comes from the allow rule, every time, not from any consent checkbox.</p>
<p>Claude's own per-tool permission settings don't substitute for this either (<a href="https://claude.com/docs/connectors/custom/add-unlisted">connector tool permissions</a>, checked October 2026). Elaichi's connected tools all route through a single <code>execute_tool</code> call on Claude's side. So a permission set at that layer covers every connected app at once, not Intune specifically.</p>
<h2 id="when-a-technician-needs-a-tool-the-allow-rule-leaves-out">When a technician needs a tool the allow rule leaves out</h2>
<p>Any member can file an access request with no permission of their own. Resolving a request requires <code>member:manage</code>, and an administrator cannot approve their own request. This is the designed path for the Tuesday when somebody genuinely needs a device action the allow rule withholds.</p>
<p>An admin approves the request in the console, under Governance, Access requests, and the person then has an access grant. The grant is for that one person. It lifts exactly the one tool requested out of their role rules. Every other rule on their role keeps applying, and nobody else changes. No rule is written and the role is not edited. No access request can be approved or denied from inside Claude, any other MCP client or the Elaichi Agent, so no AI surface can widen a restriction.</p>
<h2 id="what-the-audit-trail-shows-after-a-device-lookup">What the audit trail shows after a device lookup</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account actually reached, not the one a user meant to reach. So after a lookup, the entry shows which technician called <code>get_single_msintune_managed_device_by_id</code>, the Intune connection it reached and the outcome. The entry carries the one path argument that names the object, here the device, as the target id, and no other argument value.</p>
<p>Each entry also records the calling surface and the OAuth client. A call from Claude is logged as a user action with surface <code>mcp</code>, with Claude named and marked verified, because its redirect URIs prove it. The approval field reads "Allowed by the access Claude was granted". Over MCP, the standing grant is the approval, and there is no separate per-call approval step. Log writes are eventually consistent, so a given row can take a short time to appear after the call completes. The full field-by-field schema is in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="who-owns-the-intune-connection-when-that-admin-leaves">Who owns the Intune connection when that admin leaves</h2>
<p>Pick a connection owner who is staying, because the connection runs on that person's Microsoft sign-in, not an abstract service identity. Removing a member in Elaichi triggers an offboarding preflight, a check that lists every connection the departing member owns before the removal completes. The preflight lists private and shared connections alike. Only a private connection that a shared toolbox still relies on can block the removal. A shared connection is left untouched unless the admin deletes it or transfers it to a member who is staying. Use the transfer action before the person leaves. A transfer goes to one member, never to a team or the organization, and it sets a new owner on the connection. It leaves every existing grant on it exactly as it was, with no re-approval needed.</p>
<p>Transferring ownership in Elaichi does not change the credential underneath. The connection still runs on the departing person's Microsoft sign-in, and that account still has to be deprovisioned in Microsoft Entra ID. So before it is, have the staying owner connect Intune with their own narrow account and share that connection with the help desk. A SCIM deprovision suspends the member in Elaichi rather than removing them. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding when the agent holds access</a> covers the rest of the preflight.</p>
<h2 id="microsoft-ships-no-intune-mcp-server-so-what-else-is-there">Microsoft ships no Intune MCP server, so what else is there?</h2>
<p>There is no official Microsoft MCP server for an Intune tenant today. Microsoft's MCP Server for Enterprise is a read-only Microsoft Entra preview with no Intune scopes (<a href="https://learn.microsoft.com/en-us/graph/mcp-server/get-started">get-started page</a>, checked October 2026). The alternative to a vendor gateway is self-hosting: an Entra app registration plus a host somebody on your team maintains and patches. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The real cost of running your own MCP servers</a> sets out what that ongoing maintenance involves.</p>
<p>If the help desk works entirely inside the Intune admin center, nothing needs to leave it, and none of this applies. A team with no need to ask device questions from Claude, ChatGPT or Cursor does not need a gateway at all.</p>
<p>The case for doing this through a gateway like Elaichi rather than a one-off connector is narrow and specific. One endpoint serves Intune alongside the rest of the stack. One role carries the allowlist across all connected apps, rather than one config per app. One audit trail answers who ran what across every tool, not just Intune's. The full tool list for each connected app is in the <a href="/connectors/">connector catalog</a>. The <a href="/use-cases/">use cases page</a> shows the same pattern for other teams.</p>
<h2>FAQ</h2><dl><dt><strong>Does Microsoft ship an official MCP server for Intune?</strong></dt><dd>No. There is no official Microsoft MCP server for an Intune tenant. Microsoft's MCP Server for Enterprise is a read-only Microsoft Entra preview with no Intune scopes ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/mcp-server/get-started), checked October 2026). Teams reaching Intune from Claude or ChatGPT today either run a server themselves or use a governed MCP control plane such as Elaichi, whose msintune connector carries 198 tools.</dd><dt><strong>Is blocking the Intune wipe and retire tools enough to make an AI assistant read-only?</strong></dt><dd>No. Elaichi's msintune connector carries 198 tools, and only 69 of them read. Blocking wipe, retire, remote lock, reset passcode, bypass Activation Lock and delete device still leaves msintune_managed_devices_execute_action, which runs a named remote action on one or more devices, plus reboot, shut down, disable, clean Windows device, device management scripts and delete_a_msintune_user_by_id. A block rule covers only the tools it names. An allow rule naming the read tools you want is how a role is held to lookups.</dd><dt><strong>Which Microsoft account should connect Intune to an MCP client?</strong></dt><dd>The narrowest account whose Intune role covers the reads the team needs. Calls through Elaichi's msintune connector are delegated, so they reach Microsoft Graph as the connecting account, and a shared connection runs on its owner's credential. Microsoft's built-in Help Desk Operator can wipe, retire, remote lock and reset passcodes, while Read Only Operator's only remote task is getting a FileVault key ([learn.microsoft.com](https://learn.microsoft.com/en-us/intune/fundamentals/role-based-access-control/ref-built-in-roles), checked October 2026). Never connect as a Global Administrator.</dd><dt><strong>How quickly does a restriction change on an Intune role take effect?</strong></dt><dd>Within about two minutes. Role and restriction changes in Elaichi resolve through a short cache, so a new allow rule or block binds every surface shortly after you save it. Some changes are faster: revoking an OAuth grant, removing or suspending a member, revoking a share and disconnecting an account all take effect on the caller's next request.</dd><dt><strong>Does ticking "Run your connected tools" let Claude write to Intune?</strong></dt><dd>Yes. On Elaichi's consent screen, that checkbox covers a connected app's reads and writes alike, and only a tool whose method is a delete needs the separate delete permission. Leaving "Create and change data" unticked governs Elaichi's own operations, not Intune's create and update tools. Read-only access to a connected app is a restriction written in Elaichi, never a consent checkbox.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Jamf in Claude on a read-only API role</title>
      <link>https://elaichi.ai/blog/it-team-claude-jamf-devices/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/it-team-claude-jamf-devices/</guid>
      <description>Jamf in Claude lets a help desk check a Mac&apos;s inventory mid-ticket. Build a read-only Jamf API role, then narrow it per person with Elaichi restrictions.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Jamf ships no official MCP server for a Jamf Pro tenant, so Jamf in Claude runs through a connector that calls the Jamf Pro API. Elaichi's jamf connector signs in with a Jamf API client whose role holds only read privileges, and Elaichi restrictions then narrow which of its 25 tools each person reaches. Because a Jamf API token's subject is the client and not a person, ending someone's access means removing the member or revoking the share in Elaichi, which is refused on their next call.</aside>
<h2 id="why-jamf-in-claude-needs-a-connector">Why Jamf in Claude needs a connector</h2>
<p>A help desk agent has a ticket open and a serial number. The answer sits in Jamf Pro: which Mac, which person, which OS build, which apps are installed. Jamf in Claude is worth setting up so that lookup happens inside the ticket, not in a second console with a second sign-in.</p>
<p>Jamf ships no official MCP server for a live Jamf Pro tenant. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Jamf's own MCP server searches Jamf's API documentation and returns nothing about a live fleet (<a href="https://developer.jamf.com/developer-guide/docs/mcp">developer.jamf.com</a>, read October 2026). MCP Hub is a separate, Jamf Concepts open-source project, labeled Beta. <a href="https://github.com/Jamf-Concepts/mcp-hub">Its own repository</a> describes it as not an official product, meant to run locally, and shipping with write tools enabled by default (read October 2026). Neither one is a managed, multi-user path to a live tenant.</p>
<p>The shortcut an engineer reaches for is a local server with a Jamf token in a config file. That works for one person testing queries on a laptop. It leaves nobody able to say afterward what was queried, and nothing to change when that person moves teams or leaves. <a href="/blog/replace-personal-mcp-servers/">Replacing personal MCP servers</a> covers where that shape stops holding.</p>
<p>The fleet path for a team is a connector that calls the Jamf Pro API on the help desk's behalf. It runs under credentials nobody on the help desk ever sees directly. <a href="/connectors/jamf/">Elaichi's <code>jamf</code> connector</a> is a connector Elaichi authors, maintains and serves from its own infrastructure. It signs in with a Jamf API client's credentials. Those credentials sit in a separate credential service, encrypted at rest.</p>
<h2 id="build-the-jamf-api-role-before-you-connect-anything">Build the Jamf API role before you connect anything</h2>
<p>Create a dedicated API role holding only the read privileges a help desk ticket needs, then create an API client that carries that one role. The path in Jamf Pro is Settings, then System, then API Roles and Clients. An API client gets the combined privileges of every role assigned to it. So one narrow role is easier to defend in an access review than three broad ones stacked together (<a href="https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Creating_an_API_Client">learn.jamf.com</a>, read October 2026).</p>
<p>What to leave out, specifically:</p>
<table>
<thead>
<tr>
<th>Privilege</th>
<th>Why it's excluded</th>
</tr>
</thead>
<tbody>
<tr>
<td>Create Accounts</td>
<td>Creating an account through the Jamf Pro API defaults to <code>ADMINISTRATOR</code> privilege, so a role that can create accounts can create a full admin (<a href="https://developer.jamf.com/jamf-pro/reference/post_v1-accounts">developer.jamf.com</a>, read October 2026)</td>
</tr>
<tr>
<td>Send Computer Remote Wipe Command</td>
<td>Destructive, irreversible, named explicitly in Jamf's privilege reference</td>
</tr>
<tr>
<td>Send Mobile Device Remote Wipe Command</td>
<td>Same class of risk, different device type</td>
</tr>
<tr>
<td>Unmanage Mobile Devices</td>
<td>Removes Jamf's management hooks from a device</td>
</tr>
<tr>
<td>Send Computer Unmanage Command</td>
<td>Same, for computers</td>
</tr>
</tbody>
</table>
<p>All five are named in Jamf's own privilege reference (<a href="https://developer.jamf.com/jamf-pro/docs/privileges-and-deprecations">developer.jamf.com</a>, read October 2026). The role should hold read privileges for computer inventory, mobile devices, users and accounts. That is enough to answer "which Mac, whose it is, what's on it". It should hold nothing that creates, destroys, or remotely commands a device.</p>
<p>The Jamf role is the outer wall. It binds every call the client makes, including calls Elaichi never sees. If a tool somehow got past Elaichi's own restrictions, this role is what stops it from doing anything destructive at the Jamf API itself.</p>
<h2 id="what-the-jamf-connector-carries-and-what-it-leaves-out">What the jamf connector carries, and what it leaves out</h2>
<p>Elaichi's <code>jamf</code> connector exposes 25 tools total. The split, by effect on data:</p>
<table>
<thead>
<tr>
<th>Category</th>
<th>Count</th>
<th>Examples</th>
</tr>
</thead>
<tbody>
<tr>
<td>Read (GET)</td>
<td>10</td>
<td>list and get accounts, list and get users, list and get mobile devices, list and get mobile device apps, a mobile device search, the computer inventory list</td>
</tr>
<tr>
<td>Create</td>
<td>5</td>
<td><code>create_a_jamf_account</code>, create a user, create a mobile device, create a mobile device app, create a computer inventory record</td>
</tr>
<tr>
<td>Update</td>
<td>5</td>
<td>update an account, update a user, update a mobile device, update a mobile device app, update a computer inventory record</td>
</tr>
<tr>
<td>Delete</td>
<td>5</td>
<td>delete an account, delete a user, delete a mobile device, delete a mobile device app, delete a computer inventory record</td>
</tr>
</tbody>
</table>
<p>No tool in the connector sends a wipe command, a device lock, or an unmanage command. Those commands are not in the connector at all, so the model cannot reach for one however the request is phrased. Its riskiest tools delete records and create accounts; none of them wipes a Mac.</p>
<p>This shapes how you plan the two layers. If the Jamf API role holds no write privileges, a write tool in Elaichi fails at Jamf's wall. The failure lands in the audit trail as an error. That is correct, but noisy, and a tool the model can run is a tool it may try. The cleaner shape is to restrict the write and delete tools in Elaichi as well. The model then cannot run them at all. Search names them only as restricted, with no schema.</p>
<h2 id="one-api-client-many-people-how-restrictions-narrow-it">One API client, many people: how restrictions narrow it</h2>
<p>A Jamf API client authenticates with client credentials, and each token's subject is the client, not a person. Everyone calling through that one connection gets the same reach into Jamf. Jamf Pro has no concept of "this call came from help desk agent X vs. agent Y" once it is behind one API client. Narrowing per person happens in Elaichi, through restrictions: rules naming <a href="/blog/per-tool-vs-per-app-restrictions/">which connectors and which individual tools</a> a role or a user may reach.</p>
<p>The setup for a team: an IT admin connects the Jamf API client once, then shares that connection at <code>use</code> with the help desk team. A shared connection runs on its owner's credential, so every agent's call reaches Jamf as that same API client. Then write a restriction against the help desk role. Custom roles are a Gold-tier feature, and one person holds exactly one role at a time. So the help desk role functions as a complete persona rather than an add-on permission.</p>
<p>There are two ways to write the rule, and one of them has a trap:</p>
<ul>
<li><strong>Block rule</strong> names the connector's write and delete tools specifically (<code>create_a_jamf_account</code> first among them). It leaves the role's other connectors and tools untouched. Safe default for "hold one app to reads."</li>
<li><strong>Allow rule</strong>: once a role holds even one allow rule, that rule becomes the role's <em>entire</em> allowlist across <em>every</em> connector it uses. An allow rule naming only Jamf's read tools will silently deny Zendesk, Slack, and everything else the role was supposed to reach.</li>
</ul>
<p>Use blocks when you are restricting one app within an otherwise-open role. Use allow rules only when you are deliberately writing the role's complete approved-apps list. In that case name every connector it needs, not just the one you are thinking about right now. A block matches the tool name or its pinned operation. An allow matches the pinned operation only. The mechanics are in <a href="/blog/block-matches-name-allow-matches-operation/">why blocks match tool names but allows do not</a>.</p>
<p>A restriction change takes effect within about two minutes. The change applies on every surface, MCP, console and REST alike, and a restricted tool is withheld from the tool list. Search names it, flagged restricted, with no schema, and it cannot be called.</p>
<h2 id="add-the-one-endpoint-in-claude-and-let-agents-sign-in">Add the one endpoint in Claude and let agents sign in</h2>
<p>Claude points at one address for the whole organization: <code>POST https://api.elaichi.ai/mcp</code>. On Claude Team and Enterprise, an Owner or Primary Owner adds it once under Organization settings, Connectors, Add, Custom, Web. Each member then connects it individually under Customize, Connectors (<a href="https://support.claude.com/en/articles/11175166">support.claude.com</a>, checked October 2026). There are no per-user URLs and no tokens to paste in. Each agent still signs in once with their own OAuth grant, the browser handshake that ties their Elaichi identity to that Claude client.</p>
<p>On Elaichi's consent screen, the agent ticks the scopes the client asked for. Two things worth telling them up front: "Run your connected tools" is the scope that reaches Jamf at all. Leaving "Create and change data" unticked does <em>not</em> make Jamf read-only. That checkbox governs Elaichi's own operations, such as editing a saved connection, not a connected app's tools. Read-only Jamf is a function of the restriction on the help desk role, not of this checkbox.</p>
<p>In Elaichi, connected tools are never listed one by one, however few there are. The agent asks about a serial number, the model calls <code>search_tools</code>, then runs the match with <code>execute_tool</code>. Claude's per-connector tool permissions, Always allow, Needs approval and Blocked, land on <code>execute_tool</code> as a single gate. One setting there covers every connected tool at once, with no per-tool granularity on Claude's side (<a href="https://claude.com/docs/connectors/custom/add-unlisted">claude.com</a>, checked October 2026). Per-tool decisions for Jamf belong in Elaichi's restrictions, not in Claude's connector settings. The client-side walkthrough is in <a href="/blog/connect-elaichi-to-claude/">connecting Elaichi to Claude</a>.</p>
<h2 id="ending-access-while-the-jamf-token-is-still-valid">Ending access while the Jamf token is still valid</h2>
<p>Disabling or deleting a Jamf API client does not revoke tokens that are already issued and still valid (<a href="https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Creating_an_API_Client">learn.jamf.com</a>, read October 2026). Token lifetime is configured per client. A long lifetime leaves a real window after you think you have cut access off. A token minted an hour before you disable the client can keep working until it expires on its own schedule.</p>
<p>This is a direct argument for keeping the credential in Elaichi rather than on a laptop. The departing agent never held the Jamf token in the first place. Cutting them off means removing the member, suspending them, or revoking the share on the connection, none of which require touching Jamf Pro itself. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A SCIM deprovision suspends the member and revokes every live grant in one action. Removing the member outright is a separate, deliberate step an admin takes in Elaichi afterward.</p>
<p>One thing to plan in advance: a shared connection runs on its owner's credential. If the admin who originally connected Jamf leaves the org, transfer ownership during offboarding to someone who is staying. Otherwise the whole team's Jamf access is tied to a departing person's state. The offboarding preflight lists every connection that member owns, specifically so this does not get missed. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding when the agent holds access</a> covers the rest of that checklist.</p>
<h2 id="what-the-audit-trail-shows-after-a-ticket-closes">What the audit trail shows after a ticket closes</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the operation and tool, the connection actually reached, and the classification. It also names whether it was approved, the outcome, and an error code if one occurred. The entry carries the one path argument that names the object as the target id, and no other argument value. A device ID in the path is recorded. The body of an update is not.</p>
<p>The entry also records the surface and the OAuth client. A call from Claude shows surface <code>mcp</code> with Claude named and marked verified, because its redirect URIs prove it. The actor kind recorded is <code>user</code>, not <code>ai_assistant</code>: that second marker is reserved for calls made through the in-app Elaichi Agent, a different surface. Approval reads as "Allowed by the access Claude was granted," because over MCP the OAuth grant itself is the approval event, not a separate click. The trail is append-only and eventually consistent, so a row may take a short delay to appear after the call completes. A compliance reviewer can read all of this on a free Auditor seat. That seat lacks the <code>tool:execute</code> permission and therefore cannot call anything itself. Read access to the log does not imply write access to the fleet. For what to check in these records during a review, see <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="when-jamfs-own-ai-assistant-is-the-better-answer">When Jamf's own AI Assistant is the better answer</h2>
<p>If your admins are happy working inside the Jamf console, use Jamf's built-in AI Assistant instead and stop here. It is a better fit for that specific job. It has been generally available since 31 March 2026, and it is read-only. It makes GET calls as the signed-in user, so it inherits that person's existing Jamf permissions with no second credential anywhere (<a href="https://learn.jamf.com/r/en-US/jamf-account-documentation/AI_Assistant">learn.jamf.com</a>, read October 2026). For a Jamf admin answering a Jamf-only question inside Jamf Pro, that is less machinery than anything described in this post.</p>
<p>The case for a connector is the ticket, not the device record in isolation. The agent is in Claude with the customer's message, the Zendesk history, and the device state in one place. They are not a Jamf admin with console access of their own. If one engineer only wants to test queries on their own laptop, a local server is still a better fit than an organization-wide control plane. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you do not need an MCP gateway yet</a> draws that line explicitly. Once several people need the same reach, and somebody has to be able to prove afterward what was looked up and by whom, <a href="/blog/what-is-an-mcp-control-plane/">an MCP control plane</a> is what you are actually buying. The connector is just the part you interact with. Browse the rest of the catalog at <a href="/connectors/">/connectors/</a>, or see how other teams set this up at <a href="/use-cases/">/use-cases/</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does Jamf have an official MCP server for a Jamf Pro tenant?</strong></dt><dd>No. Jamf's MCP server at [developer.jamf.com/mcp](https://developer.jamf.com/developer-guide/docs/mcp) searches Jamf's API documentation and returns nothing about a live fleet (read October 2026). MCP Hub is a Jamf Concepts open-source project, labeled Beta, described on [its own repository](https://github.com/Jamf-Concepts/mcp-hub) as not an official product, run locally, and carrying write tools. Reaching a Jamf Pro tenant from an AI client therefore means a connector that calls the Jamf Pro API, such as Elaichi's jamf connector.</dd><dt><strong>Can a Jamf API client be limited to read-only access?</strong></dt><dd>Yes. In Jamf Pro, an API role holds privileges and an API client gets the combined privileges of its roles, set under Settings, System, API Roles and Clients ([learn.jamf.com](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Creating_an_API_Client), read October 2026). A role built from read privileges only gives the client read-only reach. Leave account creation out of it: creating an account through the Jamf Pro API defaults to ADMINISTRATOR privilege ([developer.jamf.com](https://developer.jamf.com/jamf-pro/reference/post_v1-accounts), read October 2026), so a role that can create accounts can create a full admin.</dd><dt><strong>Does disabling a Jamf API client cut off an AI client straight away?</strong></dt><dd>No. Jamf's documentation states that disabling or deleting an API client does not revoke tokens that are still valid ([learn.jamf.com](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Creating_an_API_Client), read October 2026), and token lifetime is set per client. When the connection lives in Elaichi, access ends by removing the member, suspending them, or revoking the share on the connection. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Which Jamf tools does Elaichi's jamf connector carry?</strong></dt><dd>Elaichi's jamf connector carries 25 tools: reads, plus create, update and delete for accounts, users, mobile devices, mobile device apps and computer inventory, including create_a_jamf_account. It has no tool that sends a wipe, lock or unmanage command. Which of the 25 a given person reaches is set by restrictions on their role in Elaichi, and a restricted tool is withheld from the tool list and cannot be called.</dd><dt><strong>How does a shared Jamf connection stay limited per person?</strong></dt><dd>A Jamf API client's token has the client as its subject, not a person, so every caller through one connection has the same baseline reach into Jamf. A restriction targeted at a role narrows which connectors and tools that role may reach. The change takes effect within about two minutes. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Microsoft Copilot with Salesforce: two paths</title>
      <link>https://elaichi.ai/blog/microsoft-copilot-salesforce-jira/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/microsoft-copilot-salesforce-jira/</guid>
      <description>Microsoft Copilot with Salesforce indexes your CRM for search. Live reads and writes from Claude, ChatGPT or Cursor take a different path.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Microsoft Copilot with Salesforce and Jira is a search and grounding setup: synced Copilot connectors index both apps into Microsoft Graph, and Microsoft's live federated connector list does not include either app today. Taking action in Salesforce or Jira from Claude, ChatGPT or Cursor is a separate path, which Elaichi serves through one organization-wide MCP endpoint. Each person connects their own Salesforce and Jira account, restrictions are written per role or per user down to a single tool, and every call lands in one audit trail.</aside>
<h2 id="what-microsoft-copilot-with-salesforce-gives-you-today">What Microsoft Copilot with Salesforce gives you today</h2>
<p>Your company runs on Microsoft 365. Sales works in Salesforce, engineering works in Jira, and somebody has asked whether Copilot can cover both. The short answer: Microsoft Copilot with Salesforce and Jira is built for search and grounding over an indexed copy of your data. It is not built for taking live action inside either app. A separate path, using MCP (Model Context Protocol) clients like Claude, ChatGPT or Cursor, covers the live-action case. This post lays out both, with a comparison table and the specific permission and audit behavior each one gives you.</p>
<p>Every Microsoft claim below links the Microsoft Learn page it came from, checked October 2026, and anything marked preview or planned had not shipped then.</p>
<h3 id="the-four-paths-at-a-glance">The four paths at a glance</h3>
<table>
<thead>
<tr>
<th>Path</th>
<th>What it does</th>
<th>Freshness</th>
<th>Writes to Salesforce or Jira</th>
<th>Where the control sits</th>
</tr>
</thead>
<tbody>
<tr>
<td>Synced Copilot connectors</td>
<td>Index Salesforce CRM and Jira Cloud into Microsoft Graph for search and grounding</td>
<td>Permission changes sync only on full crawls</td>
<td>No</td>
<td>Default mode honors source permissions; admins choose which fields are indexed</td>
</tr>
<tr>
<td>Federated (MCP) connectors</td>
<td>Fetch live as the signed-in user</td>
<td>Live</td>
<td>No: Salesforce and Jira are not on the list today</td>
<td>Published by Microsoft or approved partners</td>
</tr>
<tr>
<td>Copilot Studio agents</td>
<td>Call the Premium Salesforce and Jira connectors, and MCP servers</td>
<td>Live</td>
<td>Yes</td>
<td>Power Platform data policies and advanced connector policies, per connector or whole MCP server</td>
</tr>
<tr>
<td>Elaichi</td>
<td>Serves Claude, ChatGPT and Cursor through one MCP endpoint, each call as the person</td>
<td>Live</td>
<td>Yes</td>
<td>Restrictions per role or user, down to one tool, and one audit trail</td>
</tr>
</tbody>
</table>
<p>The column that matters most is writes: only Copilot Studio and Elaichi write to Salesforce or Jira today.</p>
<p>Microsoft renamed Microsoft 365 Copilot to Microsoft Copilot in August 2026, and Graph connectors are now Copilot connectors. Synced Copilot connectors index Salesforce CRM and Jira Cloud into Microsoft Graph, and Copilot answers from that index (<a href="https://learn.microsoft.com/en-us/microsoft-365/copilot/connectors/salesforce-crm-overview">learn.microsoft.com</a>, checked October 2026).</p>
<p>Federated connectors are Microsoft's live-read path. They fetch as the signed-in user at query time, and they are published by Microsoft or approved partners. Salesforce and Jira are not on that list today (<a href="https://learn.microsoft.com/en-us/microsoft-365/copilot/connectors/federated-connectors-overview">learn.microsoft.com</a>, checked October 2026).</p>
<p>The practical line falls here. "Find the renewal notes on the Acme account" is what the indexed path is for. "Create the renewal opportunity and link the Jira epic" is not. No Copilot connector, synced or federated, writes to either app today.</p>
<h2 id="why-permission-sync-is-not-the-same-as-live-permissions">Why permission sync is not the same as live permissions</h2>
<p>Synced Copilot connectors do honor the source app's permissions. The point to hold onto is that Microsoft Graph holds a copy, and a copy has a refresh schedule. It is not a window onto Salesforce or Jira, it is a snapshot of one.</p>
<p>Microsoft's own page for the Salesforce CRM connector states three specific behaviors. The default mode honors Salesforce record ownership, sharing rules and role hierarchy. Field-level security is not enforced if an admin opts in to index restricted fields. And permission changes sync only on full crawls, not incrementally (<a href="https://learn.microsoft.com/en-us/microsoft-365/copilot/connectors/salesforce-crm-overview">learn.microsoft.com</a>, checked October 2026).</p>
<p>For an IT admin, that becomes two decisions, each made once and reviewed rarely: which fields get indexed, and how often a full crawl runs. A sharing change made in Salesforce on Monday reaches Copilot search only when the next full crawl runs. Check the connector's full-crawl schedule rather than assuming one.</p>
<p>A live call has no such lag, because it has no copy to go stale. Federated connectors and MCP-based tools evaluate permissions at the moment of the call, every time, against the source system directly. That gap is scheduled refresh versus per-call evaluation. It is the reason to pick one path for search and a different one for action, rather than forcing a single connector to do both.</p>
<h2 id="where-do-copilot-studio-and-agent-365-fit">Where do Copilot Studio and Agent 365 fit?</h2>
<p>Copilot Studio is Microsoft's action path, and its governance is written per environment and per connector rather than per tool. Copilot Studio agents can call the Premium Salesforce and Jira connectors. Copilot Studio agents can also add MCP servers as tools (<a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-mcp">learn.microsoft.com</a>, checked October 2026). Each tool runs on end-user credentials by default, with maker-provided credentials as an option an admin can forbid per environment (<a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/add-tools-custom-agent">learn.microsoft.com</a>, checked October 2026).</p>
<p>Governance rides on Power Platform, through two separate mechanisms that don't talk to each other:</p>
<ul>
<li><strong>Data loss prevention (DLP) policies</strong> sort connectors into Business, Non-business and Blocked. Changes usually apply within an hour, and Microsoft's documented upper bound is 24 hours (<a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-data-loss-prevention">learn.microsoft.com</a>, checked October 2026).</li>
<li><strong>Advanced connector policies</strong> are a default-deny allowlist per environment or group. They can block a whole MCP server, but Microsoft states explicitly that per-tool MCP control is not available at this layer (<a href="https://learn.microsoft.com/en-us/power-platform/admin/advanced-connector-policies">learn.microsoft.com</a>, checked October 2026).</li>
</ul>
<p>The practical effect: one MCP server may expose both a read tool and a delete tool. The policy layer allows or blocks the server as one unit. A maker can switch off single tools inside one agent. That is a build choice per agent, not an admin policy (<a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/mcp-add-existing-server-to-agent">learn.microsoft.com</a>, checked October 2026).</p>
<p>Agent 365 has been generally available since 1 May 2026. It is priced at $15 per user per month, or bundled into Microsoft 365 E7 (<a href="https://www.microsoft.com/en-us/microsoft-agent-365">microsoft.com</a>, checked October 2026). Its tooling gateway for registered MCP servers is in preview. Admins can approve or block servers at runtime today. Microsoft has stated tool-level blocking for those servers is planned but not shipped (<a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/manage-byo-mcp-server">learn.microsoft.com</a>, checked October 2026). The <a href="/blog/copilot-studio-vs-mcp-gateway/">side-by-side of Copilot Studio and an MCP gateway</a> goes through that surface in more detail.</p>
<h2 id="how-claude-chatgpt-and-cursor-reach-salesforce-and-jira-live">How Claude, ChatGPT and Cursor reach Salesforce and Jira live</h2>
<p>The second path puts the live call directly in the AI client people already have open. The call does not go through an indexed copy or a separately governed Power Platform environment. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>Elaichi serves one organization-wide MCP endpoint, <code>POST https://api.elaichi.ai/mcp</code>, behind OAuth (the sign-in standard that hands an app limited access without a shared password). There are no per-user URLs and no embedded tokens to manage or rotate. An admin <a href="/blog/connect-company-apps-to-claude-and-chatgpt/">adds the one address to each client</a> where the client allows it. Each member then connects and signs in with their own grant. Clients register themselves through dynamic client registration, so there is no client ID or secret to distribute by hand.</p>
<p><a href="/connectors/salesforce/">Salesforce</a> and <a href="/connectors/jira/">Jira</a> are both connectors Elaichi wrote, in its catalog of 600+ connectors. Elaichi authors and serves them, rather than proxying them through a third-party integration platform. A rep connects their own Salesforce account; an engineer connects their own Jira account. Every read and every write then reaches the app as that person, evaluated live by Salesforce or Jira's own permission system. There is no index in between to go stale. A connection shared with a team runs on its owner's credential. Share one only where every person using it should be able to act as that single account.</p>
<p>Tool discovery works differently from a plain, flat server list, which matters once you connect more than one app to the same client. In Elaichi, connected tools are never listed one by one, however few there are. The model finds what it needs and calls it. That keeps a two-app rollout from filling the context window with every available tool on the first message. When a tool somebody expected is missing, <a href="/blog/mcp-tools-not-showing/">the checks run in a fixed order</a>.</p>
<p>One trade-off to state plainly, because it affects what "read-only" means in practice. On Elaichi's consent screen, the single permission "Run your connected tools" covers a connected app's reads and writes alike. Only a tool whose method is a delete also needs the "Delete data and remove access" box, which is never pre-ticked. There is no checkbox for "read-only" at connection time. Read-only access to Salesforce or Jira is something you write as a restriction afterward. It is not something a user selects when they first connect.</p>
<h2 id="writing-restrictions-for-two-apps-at-once">Writing restrictions for two apps at once</h2>
<p>Restrictions decide which connectors and which individual tools a target may reach. A target is a role or a single user. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</p>
<p>The trap with two apps is the allow rule. An allow rule is the target's entire allowlist, across every connector the target can see, not only the app it names. Write an allow rule to hold Jira to its read tools, and the role loses Salesforce entirely. The fix is a second allow rule naming Salesforce too. Allow rules on the same target union together, so one allow rule per app is the correct pattern once you know this. Holding a single app to reads while leaving every other connector untouched is done differently. Use blocks on that one app's write tools, not an allow rule at all. The <a href="/blog/per-tool-vs-per-app-restrictions/">per-tool against per-app decision</a> covers the six cases where each shape is the right one.</p>
<p>Two more behaviors to know before you write anything:</p>
<ul>
<li>Blocks always beat allows within each layer. A block is never silently overridden by a broader allow.</li>
<li>In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</li>
</ul>
<p>Timing matters when you defend the setup to security or an auditor. A restriction change takes effect within about two minutes. Removal is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="what-the-audit-trail-records-for-both-apps">What the audit trail records for both apps</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). That holds across Salesforce and Jira alike. The recorded connection is the account actually reached, taken from the execution rather than the intent. That answers "which Jira site did it write to" without reconstructing it from context.</p>
<p>Each entry carries the operation and tool name, plus the surface and the OAuth client the call came through. It also carries whether it was approved, the outcome, and an error code. It carries the one path argument that names the object as the target id, and no other argument value. A call made from Claude or Cursor is recorded as a user action, attributed to the person who made it, not to "the assistant."</p>
<p>One more distinction: the error text returned to the caller is derived from the third party's response, Salesforce's or Jira's own error message. The error written to the audit trail is not the same string. Audit records are org-visible and may fan out to a customer's own logging destination. So what is written there is an error code, never derived from Salesforce's or Jira's response.</p>
<p>On plans: the audit trail is on Elaichi's Gold plan. Forwarding it to your own Datadog comes with the Black plan, launching soon.</p>
<h2 id="when-the-microsoft-path-is-the-right-answer">When the Microsoft path is the right answer</h2>
<p>Say your people work in Teams, Outlook and Word, and what they want is to find things. Then the synced Copilot connectors are the complete and correct setup. The index honors source permissions in its default mode, you control which fields are indexed, and there is no second vendor in the call path. Adding anything else buys you nothing for a pure-search use case.</p>
<p>The Microsoft path is also right when the action you want is a Copilot Studio agent running inside Power Platform. Those agents are built and governed by the admins who already run environments and DLP policies. That fits especially well if the write operations you need are already exposed as Premium connectors.</p>
<p>The second path earns its place when three things are true at once. People are working in Claude, ChatGPT or Cursor rather than only in Microsoft surfaces. They need live reads and writes in Salesforce and Jira, as themselves, not through a shared service account. And you want the permission decision written once, per role, down to a single tool. One audit trail then covers both apps, instead of two separate connector logs.</p>
<p>Elaichi has two plans, Gold and Black. Gold is $15 per user per month as the USD list price; <a href="/pricing/">pricing</a> shows the local figure. 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. <em>Disclosure: Elaichi, the MCP control plane described as the second path above, publishes this blog. The comparison table and Microsoft-side claims are sourced independently from Microsoft's own documentation, linked throughout.</em></p>
<p>For the wider shape of this category, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For the team-level walkthroughs behind this post, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">giving each rep their own Salesforce access in ChatGPT</a>. There is also <a href="/blog/engineering-team-cursor-jira/">rolling Cursor out to an engineering team on Jira</a>. The full <a href="/connectors/">connector catalog</a> lists what else is reachable from the same address.</p>
<h2>FAQ</h2><dl><dt><strong>Can Microsoft Copilot take actions in Salesforce and Jira?</strong></dt><dd>Not through synced Copilot connectors. Those index Salesforce CRM and Jira Cloud into Microsoft Graph for search and grounding rather than for actions, and Microsoft's live federated connector list does not include Salesforce or Jira today ([learn.microsoft.com](https://learn.microsoft.com/en-us/microsoft-365/copilot/connectors/federated-connectors-overview), checked October 2026). Copilot Studio agents can call the Premium Salesforce and Jira connectors, which is Microsoft's action path and is governed through Power Platform data policies and advanced connector policies.</dd><dt><strong>Do Microsoft Copilot's Salesforce results respect Salesforce permissions?</strong></dt><dd>In the default mode, yes: Microsoft's own page says the Salesforce CRM connector honors record ownership, sharing rules and role hierarchy ([learn.microsoft.com](https://learn.microsoft.com/en-us/microsoft-365/copilot/connectors/salesforce-crm-overview), checked October 2026). Two limits appear on the same page. Field-level security is not enforced if an admin opts in to index restricted fields, and permission changes sync only on full crawls, so a sharing change is reflected when the next full crawl runs.</dd><dt><strong>Do Power Platform policies control individual MCP tools?</strong></dt><dd>No. Advanced connector policies are a default-deny allowlist per environment or group, and Microsoft states that per-tool MCP control is not available there, so a whole MCP server is allowed or blocked as one unit ([learn.microsoft.com](https://learn.microsoft.com/en-us/power-platform/admin/advanced-connector-policies), checked October 2026). Agent 365's tooling gateway for registered MCP servers is in preview, with tool-level blocking planned.</dd><dt><strong>How do you make Jira read-only for a role in Elaichi?</strong></dt><dd>With a restriction, not a consent checkbox. The simplest version is block rules on Jira's write tools for that role, which leaves the role's other apps untouched. An allow rule also works but behaves as the role's whole allowlist across every connector, so the role then needs an allow rule for each other app it uses. The change takes effect within about two minutes.</dd><dt><strong>Which AI clients connect to Elaichi's MCP endpoint?</strong></dt><dd>Claude, ChatGPT, Cursor and any other MCP client. They all point at the same address, POST https://api.elaichi.ai/mcp, and each person signs in over OAuth with their own grant, picking scopes on Elaichi's consent screen. Microsoft's Copilot surfaces are governed by Microsoft's own controls, such as Power Platform policies and the Microsoft 365 admin center.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>n8n AI agents per-user permissions and audit</title>
      <link>https://elaichi.ai/blog/n8n-ai-agents-per-user-permissions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/n8n-ai-agents-per-user-permissions/</guid>
      <description>n8n AI agents per-user permissions come down to whose credential a run holds: what n8n documents, and what Elaichi&apos;s MCP endpoint requires.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In n8n, a Fixed credential runs every execution as one account, and n8n's per-user end-user credentials are Enterprise, in Preview, OAuth only, and exclude the Schedule Trigger. Elaichi is a governed MCP control plane whose endpoint hands a client one member's OAuth grant, so every run acts as that member, under that member's role restrictions, with the member and the client named in the audit trail. n8n is not on the list of clients Elaichi names as connecting, so check sign-in in a throwaway workflow before you build on it.</aside>
<h2 id="what-n8n-ai-agents-per-user-permissions-actually-mean">What n8n AI agents per-user permissions actually mean</h2>
<p>n8n AI agents per-user permissions come down to one question. Whose credential does the run hold? n8n's default is a Fixed credential. It is the same account for every execution, manual or scheduled. An agent reaching Salesforce, Jira and Zendesk reaches them as whoever connected those accounts. That holds no matter who started the run. n8n documents this directly. It warns that a Fixed credential can expose one person's access to everyone (<a href="https://docs.n8n.io/administer/manage-credentials/end-user-credentials">docs.n8n.io</a>, checked October 2026).</p>
<p>Elaichi comes at the same question from the other side. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Every company account is connected once, and the tools those accounts expose are served through one organization-wide MCP endpoint at <code>POST https://api.elaichi.ai/mcp</code>. A client signs in there over OAuth and holds a grant, which is the permission one named person gave one named client. That grant carries the person's role, and their restrictions apply on every call. A restriction is a rule naming which connectors and which individual tools a role or a user may reach.</p>
<p>n8n is not on the list of clients Elaichi names as connecting. Nothing here says it connects.</p>
<h2 id="fixed-credentials-versus-end-user-credentials-in-n8n">Fixed credentials versus end-user credentials in n8n</h2>
<p>n8n has a per-user credential model, and its documented limits decide whether it helps you here. A Fixed credential, the default, resolves to one account for everyone. End-user credentials resolve per user. But n8n currently lists them as Enterprise, in Preview, not for production, OAuth only, and team projects only (<a href="https://docs.n8n.io/administer/manage-credentials/end-user-credentials">docs.n8n.io</a>, checked October 2026).</p>
<p>The supported triggers matter more than the tier:</p>
<table>
<thead>
<tr>
<th>Trigger</th>
<th>Resolves credential per user?</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Manual trigger</td>
<td>Yes</td>
<td>Supported</td>
</tr>
<tr>
<td>Chat Hub</td>
<td>Yes</td>
<td>Supported</td>
</tr>
<tr>
<td>MCP Server Trigger</td>
<td>Yes</td>
<td>Supported</td>
</tr>
<tr>
<td>Form trigger</td>
<td>Yes</td>
<td>With n8n User Auth</td>
</tr>
<tr>
<td>Chat trigger</td>
<td>Yes</td>
<td>Hosted Chat, with n8n User Auth</td>
</tr>
<tr>
<td>Schedule Trigger</td>
<td>No</td>
<td>Runs as whatever account the workflow's credential resolves to; no per-run identity</td>
</tr>
</tbody>
</table>
<p>The Schedule Trigger runs a published workflow on intervals or cron. It is not on n8n's list of triggers compatible with end-user credentials. So a scheduled agent cannot use n8n's native per-user identity today, as of n8n's current docs. Whether an MCP OAuth2 credential can itself be configured as an end-user credential is not documented either way. Treat that as an open question to ask n8n, not an assumption to design around.</p>
<p>Credential sharing sits underneath all of this. Sharing is available on every n8n Cloud plan and on self-hosted Business and Enterprise, and recipients can use a shared credential without seeing its contents. That's convenient, and it's the shared-account problem in another shape: everyone using a shared credential inherits one identity.</p>
<h2 id="does-n8n-meet-elaichis-endpoint-requirements">Does n8n meet Elaichi's endpoint requirements?</h2>
<p>On paper the two lists line up. Verify it in a throwaway workflow before you build on it. Matching documentation is not the same as a working handshake. When the handshake fails, <a href="/blog/mcp-oauth-errors/">the OAuth error itself names what to fix</a>.</p>
<p>The endpoint requires MCP over Streamable HTTP with JSON-RPC 2.0, stateless, behind OAuth. Clients register themselves through dynamic client registration (<a href="https://datatracker.ietf.org/doc/html/rfc7591">RFC 7591</a>), so there's no client ID or secret to paste in manually. PKCE with <code>S256</code> is required. It proves the software finishing sign-in is the software that started it. A missing <code>code_challenge_method</code> is not assumed to be <code>S256</code>, and <code>plain</code> is refused outright. A <code>resource</code> value, if the client sends one, must be <code>https://api.elaichi.ai</code>, or the token request fails with <code>invalid_target</code>. Scopes are limited to <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code>, <code>mcp:tools</code>, <code>openid</code> and <code>email</code>.</p>
<p>n8n's MCP Client Tool documents Server Transport as HTTP Streamable (the default) or deprecated SSE. It documents authentication as Bearer Auth, Header Auth, MCP OAuth2, Multiple Headers Auth or None. Its MCP OAuth2 credential uses dynamic client registration by default and takes an optional Resource URL. It negotiates PKCE with S256 where the server supports it (<a href="https://docs.n8n.io/integrations/builtin/credentials/mcp/">docs.n8n.io</a>, checked October 2026).</p>
<p>Two behaviors to check at first sign-in:</p>
<ol>
<li><strong>Scope narrowing is possible, widening isn't.</strong> A client that requests no scope at all gets read-only access. Connected third-party tools additionally require <code>mcp:tools</code> (the "Run your connected tools" checkbox). Without <code>mcp:destructive</code>, any connected tool whose underlying method is a delete is left out of the search index. A call to one by name is still refused, with a message naming the missing scope. Consent can only narrow what a client requested.</li>
<li><strong>Rate limiting.</strong> The endpoint allows 120 MCP requests per minute per token and returns HTTP 429 with <code>Retry-After: 60</code> above that. A wide fan-out loop will hit this, for example an agent calling <code>search_tools</code> per item in a batch. Batch or cache tool discovery instead of repeating it per item.</li>
</ol>
<h2 id="whose-identity-does-a-scheduled-run-act-as">Whose identity does a scheduled run act as?</h2>
<p>Through Elaichi, a scheduled run acts as the member whose grant the credential holds. There is no anonymous service identity on the endpoint. The grant is read fresh on every call. So the run gets that member's current reach and nothing wider than it, at the moment the call happens.</p>
<p>Three consequences follow. First, that member's role restrictions apply to the run exactly as if they'd made the call themselves. A role or restriction change reaches the run within about two minutes. Second, each tool call that reaches execution gets an audit entry, run or failed. It names the member, the surface <code>mcp</code>, the OAuth client it came through, the tool, and the connection actually reached. Third, a call from an MCP client is recorded with <code>actor_kind</code> of <code>user</code>, not as an AI actor. Elaichi's AI marker covers only its in-product Agent, not third-party MCP clients calling in.</p>
<p>The client name on an audit entry is marked verified only where its redirect URIs prove it. This currently covers Claude, ChatGPT and Cursor. Any other client shows the name it registered with, marked unverified. Read that as a label for a human reviewer, not as a security control that blocks anything.</p>
<p>Name the trade-off before you ship it. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A SCIM deprovision suspends rather than deletes, with the same effect on grants. A nightly workflow signed in with a departed employee's grant stops running that night, mid-pipeline if it's mid-run. Sometimes that's exactly the behavior you want; sometimes it's an unplanned outage. Decide which, deliberately, before it happens. See <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding AI access</a>.</p>
<p>Plan for token lifetimes too. An access token lasts an hour, and a refresh token lasts 30 days and rotates on every use. A workflow idle for more than 30 days needs its credential reconnected. Reusing an old refresh token revokes the whole grant, so test what happens when two executions refresh the same credential at once.</p>
<h2 id="why-tools-to-include-cannot-pick-one-connected-app">Why Tools to Include cannot pick one connected app</h2>
<p>It cannot, because <a href="/blog/mcp-tools-not-showing/">connected tools are never advertised one by one</a>. Elaichi lists its own <code>elaichi__</code> operations individually, plus two generic tools: <code>search_tools</code> and <code>execute_tool</code>. Connected third-party tools (Jira, Zendesk, Salesforce, etc.) are <em>found</em> with <code>search_tools</code> and <em>run</em> with <code>execute_tool</code>, regardless of how many connected tools exist behind them.</p>
<p>n8n's Tools to Include option offers All, Selected or All Except over the tools a server advertises. Against this endpoint, that means picking or excluding <code>execute_tool</code> as a single unit, never Jira's create-issue tool as distinct from Zendesk's. The same ceiling applies to n8n's human-in-the-loop approval for tools. It gates <code>execute_tool</code> as a whole, not the specific operation behind it. <code>execute_tool</code> is also annotated destructive and open-world by design, because its real risk tier isn't knowable before the call resolves. So a client configured to prompt on anything not marked read-only will prompt on every connected call, reads included.</p>
<p>Per-app and per-tool control lives in Elaichi's restriction layer instead, scoped to a role or a user. Blocks beat allows. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. One caution on allow rules. An allow rule is the target's entire allowlist across every connector. So a role restricted to one app's read tools also needs explicit allow rules naming every other app it uses. Otherwise those calls fail silently from the agent's perspective. <a href="/blog/per-tool-vs-per-app-restrictions/">Restricting one tool or a whole app</a> walks through the six cases this produces.</p>
<h2 id="what-n8ns-own-logs-record-and-what-they-miss">What n8n's own logs record, and what they miss</h2>
<p>n8n's audit events leave the instance only through Log Streaming, which is Enterprise-tier. Two gaps matter specifically for a scheduled agent. Workflow execution events carry no <code>userId</code> when a Schedule Trigger starts the run. There's no human to attribute it to in n8n's own data model. And n8n's MCP-specific audit events cover its instance-level MCP server, not the MCP Server Trigger used inside workflows (<a href="https://docs.n8n.io/administer/observe-and-log/stream-logs-to-external-systems">docs.n8n.io</a>, checked October 2026). If a scheduled agent deletes a record, n8n's log alone will not name the human accountable for it. It names only the workflow and the service account it ran under.</p>
<p>Elaichi's audit trail is a different unit of record: per call rather than per workflow execution. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The text written to the trail is never derived from the third party's response. So a malformed or hostile error body from, say, Jira cannot inject content into the log pipe. The trail is org-visible, newest-first, and filterable by actor, category, action kind and time. A free read-only Auditor seat lets a compliance reviewer read it without a paid license. It's eventually consistent, so a row may take a moment to appear after the call completes. Forwarding it to your own Datadog comes with the Black plan, launching soon. For what a record needs to contain to actually survive a compliance review, see <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<h2 id="who-should-sign-the-workflow-credential-in">Who should sign the workflow credential in</h2>
<p>The person who owns the workflow, using their own grant, under their own role, not a shared admin account. That keeps one accountable name on every run. It also caps the blast radius at one job's worth of access, rather than an administrator's entire reach. Every member holds exactly one role, so a workflow inherits its owner's whole role. If that is wider than the job, have the credential signed in by someone whose role fits the job. <a href="/blog/designing-roles-for-ai-agents/">One role each</a> covers why a role should be a complete, narrow persona rather than a reused one. Use n8n's end-user credentials only where n8n's documented triggers actually support them. As of this writing, that excludes the Schedule Trigger.</p>
<p>There's a case where none of this is worth doing. Say a workflow touches exactly one app, and n8n already has a native node for it. If a single service account on that one app is an acceptable risk for your org, a control plane buys you an audit trail and restrictions you don't yet need. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway</a> is the honest version of that decision. Read it before adding infrastructure you won't use.</p>
<p>If you do need per-user control across multiple apps, the shape is simple. One endpoint, one grant per person, no shared bot identity, one role per job. The same endpoint is what people point <a href="/blog/connect-company-apps-to-claude-and-chatgpt/">Claude and ChatGPT at</a>. Elaichi serves the 600+ connectors in its <a href="/connectors/">connector catalog</a> directly, most of them its own and the rest vendors' MCP servers it governs. So restrictions are defined once at the gateway, rather than re-implemented per downstream server or per workflow tool.</p>
<h2>FAQ</h2><dl><dt><strong>Does n8n connect to Elaichi's MCP endpoint?</strong></dt><dd>n8n is not on the list of clients Elaichi names as connecting, so check sign-in yourself before relying on it. On paper the requirements match: Elaichi needs MCP over Streamable HTTP with OAuth, dynamic client registration and PKCE S256, and n8n's MCP Client Tool documents HTTP Streamable transport and an MCP OAuth2 credential that uses dynamic client registration and picks PKCE S256 where the server supports it ([docs.n8n.io](https://docs.n8n.io/integrations/builtin/credentials/mcp/), checked October 2026). Build a throwaway workflow with a manual trigger and complete sign-in once before anything else.</dd><dt><strong>Can an n8n scheduled workflow run as the person who triggered it?</strong></dt><dd>No. n8n's end-user credentials, which resolve per user, are Enterprise, in Preview, OAuth only and team projects only, and the Schedule Trigger is not among their supported triggers ([docs.n8n.io](https://docs.n8n.io/administer/manage-credentials/end-user-credentials), checked October 2026). Through Elaichi, a workflow's OAuth credential holds one member's grant, so every run, scheduled ones included, acts as that member, under that member's role and restrictions.</dd><dt><strong>What does Elaichi record when an MCP client calls a tool?</strong></dt><dd>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). It names the member, the surface the call came through, the OAuth client, the tool, the connection actually reached, whether the call was approved, the outcome and an error code. It carries the one path argument that names the object as the target id, and no other argument value. The client's name is marked verified only where its redirect URIs prove it, which covers Claude, ChatGPT and Cursor.</dd><dt><strong>Can I make one connected app read-only for an AI agent?</strong></dt><dd>Yes, with a restriction in Elaichi, not with an OAuth consent checkbox. For a connected app's tools, the "Run your connected tools" scope covers reads and writes alike, and only a tool whose method is a delete needs the destructive scope on top. Read-only access is written as an allow rule naming that app's read tools, or as blocks on its write tools. An allow rule becomes the target's whole allowlist across every connector, so the role needs allow rules for its other apps too.</dd><dt><strong>What happens to a workflow when the credential owner leaves?</strong></dt><dd>It stops on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant's revoked state is re-read from the organization store on every call with no cache. A nightly workflow signed in with that person's grant fails the next time it runs. Pick an owner who is staying, or plan the handover before the leave date.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>OpenAI Agents SDK governed access to company apps</title>
      <link>https://elaichi.ai/blog/openai-agents-sdk-governed-access/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/openai-agents-sdk-governed-access/</guid>
      <description>What OpenAI Agents SDK governed access to Salesforce and Slack requires: a person&apos;s browser OAuth grant, token rotation, and restrictions written server-side.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> The OpenAI Agents SDK documents four ways to attach an MCP server, but runs no OAuth flow in Python, so a program needs a person's browser-obtained grant and a refresher. Elaichi serves Salesforce, Slack and the rest of its catalog through one OAuth-protected MCP endpoint, where per-tool control is a restriction on that person's role rather than an SDK filter. Elaichi does not name the Agents SDK among the clients that connect, so treat this as requirements set beside OpenAI's options, and test it yourself.</aside>
<h2 id="which-agents-sdk-class-fits-a-remote-mcp-endpoint">Which Agents SDK class fits a remote MCP endpoint?</h2>
<p>A remote server behind OAuth fits <code>MCPServerStreamableHttp</code> or <code>HostedMCPTool</code>. Stdio is for a server running as a local child process, which a hosted endpoint is not.</p>
<p>The situation: you have an agent written with the OpenAI Agents SDK, it needs to read opportunities in Salesforce and post a digest to Slack, and it has to act as a named person with a record of what it did. OpenAI Agents SDK governed access comes down to three decisions. Which transport class, who holds the OAuth grant, and where the per-tool rules live.</p>
<p>The OpenAI Agents SDK documents four MCP shapes:</p>
<table>
<thead>
<tr>
<th>Class</th>
<th>Transport</th>
<th>Who calls the server</th>
<th>Use when</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>MCPServerStdio</code></td>
<td>Local process, stdio</td>
<td>Your process</td>
<td>The server runs as a local child process</td>
</tr>
<tr>
<td><code>MCPServerSse</code> (deprecated)</td>
<td>HTTP + Server-Sent Events</td>
<td>Your process</td>
<td>Legacy servers only; do not use for new work</td>
</tr>
<tr>
<td><code>MCPServerStreamableHttp</code></td>
<td>HTTP, streamable</td>
<td>Your process</td>
<td>Remote server, your code holds the token and makes the calls</td>
</tr>
<tr>
<td><code>HostedMCPTool</code> / Responses API <code>mcp</code> tool</td>
<td>HTTP, streamable</td>
<td>OpenAI's infrastructure</td>
<td>Remote server, OpenAI's backend makes the calls on the model's behalf</td>
</tr>
</tbody>
</table>
<p>Source: the Agents SDK MCP guide (<a href="https://openai.github.io/openai-agents-python/mcp/">openai.github.io</a>, checked October 2026). MCP is the Model Context Protocol, the wire format an AI client uses to find and call tools on a server (<a href="https://modelcontextprotocol.io/">the specification</a>).</p>
<p>Elaichi is a remote server. It serves standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth, at one organization-wide address: <code>POST https://api.elaichi.ai/mcp</code>. There are no per-toolbox URLs and no embedded tokens. With <code>MCPServerStreamableHttp</code> your own process makes the calls. With <code>HostedMCPTool</code>, or the Responses API <code>mcp</code> tool, OpenAI's infrastructure calls the server instead.</p>
<p><em>Disclosure: Elaichi publishes this blog.</em></p>
<p>One caveat before any code. Elaichi names Claude, ChatGPT, Cursor and any other MCP client as the clients that connect. Neither the Agents SDK nor the Responses API <code>mcp</code> tool is named there specifically. What follows sets Elaichi's documented requirements beside OpenAI's documented options. Prove the pairing in a throwaway organization first.</p>
<p>Copy the address exactly. <code>POST https://api.elaichi.ai/mcp</code> answers 401 with the <code>resource_metadata</code> challenge that starts sign-in. With a trailing slash it answers 404, and on <code>app.elaichi.ai/mcp</code> it answers 405 (probed October 2026). Neither carries the challenge, so neither starts sign-in.</p>
<h2 id="openai-agents-sdk-governed-access-starts-with-one-persons-grant">OpenAI Agents SDK governed access starts with one person's grant</h2>
<p>Your program holds a real person's OAuth grant, not a service key. OAuth is the sign-in handshake that issues a scoped token, and the grant is the standing permission a person approved for one named client.</p>
<p>Elaichi takes OAuth only. A client registers itself through dynamic client registration (<a href="https://datatracker.ietf.org/doc/html/rfc7591">RFC 7591</a>) at <code>/oauth/register</code>, with PKCE <code>S256</code> required, then sends the person to Elaichi's consent screen in a browser. There is no client ID, secret or header to paste.</p>
<p>The Python SDK will not run that flow. The Python Agents SDK takes a token through <code>headers</code> or an <code>httpx.Auth</code> handler in <code>params["auth"]</code>. The JS SDK accepts an <code>authProvider</code>, the MCP TypeScript SDK's <code>OAuthClientProvider</code> (<a href="https://openai.github.io/openai-agents-js/guides/mcp/">openai.github.io</a>, checked October 2026). The Responses API <code>mcp</code> tool takes an <code>authorization</code> value that OpenAI says it never stores and sends on every request (<a href="https://developers.openai.com/api/docs/guides/tools-connectors-mcp">developers.openai.com</a>, checked October 2026). The Python SDK and the Responses API tool assume you already have a token; the JS SDK's <code>authProvider</code> can run the browser leg through the MCP TypeScript SDK.</p>
<p>So you build one component: a browser sign-in that captures the grant, plus storage and a refresher. Minimal shape in Python:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#D7B46A">from</span><span style="color:#E6E1D8"> agents</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">mcp </span><span style="color:#D7B46A">import</span><span style="color:#E6E1D8"> MCPServerStreamableHttp</span></span>
<span class="line"><span style="color:#D7B46A">import</span><span style="color:#E6E1D8"> httpx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#D7B46A">class</span><span style="color:#D7B46A"> ElaichiAuth</span><span style="color:#928D84">(</span><span style="color:#E6E1D8">httpx</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">Auth</span><span style="color:#928D84">):</span></span>
<span class="line"><span style="color:#928D84">    """</span><span style="color:#7BC496">Wraps a token store that owns refresh, rotation, and the single-writer lock.</span><span style="color:#928D84">"""</span></span>
<span class="line"><span style="color:#D7B46A">    def</span><span style="color:#D7B46A"> __init__</span><span style="color:#928D84">(</span><span style="color:#E6E1D8">self</span><span style="color:#928D84">,</span><span style="color:#E6E1D8"> token_store</span><span style="color:#928D84">):</span></span>
<span class="line"><span style="color:#E6E1D8">        self</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">token_store </span><span style="color:#D7B46A">=</span><span style="color:#E6E1D8"> token_store</span></span>
<span class="line"></span>
<span class="line"><span style="color:#D7B46A">    def</span><span style="color:#D7B46A"> auth_flow</span><span style="color:#928D84">(</span><span style="color:#E6E1D8">self</span><span style="color:#928D84">,</span><span style="color:#E6E1D8"> request</span><span style="color:#928D84">):</span></span>
<span class="line"><span style="color:#E6E1D8">        token </span><span style="color:#D7B46A">=</span><span style="color:#E6E1D8"> self</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">token_store</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">get_access_token</span><span style="color:#928D84">()</span><span style="color:#928D84">  # refreshes if &#x3C; ~60s to expiry</span></span>
<span class="line"><span style="color:#E6E1D8">        request</span><span style="color:#928D84">.</span><span style="color:#E6E1D8">headers</span><span style="color:#928D84">[</span><span style="color:#928D84">"</span><span style="color:#7BC496">Authorization</span><span style="color:#928D84">"</span><span style="color:#928D84">]</span><span style="color:#D7B46A"> =</span><span style="color:#D7B46A"> f</span><span style="color:#7BC496">"Bearer </span><span style="color:#E6E1D8">{token}</span><span style="color:#7BC496">"</span></span>
<span class="line"><span style="color:#D7B46A">        yield</span><span style="color:#E6E1D8"> request</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E6E1D8">server </span><span style="color:#D7B46A">=</span><span style="color:#E6E1D8"> MCPServerStreamableHttp</span><span style="color:#928D84">(</span></span>
<span class="line"><span style="color:#E6E1D8">    params</span><span style="color:#D7B46A">=</span><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">        "</span><span style="color:#7BC496">url</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span><span style="color:#928D84">,</span></span>
<span class="line"><span style="color:#928D84">        "</span><span style="color:#7BC496">auth</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#E6E1D8"> ElaichiAuth</span><span style="color:#928D84">(</span><span style="color:#E6E1D8">token_store</span><span style="color:#928D84">),</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">)</span></span></code></pre>
<p>The snippet leaves out the browser consent leg, which runs once per person at onboarding, not on every agent invocation. The <code>token_store</code> is the part worth building carefully. The lifetimes and locking rule below explain why.</p>
<p>Four lifetimes shape the token store. The consent request lasts 30 minutes and works once. An access token lasts 1 hour. A refresh token lasts 30 days and rotates on every use: each refresh call returns a new refresh token and invalidates the old one. Reusing an old refresh token or an authorization code revokes the whole grant, so serialize refreshes through a single writer (a DB advisory lock or a single refresher process). This matters concretely in multi-process deployments: if two workers both see a token expiring and both call refresh concurrently, the second call's refresh token is already dead by the time it lands, and the whole grant goes with it. One writer, one in-flight refresh at a time, is not optional. The grant itself has no expiry, but 30 idle days means somebody signs in again.</p>
<p>Four details trip OAuth libraries here:</p>
<ul>
<li>Scopes come only from <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code>, <code>mcp:tools</code>, <code>openid</code> and <code>email</code>. A library that adds <code>offline_access</code> gets <code>invalid_scope</code>.</li>
<li>A <code>resource</code> parameter, if sent, must be on <code>https://api.elaichi.ai</code>, or <code>invalid_target</code>.</li>
<li>The <code>redirect_uri</code> must match registration exactly. A loopback address may change port only, never host, so <code>127.0.0.1</code> never matches <code>localhost</code>.</li>
<li>Rate limits are 30 OAuth requests a minute and 120 MCP requests a minute per token, answered with 429 and <code>Retry-After: 60</code>.</li>
</ul>
<p>Sign-in needs a browser. A program running headless in CI cannot complete it. That is a stop, not a configuration problem.</p>
<p>A revoked or expired grant answers 401 <code>invalid_token</code> on the next request, and a refresh answers <code>invalid_grant</code>. Both are fixed by sending the person back through sign-in. The two credential shapes are compared in <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth or API keys for AI agents</a>.</p>
<p>If your organization runs both patterns at once, one team wiring <code>MCPServerStreamableHttp</code> directly and another going through <code>HostedMCPTool</code> via the Responses API, both see the same <code>tools/list</code> output for the same grant, because the tool list is a property of the grant's role and scopes, not of which SDK class is calling. There's no split-brain case here: change the role, both callers see it change within about two minutes.</p>
<h2 id="why-per-tool-control-over-salesforce-and-slack-is-written-in-elaichi">Why per-tool control over Salesforce and Slack is written in Elaichi</h2>
<p>Client-side filters cannot tell one Salesforce tool from another. Connected tools are never listed in <code>tools/list</code>, however few there are. Elaichi's list carries its own <code>elaichi__</code> operations plus two meta-tools: the model finds a connected tool with <code>search_tools</code> and runs it with <code>execute_tool</code>.</p>
<p>That bounds what the SDK's controls can do. <code>tool_filter=create_static_tool_filter(...)</code>, the Responses API's <code>allowed_tools</code> and <code>require_approval</code> all act on advertised names. Against Elaichi they can allow or gate <code>execute_tool</code> as a whole. Allow it and every connected tool the grant reaches is callable. Block it and the agent reaches no connected app at all. <code>execute_tool</code> is annotated destructive and open-world on purpose, because its real tier is not knowable before the call.</p>
<p>Client-side approval is also inconsistent across OpenAI's own surfaces. The JS <code>hostedMcpTool</code> defaults <code>requireApproval</code> to <code>'never'</code> (<a href="https://openai.github.io/openai-agents-js/guides/mcp/">openai.github.io</a>, checked October 2026), while the Responses API <code>mcp</code> tool requires approval by default (<a href="https://developers.openai.com/api/docs/guides/tools-connectors-mcp">developers.openai.com</a>, checked October 2026). A control whose default flips between surfaces is a poor home for a Salesforce write policy.</p>
<p>Write the policy in Elaichi, as a restriction on the role the agent's person holds. A restriction is a rule about which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>For the Salesforce and Slack pair, two shapes do most of the work:</p>
<ul>
<li>Blocks on one app's write tools hold that app to reads and leave the person's other apps untouched.</li>
<li>An allow rule is stricter and wider. It becomes the role's entire allowlist across every connector, so a role allowed a handful of Salesforce read tools also needs allow rules naming its other apps, Slack included, or it loses them.</li>
</ul>
<p>A digest-posting agent usually wants the first shape twice. Block the Salesforce write tools so the agent reads opportunities and changes nothing, and block Slack's destructive tools so it posts without deleting. A restricted tool is withheld from <code>tools/list</code> and cannot be called. Search names it only as restricted, with no schema. A role or restriction change takes effect within about two minutes, which matters while you are testing. Which shape fits which case is worked through in <a href="/blog/per-tool-vs-per-app-restrictions/">restricting one tool or a whole app</a>.</p>
<p>One scope note surprises people. For a connected app's tools, <code>mcp:tools</code> runs reads and writes alike, and only a tool whose method is a delete costs <code>mcp:destructive</code>. Leaving "Create and change data" unticked on the consent screen does not make Slack read-only. Read-only access to a connected app is a restriction, never a consent checkbox.</p>
<p>Every call acts as the member whose grant the program holds. The audit entry records the surface as <code>mcp</code>, names the OAuth client, and names the connection actually reached, so "which Slack workspace did it post to" has an answer. A client that registers itself shows the name it registered with, marked unverified; only clients whose redirect URIs prove them, Claude, ChatGPT and Cursor among them, are marked verified. The entry carries the one path argument that names the object as the target id, and no other argument value. Offboarding follows the same model. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="what-sdk-tracing-records-and-openais-warning-about-aggregators">What SDK tracing records, and OpenAI's warning about aggregators</h2>
<p>Agents SDK tracing is on by default and includes tool inputs and outputs. It goes to OpenAI's Traces dashboard, covers MCP tool listing and calls, and is governed by <code>trace_include_sensitive_data</code> (<a href="https://openai.github.io/openai-agents-python/tracing/">openai.github.io</a>, checked October 2026). If Salesforce field values should not land in a third party's dashboard, decide that before the first run and reroute with <code>add_trace_processor()</code> or <code>set_trace_processors()</code>.</p>
<p>OpenAI also says it does not verify remote MCP servers, that a malicious one can exfiltrate what is in the model's context, and that "aggregators" deserve extra due diligence (<a href="https://developers.openai.com/api/docs/guides/tools-connectors-mcp">developers.openai.com</a>, checked October 2026). That warning points at Elaichi too, and deserves a direct answer rather than a reassurance.</p>
<p>What holds on Elaichi's endpoint: Elaichi authors, maintains and serves most of its connectors from its own infrastructure, and governs vendors' own MCP servers for the rest. Connector credentials sit in a separate credential service, encrypted at rest with AES-256-GCM. Role checks apply per operation, a tool classified <code>forbidden</code> is reachable under no scope, results are scrubbed for secret-shaped values as a backstop, OAuth scopes bound the grant, and every call that reaches execution is logged. The detail is on the <a href="/security/">security page</a>.</p>
<p>What does not hold: the prompt-injection write gate in the Elaichi Agent does not apply to <code>POST /mcp</code>, and cannot, because an MCP server never sees a user prompt. Do not count the endpoint as prompt-injection protection. The rest of that surface is in <a href="/blog/mcp-security-risks/">MCP security risks and how to reduce them</a>.</p>
<h2 id="when-the-apps-own-mcp-server-is-the-better-answer">When the app's own MCP server is the better answer</h2>
<p>One agent, one app, one vendor: use the vendor's own server. Salesforce hosted MCP servers are generally available for Enterprise Edition orgs and above, where "every transaction runs as the authenticated user" (<a href="https://developer.salesforce.com/blogs/2026/04/salesforce-hosted-mcp-servers-are-now-generally-available">developer.salesforce.com</a>, checked October 2026). Slack hosts one at <code>https://mcp.slack.com/mcp</code>, where workspace admins approve MCP clients and each client must be backed by a registered Slack app (<a href="https://docs.slack.dev/ai/slack-mcp-server/">docs.slack.dev</a>, checked October 2026). Both run under the app's own permission model and add no second vendor. If your agent only ever touches one app, this is the simpler, lower-trust-surface choice, and we'd say so even though we sell the alternative.</p>
<p>The case for a single endpoint like Elaichi's starts when the agent spans several apps and more are coming. One address, one grant per person, restrictions written once against a role, and one audit trail across every app. That consolidation is the actual trade: fewer integration points per agent, at the cost of adding Elaichi itself as a party that touches every credential. Removing someone from Elaichi ends their access through Elaichi and nothing more; their Salesforce and Slack accounts are still deprovisioned separately, where they live. Elaichi does not replace app-level offboarding, it adds a second place that also needs to be checked.</p>
<p>If what you actually need is a budget cap per model or a rate limit on inference, that is a different layer, and a proxy in front of the model is the right shape. Elaichi governs tool execution, not token spend. The 600+ connectors behind the endpoint are listed in the <a href="/connectors/">connector catalog</a>, including <a href="/connectors/salesforce/">Salesforce</a> and <a href="/connectors/slack/">Slack</a>.</p>
<h2 id="a-first-run-you-can-check-in-an-afternoon">A first run you can check in an afternoon</h2>
<p>Start in a throwaway organization, with a member whose role you are willing to break. Sign in once through a browser, store the grant, point <code>MCPServerStreamableHttp</code> at <code>https://api.elaichi.ai/mcp</code>, and call <code>tools/list</code>.</p>
<p>Seeing <code>search_tools</code> and <code>execute_tool</code> means the grant reaches connected tools. Seeing only <code>elaichi__</code> operations means the grant lacks <code>mcp:tools</code> or no connected tool is reachable yet, for example a connection still pending or needing reauthorization. Reconnecting with "Run your connected tools" ticked fixes the first case. An empty list usually means the role lacks <code>tool:execute</code>, which no amount of re-authorizing grants. The rest of the ladder is in <a href="/blog/mcp-tools-not-showing/">why MCP tools do not show up</a>.</p>
<p>Then prove the governance leg. Block a Salesforce write tool on that role, give the change about two minutes, and search for the tool. It should now show only as restricted, with no schema. Then run an allowed read and open the audit trail. The entry should name the member, the OAuth client and the connection reached. That record is the evidence a reviewer asks for later.</p>
<p>For the wider shape, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. For the same problem from the human end, where a rep uses their own Salesforce access inside a chat client, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">each rep's own Salesforce access in ChatGPT</a>. Team rollouts sit on <a href="/use-cases/">use cases</a>, and Gold's USD list price is on <a href="/pricing/">pricing</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does the OpenAI Agents SDK connect to Elaichi's MCP endpoint?</strong></dt><dd>Elaichi names Claude, ChatGPT, Cursor and any other MCP client as the clients that connect, and the OpenAI Agents SDK is not named specifically. Elaichi's endpoint is standard MCP over Streamable HTTP at POST https://api.elaichi.ai/mcp, behind OAuth with dynamic client registration and PKCE S256, so the SDK's MCPServerStreamableHttp class is the shape that matches. Test the pairing in a throwaway organization before building on it.</dd><dt><strong>How does a Python Agents SDK program get an Elaichi access token?</strong></dt><dd>The Python OpenAI Agents SDK runs no OAuth flow of its own; you pass a token through headers or an httpx.Auth handler in params["auth"]. Elaichi issues tokens only through OAuth with dynamic client registration, PKCE S256 and a person signing in from a browser, so the program needs a component that captures that person's grant and refreshes it. A headless CI job with no browser access cannot complete the sign-in.</dd><dt><strong>Can require_approval or allowed_tools limit which Salesforce tools an agent calls through Elaichi?</strong></dt><dd>No. Elaichi never lists connected tools in tools/list; the model finds them with search_tools and runs them with execute_tool. Client-side filters such as tool_filter, allowed_tools and require_approval can only pick or gate execute_tool as a whole, which covers every connected app at once. Per-tool control over Salesforce or Slack is a restriction written in Elaichi against the person's role or the person, and it takes effect within about two minutes.</dd><dt><strong>How long do Elaichi's OAuth tokens last for a long-running agent?</strong></dt><dd>An access token lasts 1 hour. A refresh token lasts 30 days and rotates on every use, and reusing an old refresh token or an authorization code revokes the whole grant. The grant itself has no expiry, so a single serialized refresher keeps a long-running program signed in. After 30 idle days, the person signs in again.</dd><dt><strong>Does Agents SDK tracing record what an agent read from Salesforce?</strong></dt><dd>Yes, by default. OpenAI's Agents SDK tracing is on by default, sends traces to OpenAI's Traces dashboard, covers MCP tool listing and calls, and includes tool inputs and outputs unless trace_include_sensitive_data is turned off ([openai.github.io](https://openai.github.io/openai-agents-python/tracing/), checked October 2026). Traces can be rerouted with add_trace_processor() or set_trace_processors().</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>How to restrict ChatGPT Enterprise connectors</title>
      <link>https://elaichi.ai/blog/restrict-chatgpt-enterprise-connectors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/restrict-chatgpt-enterprise-connectors/</guid>
      <description>You can restrict ChatGPT Enterprise connectors per app, and per group on Enterprise and Edu. Here is exactly where that grain stops.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> ChatGPT Enterprise admins can switch each app on or off for the workspace, give different groups different apps through custom roles, and turn an app's read and write actions on separately. Those switches work one app at a time, so they cannot tell one connected app or tool apart behind a governed MCP endpoint. With Elaichi, the per-app and per-tool rules are written once as role restrictions, and the same rules then hold in Claude and Cursor as well as ChatGPT.</aside>
<h2 id="can-admins-restrict-chatgpt-enterprise-connectors">Can admins restrict ChatGPT Enterprise connectors?</h2>
<p>Yes. Somebody in finance asks for Salesforce inside ChatGPT, and you want the boundary set before the first query runs.</p>
<p>Scope note before the detail: the OpenAI sections below are sourced to a specific help.openai.com article and a check date. Re-check a menu path on the live page before you write a runbook. The sections after "Where ChatGPT's per-action switches stop" describe Elaichi, a third-party MCP control plane, and how it extends those controls below the per-app level.</p>
<p>You can restrict ChatGPT Enterprise connectors app by app, and on Enterprise and Edu group by group. As of this check, apps are managed at Admin Console, then the workspace, then Plugins. The older page is Workspace settings, then Apps. It is also reached from Plugins through Manage Legacy Apps (help.openai.com, <a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">admin controls for plugins and apps</a>, checked October 2026).</p>
<p>Plan matters more than anything else here:</p>
<table>
<thead>
<tr>
<th>Plan</th>
<th>Workspace-wide app toggle</th>
<th>Per-group app assignment</th>
<th>Action-level controls</th>
</tr>
</thead>
<tbody>
<tr>
<td>Free / Plus / Pro</td>
<td>No admin console</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Team / Business</td>
<td>Yes, workspace-wide only</td>
<td>No</td>
<td>Yes, since 20 April 2026</td>
</tr>
<tr>
<td>Enterprise / Edu</td>
<td>Yes</td>
<td>Yes, via custom roles</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>The workspace-wide switch is the one control that exists on every paid team plan. Business workspaces start with apps on. New Enterprise and Edu workspaces start with a selected default set on. If you're auditing an existing workspace, don't assume the default. Read the current state directly.</p>
<h2 id="giving-different-groups-different-apps">Giving different groups different apps</h2>
<p>Per-group app assignment is Enterprise and Edu only; it does not exist on Business at any price point. The path is Permissions &#x26; roles, then Custom roles, then <strong>Plugins &#x26; connected data</strong>, then <strong>Select</strong>. Roles are assigned to manual groups or groups synced via SCIM.</p>
<p>SCIM (<a href="https://www.rfc-editor.org/rfc/rfc7644">RFC 7644</a>) is the standard that syncs users and groups from your identity provider (Okta, Entra ID, etc.) into ChatGPT. So group membership in ChatGPT tracks group membership in your IdP, instead of being maintained by hand.</p>
<p>Two resolution rules matter in practice:</p>
<ul>
<li><strong>Roles are additive.</strong> If any role a person holds grants a permission, they have it. There is no "most restrictive role wins": a second role can only add access, never subtract it.</li>
<li><strong>Propagation is not instant.</strong> Changes take up to 5 minutes to apply (help.openai.com, <a href="https://help.openai.com/en/articles/11750701-managing-feature-access-with-role-based-access-control-in-chatgpt">role-based access control in ChatGPT</a>, checked October 2026). If you're testing a permission change, wait before concluding it failed.</li>
</ul>
<p>On Business there is no group grain at all. Switching an app on switches it on for every member of the workspace. If your plan is Business and finance needs an app that support should not reach, that split cannot be built in the ChatGPT admin console. It has to live in an identity layer or a separate tool below the app.</p>
<h2 id="read-actions-write-actions-and-when-chatgpt-asks-first">Read actions, write actions and when ChatGPT asks first</h2>
<p>Separate controls govern what an app may do and when the person is asked to approve it. Keep them distinct when you configure a workspace.</p>
<table>
<thead>
<tr>
<th>Control</th>
<th>Location</th>
<th>Options</th>
<th>Governs</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Actions</strong></td>
<td>Per app</td>
<td>Read actions on/off, write actions on/off, set independently</td>
<td>Whether the app's read and write capabilities exist at all</td>
</tr>
<tr>
<td><strong>New actions</strong></td>
<td>Per app</td>
<td>Enable all new actions / Only enable new read actions / Disable new actions</td>
<td>What happens automatically when the connector ships a new capability</td>
</tr>
<tr>
<td><strong>Plugin permissions</strong></td>
<td>Workspace-wide or per app</td>
<td>Always ask / Allow read actions / Allow low-risk actions / Allow all actions (per-app only)</td>
<td>Whether the end user sees an approval prompt before a given call runs</td>
</tr>
</tbody>
</table>
<p>Business has had the <strong>Actions</strong> control since a release dated 20 April 2026 (help.openai.com, <a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">admin controls for plugins and apps</a>, checked October 2026).</p>
<p>On <strong>Plugin permissions</strong>: members of a managed workspace never get a lasting "Always allow". No current OpenAI page documents what the default setting is for a newly enabled app. Check your own workspace rather than assuming "Always ask" or any other state (help.openai.com, <a href="https://help.openai.com/en/articles/20001495-managing-app-permissions-in-chatgpt">managing app permissions</a>, checked October 2026).</p>
<p>These controls only police what ChatGPT asks about. The destination system's own <a href="https://oauth.net/2/">OAuth 2.0</a> scopes are a separate, independent check. OAuth is the browser sign-in flow that issues a scoped, revocable token instead of handing over a password. Salesforce's or Jira's own scope grants still apply underneath whatever ChatGPT allows.</p>
<h2 id="who-may-publish-a-custom-mcp-app">Who may publish a custom MCP app</h2>
<p>Only Admins and Owners can publish a custom app, on every plan tier that supports custom apps at all.</p>
<p><a href="https://modelcontextprotocol.io">MCP</a> (Model Context Protocol) is the open standard an AI client uses to discover a server's tools and call them. On Business, only admins and owners can use developer mode. On Enterprise and Edu, role-based access control can let regular members build and test drafts. The publish step, which sets the app's enabled actions and, on Enterprise and Edu, which groups receive it, stays with Admins and Owners.</p>
<p>Two behaviors worth planning around:</p>
<ul>
<li><strong>Snapshots, not live sync.</strong> A published app runs on a frozen snapshot of its tool list. If the connector adds a tool later, it arrives disabled by default until an admin manually refreshes the app.</li>
<li><strong>No verification, no escalation path.</strong> OpenAI does not review or verify custom MCP apps before publish. There is no documented member-to-admin request flow for "I need this app published" (help.openai.com, <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">developer mode and MCP apps</a>, checked October 2026). Whatever approval process you want has to be built outside ChatGPT. It lives in Slack, a ticketing system, or <a href="/blog/human-approval-for-ai-agent-actions/">the approval step in front of the tool call itself</a>.</li>
</ul>
<h2 id="where-chatgpts-per-action-switches-stop">Where ChatGPT's per-action switches stop</h2>
<p>This is the architectural limit that the controls above cannot see past. It applies to a server that exposes a search tool and an execute tool instead of listing every connected tool, as Elaichi does.</p>
<p>To ChatGPT, Elaichi is one custom app whose listed tools are <code>search_tools</code>, <code>execute_tool</code> and Elaichi's own operations. The actual connected tools, a Salesforce record update or a Jira issue create, are never listed in <code>tools/list</code>, no matter how few of them exist. The model finds a connected tool at runtime by calling <code>search_tools</code>, then invokes it by calling <code>execute_tool</code> with the tool's identifier as an argument.</p>
<p>Consequence: ChatGPT's per-app Actions toggle (read/write) and its Plugin permissions prompt can only act on <code>execute_tool</code> as a single undifferentiated unit. They cannot distinguish a Salesforce read from a Jira write, because both are the same tool call from ChatGPT's point of view. Only the arguments differ, and ChatGPT's admin console does not inspect arguments. Elaichi annotates <code>execute_tool</code> as destructive and open-world precisely because its real risk tier can't be known until the call resolves.</p>
<p>The practical implication: setting the aggregator app to "read actions only" in ChatGPT does <strong>not</strong> make the connectors behind it read-only. That setting acts on <code>execute_tool</code>, which runs every connected tool, reads included, so it cannot single out the writes behind it. If you need read/write or connector-level granularity, it has to be enforced inside the aggregator, before the call leaves it. That is what the rest of this post describes.</p>
<h2 id="writing-per-app-and-per-tool-rules-in-elaichi">Writing per-app and per-tool rules in Elaichi</h2>
<p>From here on, this describes Elaichi specifically, not an OpenAI feature.</p>
<p>Elaichi enforces per-app and per-tool rules as <strong>restrictions</strong>, written server-side, independent of ChatGPT's own permission model. A restriction names which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Resolution logic:</p>
<ol>
<li><strong>A member is governed by two layers at once.</strong> One is their role's rules. The other is any rule aimed at them personally. A tool is reachable only when both layers admit it, so a personal rule can only narrow what the role allows. It never replaces or loosens a role rule.</li>
<li><strong>Within each layer, allow rules union and block rules union.</strong></li>
<li><strong>Blocks always beat allows</strong>, regardless of which rule was written more recently or more specifically.</li>
<li><strong>An allow rule naming nothing denies everything.</strong> In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is an easy rule to write by accident when a restriction is left half-filled.</li>
<li><strong>An allow rule naming a connector as a whole grants every tool on that connector</strong>, even if specific tool entries are also listed. The tool entries in that case add nothing beyond what the connector-level grant already covers.</li>
</ol>
<p>Matching detail that affects correctness: blocks match on the tool's <em>name</em> or on the operation pinned against the catalog. Allows match the pinned operation only. The reason is that a tool's advertised display name can be edited by whoever maintains the connector's documentation. Matching allows against a name would let a documentation edit silently widen access. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. A restriction change takes effect within about two minutes.</p>
<p>Elaichi serves 600+ connectors, most of them authored on its own infrastructure, on one organization-wide endpoint, <code>https://api.elaichi.ai/mcp</code>. Because the restriction is enforced at that endpoint rather than inside any one client, a restriction written once for a role applies identically. That is true whether the member is using Claude, ChatGPT, Cursor or any other MCP client. Each client sees the same filtered tool list and the same enforcement, because the filtering happens before the response reaches the client.</p>
<p>Each member holds exactly one role, which is why <a href="/blog/designing-roles-for-ai-agents/">roles are built as complete personas</a> rather than stacked fragments. The walkthrough of <a href="/blog/per-tool-vs-per-app-restrictions/">when to block a tool and when to block the app</a> covers how to choose the grain for a given rule.</p>
<p><strong>Failure mode to plan for:</strong> because enforcement happens at <code>api.elaichi.ai</code>, that endpoint is a dependency for every connector call from every client. If it's unreachable, calls fail closed: ChatGPT's <code>execute_tool</code> call returns an error rather than falling back to a direct, unfiltered connection to Salesforce or Jira. This also means every connector call takes one additional network hop versus a native, unmediated connector. Whether that overhead matters depends on your latency budget. It is worth measuring against your own traffic rather than taking on faith.</p>
<h2 id="where-each-layers-record-lives">Where each layer's record lives</h2>
<p>The two layers, ChatGPT's own logs and Elaichi's audit log, keep separate records, and neither is a superset of the other.</p>
<p>ChatGPT's Compliance Logs Platform is Enterprise and Edu only (Business has no equivalent). <code>APP_LOG</code> events carry the user's id and email, the app identifier (<code>app_type</code> includes <code>MCP</code> for custom apps), the conversation id, and the request/response payload. Relevant admin events include <code>APP_SET_ENABLED_ACTIONS</code>, <code>ROLE_SET_PLUGIN_PERMISSIONS</code>, and <code>PLUGIN_USE_BLOCKED</code>. Files are retained 30 days. No field documents the specific tool name that was called inside an aggregator app (OpenAI, <a href="https://chatgpt.com/public/admin/api-reference">compliance API reference</a>, checked October 2026). That is precisely the gap that makes the per-action limit concrete: ChatGPT's own logs cannot tell you which connector or tool ran inside <code>execute_tool</code>.</p>
<p>Elaichi's audit log is the append-only record of <a href="/blog/what-an-ai-audit-log-must-capture/">what a tool-call entry has to capture</a> at the tool level. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The entry holds the one path argument that names the object, as the target id, and no other argument: no argument names, no count, and no other values. Each entry records the client surface and the OAuth client the call arrived through. Claude, ChatGPT, and Cursor are distinguishable from each other by their registered redirect URIs. Each entry also states how the call was approved, which over MCP corresponds to the scope the client was granted at consent. The log is eventually consistent, so a row can take a short time to appear after the call completes. Don't treat an immediate query as authoritative.</p>
<h2 id="the-order-to-set-this-up">The order to set this up</h2>
<p>This sequence is Elaichi-specific. Write the restrictions before anyone connects. A person who signs in first can connect any catalog app their role allows. A restriction added afterward does not retroactively apply to calls already made.</p>
<ol>
<li>Decide the roles. One role per member, each a complete persona.</li>
<li>Write a restriction per role in Elaichi: allow rules for the approved connectors, blocks for the specific tools nobody in that role should reach.</li>
<li>Create the custom app in ChatGPT under Workspace settings, then Apps, then Create. Paste <code>https://api.elaichi.ai/mcp</code> exactly, with no trailing slash, then Scan Tools and complete the OAuth prompt.</li>
<li>Publish the app, setting its enabled actions and, on Enterprise and Edu, the groups it's assigned to.</li>
<li>Set Plugin permissions to control how often ChatGPT prompts before a call.</li>
<li>Have each member connect and sign in. They choose scopes on Elaichi's own consent screen at connection time, and that per-person grant is independent of the role-level restriction and cannot exceed it.</li>
<li>Read the first week of calls in Elaichi's audit trail, filtered to the ChatGPT client. Confirm the restrictions behaved as written before you treat the rollout as done.</li>
</ol>
<p>The client-side detail of step 3 and step 6 is covered in <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT connection walkthrough</a>.</p>
<h2 id="when-the-native-controls-are-enough">When the native controls are enough</h2>
<p>If ChatGPT is the only AI client your organization will run, stop at the native controls described above. That holds when every app your teams need is already in OpenAI's own catalog with the granularity you need. The workspace switches, custom roles, and action controls cost nothing beyond your existing ChatGPT plan. Adding another layer for a problem you don't have is pure overhead.</p>
<p>A control plane like Elaichi earns its place under two conditions, not before. The first: a second MCP client enters the picture (Claude, Cursor, an internal agent), and you need the same restriction to apply in both without maintaining it twice. The second: the access rule you need is finer than "this app, on or off". That means a specific tool inside a connector rather than the whole connector. The Claude side of that two-client case is set out in <a href="/blog/approve-apps-employees-connect-to-claude/">approving apps for Claude across a company</a>.</p>
<p>The case against adding a layer prematurely is set out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when a gateway is premature</a>. The trade-off against OpenAI's built-in apps is in <a href="/blog/elaichi-vs-native-ai-connectors/">native connectors versus one endpoint</a>. For the architecture underneath all of this, see <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. To check whether your teams' apps are covered, see the <a href="/connectors/">connector catalog</a> or <a href="/use-cases/">team use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can a ChatGPT Business workspace give different teams different apps?</strong></dt><dd>No. On ChatGPT Business, turning an app on turns it on for the whole workspace. Giving different groups different apps runs through custom roles under Permissions & roles, then Custom roles, then Plugins & connected data, and that is available on Enterprise and Edu only. Roles are assigned to manual or SCIM groups, roles add up, and changes take up to 5 minutes (help.openai.com, checked October 2026).</dd><dt><strong>Does turning off write actions on a custom MCP app make the connected apps read-only?</strong></dt><dd>No. For a governed MCP endpoint such as Elaichi, ChatGPT sees one custom app whose tools are search_tools, execute_tool and the control-plane operations. Connected tools are never listed individually, so the per-action switches cannot separate a read from a write inside Salesforce or Jira. Read-only access to a connected app is written in Elaichi as a restriction, typically an allow rule naming that connector's read tools. Once a role holds an allow rule, every connector no allow rule names is denied for that role, so the role also needs an allow rule for each other app it uses, or blocks on this app's write tools instead.</dd><dt><strong>How quickly does a restriction change take effect in Elaichi?</strong></dt><dd>Within about two minutes. Role membership and restriction changes resolve through a 60-second cache plus edge propagation on every surface, including MCP, the console and the REST API. A few changes are faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Which log shows that an AI agent wrote to a specific account?</strong></dt><dd>Elaichi's audit log, which writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). It also records the one path argument that names the object, as the target id, and no other argument, plus the surface, the OAuth client the call came through, and how the call was approved. ChatGPT's own Compliance Logs Platform, on Enterprise and Edu, records APP_LOG events with the user, the app and the conversation, and documents no tool-name field.</dd><dt><strong>Who can publish a custom MCP app in ChatGPT Enterprise?</strong></dt><dd>Only Admins and Owners. On Enterprise and Edu, role-based access control can let members build drafts, but the publish step stays with Admins and Owners, and it sets the app's actions and which groups receive it. A published app runs on a frozen snapshot of its tools, so new actions arrive disabled until an admin refreshes them, and OpenAI does not verify custom apps (help.openai.com, checked October 2026).</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Scheduled AI agent tasks, governed in advance</title>
      <link>https://elaichi.ai/blog/scheduled-ai-agent-tasks-safely/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/scheduled-ai-agent-tasks-safely/</guid>
      <description>Scheduled AI agent tasks run with nobody present to approve, so the controls that count are set first: role restrictions, frozen arguments, a narrowed grant.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A scheduled task calls your SaaS tools when nobody is there to approve anything, so the only controls that matter are the ones configured before it runs. Through Elaichi, a scheduled run acts as the member whose OAuth grant the client holds, under that member's role restrictions, and the audit trail names both the member and the client. The three things to set first are restrictions on the role, frozen parameters on a toolbox entry, and a grant scoped to chosen toolboxes.</aside>
<h2 id="why-scheduled-ai-agent-tasks-need-controls-set-before-the-run">Why scheduled AI agent tasks need controls set before the run</h2>
<p>A scheduled task fires at 6am with nobody at the keyboard. That single fact decides the rest. Scheduled AI agent tasks are made safe by what you configure in advance. The approval prompt that would normally catch a bad call has no one there to answer it.</p>
<p>Most teams reach for approval first. Right instinct, wrong layer. Over Elaichi's MCP endpoint, the OAuth grant is the approval. MCP is the protocol an AI client uses to find and call tools. OAuth is the sign-in that issues a client a token on a person's behalf. The person ticked scopes on Elaichi's consent screen for that named client, and that was the human decision. There is no per-call prompt on the endpoint, and any approval card an MCP client renders from Elaichi's results is display only. This applies specifically to the OAuth-gated pattern described here. Some MCP servers authenticate with static API keys or mTLS instead. That removes the consent-screen step entirely and pushes all authorization decisions onto whatever issued the key. If your stack uses that pattern, the "grant as approval" argument below doesn't transfer; you need an equivalent decision made at key-issuance time. <a href="/blog/human-approval-for-ai-agent-actions/">The layers of approval</a> sets out who decides what, and where.</p>
<p>One limit belongs in the open. The endpoint does not inspect prompts and cannot, because an MCP server never sees the user's prompt. It only sees the tool call and arguments the client's model chose to send. The prompt-injection write gate in the Elaichi Agent window does not apply to <code>POST /mcp</code>. What does hold on the endpoint: permissions per operation, the forbidden classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution. None of these five inspect the natural-language prompt that produced the call; all five constrain or record the call itself.</p>
<h2 id="what-do-scheduled-tasks-in-claude-and-chatgpt-do-today">What do scheduled tasks in Claude and ChatGPT do today?</h2>
<p>Three surfaces, three different answers, each read on the vendor's own page.</p>
<table>
<thead>
<tr>
<th>Surface</th>
<th>Default write behavior</th>
<th>Approval model</th>
<th>Execution identity</th>
<th>Source checked</th>
</tr>
</thead>
<tbody>
<tr>
<td>ChatGPT scheduled tasks</td>
<td>Can use Gmail, Slack, GitHub and similar apps; writes may pause for approval</td>
<td>Actions that send messages or change data may pause the task for approval; workspace admins control app permissions</td>
<td>Tasks are included in the Compliance API</td>
<td><a href="https://help.openai.com/en/articles/10291617-scheduled-tasks-in-chatgpt">OpenAI help center</a>, checked October 2026</td>
</tr>
<tr>
<td>Claude Code routines (research preview)</td>
<td>Every connected connector is included by default; writes execute without approval</td>
<td>No approval step; the routine calls tools, writes included, unattended</td>
<td>Actions appear as the owning user</td>
<td><a href="https://code.claude.com/docs/en/web-scheduled-tasks">Claude Code docs</a>, checked October 2026</td>
</tr>
<tr>
<td>Claude Cowork scheduled tasks</td>
<td>Uses connectors; runs remotely</td>
<td>Not documented on the cited page</td>
<td>Not documented; the execution identity is unspecified</td>
<td><a href="https://support.claude.com/en/articles/13854387-schedule-recurring-tasks-in-claude-cowork">Claude support</a>, checked October 2026</td>
</tr>
</tbody>
</table>
<p>A pause is the safe outcome and also an unfinished job, the trade-off to weigh before scheduling anything that writes. Claude Code's shape works unattended precisely because it skips that trade-off. That puts the whole weight of the control on what the owning user can reach: if the user's account can delete a repo, the routine can too. Claude Cowork's undocumented identity is not a minor omission. "Whose credential did this action run under" is the first question any access review asks, and a page that doesn't answer it means you're assuming, not verifying. Treat it as an open question to put to Anthropic rather than a gap to fill in with guesswork.</p>
<p>The practical reading: an unattended run may stop and wait, may write without asking, or may act as an identity nobody can name. Pick your controls accordingly, and re-verify this table against the vendor pages periodically. Scheduled-task behavior for all three products is young enough (research preview, in one case) that it is likely to change faster than most API surfaces.</p>
<h2 id="whose-account-does-a-scheduled-run-act-as-through-elaichi">Whose account does a scheduled run act as through Elaichi?</h2>
<p>It acts as the member whose grant the client holds. Nothing else.</p>
<p>Every client points at one organization-wide address, <code>POST https://api.elaichi.ai/mcp</code>, and each member signs in there once with their own OAuth grant. A scheduled task calls through whichever grant its client is holding, so the call carries that member's role, that member's restrictions and that member's connections. There is no shared service account in the middle unless somebody deliberately shares a connection. A shared connection runs on its owner's credential, so the app sees the owner's account. The reasoning behind <a href="/blog/ai-agents-employee-permissions/">giving an agent an employee's own permissions</a> is the same reasoning that makes a scheduled run attributable.</p>
<p>The record says the same thing afterward. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and each entry names the member, not a generic "agent" identity. The entry also records the surface, <code>mcp</code>, and the OAuth client the call came through. A client's name is marked verified only when its redirect URIs prove it, which covers Claude, ChatGPT and Cursor. A client signing in through a loopback address, such as Claude Code, shows the name it registered with, marked unverified. The approval line on an MCP entry reads "Allowed by the access  was granted." That describes the OAuth grant as the authorizing event, not a per-call human decision. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the rest of the record shape.</p>
<h2 id="which-controls-hold-when-nobody-is-present">Which controls hold when nobody is present</h2>
<p>Three mechanisms, all set before the schedule fires: restrictions on the role, frozen parameters on a toolbox entry, and a grant scoped to chosen toolboxes. These are Elaichi-specific constructs. The general principle (constrain reachable tools, pin dangerous arguments, scope the credential) is portable to any MCP control plane. The specific nouns below are not standard MCP or OAuth terms.</p>
<p><strong>Restrictions on the role.</strong> A restriction decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Within each layer, allow rules union, block rules union, and blocks always beat allows. So a single block on a destructive tool cannot be overridden by any allow rule in the same role, and the two rule types <a href="/blog/block-matches-name-allow-matches-operation/">match a tool by different things</a>. For a scheduled role, blocks on an app's destructive tools are the simplest shape that does not break the rest. An allow rule behaves differently and catches people out. It becomes the role's whole allowlist across every connector, so every other app that role needs takes its own allow rule, naming whole connectors where that is fine. An allow rule naming nothing denies everything. Restrictions are enforced at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. That is a stronger guarantee than "the model is instructed not to call it," since the tool cannot be called at all. A restriction change takes effect within about two minutes, which matters when you're trying to close access in a hurry.</p>
<p><strong>Frozen parameters on a toolbox entry.</strong> A freeze is a per-entry map over a tool's arguments: a destination folder, a payee, a channel. Frozen keys are stripped from the advertised schema, so the model never sees them as fillable fields. Frozen values are merged over caller arguments at execution, so a model that guesses the key name and passes it anyway cannot un-freeze it. The precedence order is: entry defaults, then caller arguments, then frozen values. Frozen values win last. The caveat matters more than the mechanism: a freeze holds only on the path that runs through the entry. If the owner shares the connection itself with the team, the frozen path is bypassed. Anyone holding use on the connection can call the tool unfrozen. The correct setup: the owner keeps the connection unshared with the team. The owner then pins it into a toolbox entry with frozen values, and shares the toolbox at <code>use</code>. Do not try to close the other path with a restriction. A block on the tool withholds the frozen entry too, since restrictions apply before entry-level logic runs. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking a tool argument the way a wire transfer locks a payee</a> walks through the setup.</p>
<p><strong>A grant scoped to chosen toolboxes.</strong> On Elaichi's consent screen, with "Run your connected tools" ticked, a second step asks which toolboxes. The choice is All my tools, or Only the ones I pick, up to 50. For a client that will run unattended, pick. A grant scoped to chosen toolboxes reaches only their tools. If none of them resolves any more there are no connected tools at all, never a silent fallback to everything else the member can reach.</p>
<p>One correction worth carrying into the setup. Leaving "Create and change data" unticked does not make a connected app read-only. For a connected app's tools, "Run your connected tools" covers reads and writes alike. Only a tool whose method is a delete also costs "Delete data and remove access." Read-only access to a connected app is a restriction, not a consent checkbox. <a href="/blog/least-privilege-tool-calls-without-breaking-automation/">Least privilege without breaking automation</a> covers how far to take that before the task stalls.</p>
<h2 id="what-stops-a-scheduled-task-and-how-fast">What stops a scheduled task, and how fast?</h2>
<p>Some changes stop a scheduled run on its very next call, and some take longer. The difference matters when you are closing access in a hurry. Assuming the wrong latency during an incident is itself a risk.</p>
<p><strong>Next call (fast path):</strong> removing or suspending the member. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A SCIM deprovision sets the member to suspended rather than removing them, and that is enough to refuse the next call. SCIM is the standard an identity provider uses to push joiners and leavers into an app. Revoking a share or disconnecting an account also takes effect on the caller's next request. A revoked grant returns 401 <code>invalid_token</code>; a refresh attempt against a revoked grant returns <code>invalid_grant</code>.</p>
<p><strong>Propagation delay (slow path):</strong> role changes, restriction changes and team membership changes take effect within about two minutes. Never plan a shutdown around a restriction edit for that reason. To stop a task at once, suspend the member or revoke the grant, and leave the role alone.</p>
<p>Then there is the clock the task runs against regardless of what you change. An access token lasts 1 hour. A refresh token lasts 30 days and rotates on every use; reusing an old refresh token or authorization code revokes the whole grant. The grant itself has no expiry. But a client idle past 30 days needs the member to sign in again, in a browser, since sign-in cannot be completed headless. Practical consequence: a schedule that quietly stops running is often a grant that needs reconnecting, not a broken connector. That distinction should be the first thing you check before debugging further.</p>
<p>Last, the person behind the connection. Each toolbox entry records who pinned it, and that identity is re-checked on every call, not just at creation. If that person loses <code>use</code>, is removed, or is SCIM-suspended, the entry resolves <code>unmet</code> for every grantee until someone present re-pins it. So a scheduled task can stop working weeks after the person who set it up has left. The connection behind a recurring task should belong to someone who will still be there in six months, as a matter of design, not hope. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding when the agent holds access</a> covers the preflight.</p>
<h2 id="when-a-scheduled-run-is-the-wrong-shape">When a scheduled run is the wrong shape</h2>
<p>If a person genuinely has to look at every write before it lands, do not schedule it over an MCP endpoint at all. There is no mechanism described above that inserts a human into that loop. The Elaichi Agent fits that requirement: a write or delete there stops at an approval card with Deny, Allow once and Always allow, and a delete asks every time. ChatGPT's scheduled tasks may pause for approval on data-changing actions, so check that behavior against the requirement before relying on it. The MCP endpoint, by design, puts no person in the loop.</p>
<p>If the task only reads, skip the frozen parameters and spend the effort on restrictions. A read-only scheduled summary needs a narrow role and an accurate audit trail. Frozen parameters solve an argument-tampering problem that doesn't exist if no call in the role can write.</p>
<p>And if one team runs one app with one assistant, a scheduled task pointed at that app's own MCP server is often enough. Standing up a separate control plane adds overhead that only pays off once the same role needs to touch more than one system. The case for a control plane starts when the same role touches several apps. That is the argument in <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>. The apps a scheduled role can be pointed at are in the <a href="/connectors/">connector catalog</a>, 600+ connectors in all.</p>
<h2>FAQ</h2><dl><dt><strong>Does Elaichi ask for approval before a scheduled AI task writes to an app?</strong></dt><dd>No. Over Elaichi's MCP endpoint, the OAuth grant is the approval: the person picked scopes on Elaichi's consent screen for that named client, and the server re-checks those scopes on every call. There is no per-call prompt on the endpoint, and any approval card an MCP client renders from Elaichi's results is display only. Per-call prompting over MCP belongs to the client. Inside the Elaichi Agent, a write or delete does stop at an approval card before it runs.</dd><dt><strong>Whose permissions does a scheduled AI agent task run with?</strong></dt><dd>Through Elaichi, a scheduled task runs with the permissions of the member whose OAuth grant the client holds. The call carries that member's role, restrictions and connections, and Elaichi's audit entry names that member, the surface (mcp) and the OAuth client it came through. Claude Code routines act as the owning user, per [Anthropic's docs](https://code.claude.com/docs/en/web-scheduled-tasks) (checked October 2026); whose identity a Claude Cowork scheduled task acts as is not documented.</dd><dt><strong>How long can a scheduled task keep calling without anyone signing in again?</strong></dt><dd>An Elaichi access token lasts 1 hour and a refresh token lasts 30 days, rotating on every use. A client that keeps refreshing can run indefinitely, but one that sits idle past 30 days needs the member to sign in again in a browser, because Elaichi's OAuth sign-in cannot be completed headless. Reusing an old refresh token or authorization code revokes the whole grant.</dd><dt><strong>What happens to a scheduled task when the employee behind it leaves?</strong></dt><dd>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. So the scheduled task's very next call is refused. A SCIM deprovision sets the member to suspended rather than removing them, which has the same effect on live grants. Separately, any toolbox entry that person pinned stops resolving for every grantee until someone present re-pins it.</dd><dt><strong>Can an argument be locked so a scheduled agent cannot change it?</strong></dt><dd>Yes, with frozen parameters on a toolbox entry in Elaichi. Frozen keys are stripped from the advertised tool schema, so the model cannot fill them in, and frozen values are merged over caller arguments at execution, so passing the key cannot override the freeze. The freeze holds only on the path through that entry, so the connection's owner leaves the connection unshared and shares the toolbox at use instead.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>governance</category>
    </item>
    <item>
      <title>Stop sharing personal API keys with AI tools</title>
      <link>https://elaichi.ai/blog/stop-sharing-personal-api-keys-with-ai-tools/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/stop-sharing-personal-api-keys-with-ai-tools/</guid>
      <description>Find where people sharing personal API keys with AI tools put them, lean on what the key issuers already catch, then remove the reason to paste one.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Stopping people sharing personal API keys with AI tools takes three moves: find the keys in local MCP client config files, repositories and chats; turn on what GitHub, OpenAI and Anthropic already catch; then remove the reason people paste keys. Elaichi is the third move. It is one organization-wide MCP endpoint behind OAuth, where connector credentials sit with a separate credential service and the model never handles them. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</aside>
<h2 id="where-people-sharing-personal-api-keys-with-ai-tools-put-them">Where people sharing personal API keys with AI tools put them</h2>
<p>They sit in three places: local AI client config files, Git repositories, and chat histories. Start with the config files, because nothing inventories them for you.</p>
<p>The usual path is ordinary. An engineer wants Claude or Cursor to read an internal system, installs a local MCP server, and pastes a key into that server's environment block. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Sharing personal API keys with AI tools spreads through exactly this shortcut, one laptop at a time, with no ticket and no record. Nobody is being reckless. There is no sanctioned path, so people build their own.</p>
<p>This post covers the Claude/ChatGPT/Cursor/Copilot ecosystem because that is where the documented vendor controls exist as of this writing. The same failure mode shows up with other providers' keys: Azure OpenAI keys pasted into local scripts, and AWS Bedrock credentials in <code>.env</code> files. Neither has a vendor-documented admin console either. The discovery method below, read the file rather than ask the vendor, applies to all of them.</p>
<p>No client vendor documents an admin console that lists the servers sitting in members' local config files (vendor docs read October 2026). Finding them means reading the files on each device, with a mobile device management or endpoint detection script. The paths, from each vendor's own documentation:</p>
<ul>
<li><strong>Claude Desktop</strong>: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code> on macOS, <code>%APPDATA%\Claude\claude_desktop_config.json</code> on Windows, servers under <code>mcpServers</code> (<a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">modelcontextprotocol.io</a>).</li>
<li><strong>Claude Code</strong>: <code>~/.claude.json</code> for local and user scope, <code>.mcp.json</code> at the repo root for project scope. That file also holds the sign-in session, so read only its <code>mcpServers</code> objects (<a href="https://code.claude.com/docs/en/mcp">code.claude.com</a>).</li>
<li><strong>Cursor</strong>: <code>~/.cursor/mcp.json</code> globally, <code>.cursor/mcp.json</code> per project (<a href="https://cursor.com/docs/mcp">cursor.com/docs/mcp</a>).</li>
<li><strong>VS Code with GitHub Copilot</strong>: <code>.vscode/mcp.json</code> and a user-profile <code>mcp.json</code>, both now marked deprecated, plus <code>.mcp.json</code> at the project root and <code>~/.copilot/mcp-config.json</code> (<a href="https://code.visualstudio.com/docs/agent-customization/mcp-servers">code.visualstudio.com</a>).</li>
<li><strong>Devin Desktop</strong>, formerly Windsurf: <code>~/.config/devin/mcp_config.json</code>, and the older <code>~/.codeium/windsurf/mcp_config.json</code> (<a href="https://docs.devin.ai/desktop/cascade/mcp">docs.devin.ai</a>).</li>
<li><strong>Codex</strong>: <code>~/.codex/config.toml</code>, one <code>[mcp_servers.&#x3C;name>]</code> table per server (<a href="https://learn.chatgpt.com/docs/extend/mcp">learn.chatgpt.com</a>).</li>
</ul>
<p>Run the same sweep across repositories and any chat export you can reach. A fuller version of the discovery pass is in <a href="/blog/find-mcp-servers-employees-installed/">the guide to finding installed MCP servers</a>.</p>
<h2 id="what-do-the-key-issuers-already-catch">What do the key issuers already catch?</h2>
<p>More than most security teams assume. Some of it is on by default and the rest is a license line, before you build anything.</p>
<p>GitHub secret scanning is free and automatic on public repositories. Private and internal repositories need GitHub Secret Protection, at $19 per active committer per month on GitHub Team or Enterprise. Push protection for users is on by default for public repositories on GitHub.com; repository push protection is off by default and needs Secret Protection (<a href="https://docs.github.com/en/code-security/concepts/secret-security/push-protection">docs.github.com</a>, <a href="https://github.com/security/advanced-security">GitHub Advanced Security</a>, checked October 2026). OpenAI and Anthropic keys are partner patterns, so they carry push protection and validity checks (<a href="https://docs.github.com/en/code-security/reference/secret-security/supported-secret-scanning-patterns">docs.github.com</a>, checked October 2026).</p>
<p>OpenAI says sharing API keys is against its Terms of Use, and that it disables a key as soon as it is found on the public internet or inside an app-store app (<a href="https://help.openai.com/en/articles/8304786-keeping-your-openai-account-secure">help.openai.com</a>, checked October 2026). Anthropic takes part in GitHub's partner program, deactivates exposed Claude API keys automatically and emails the owner; a personal key is archived when its owner is removed from the organization (<a href="https://support.claude.com/en/articles/9767949-api-key-best-practices-keeping-your-keys-safe-and-secure">support.claude.com</a>, checked October 2026).</p>
<p>Turn these on first. They cost a license line and a configuration change, and they catch the loudest failure mode, which is a key committed to a repository. They do nothing about a valid token sitting quietly in a config file on one laptop, which never gets near <code>git push</code>.</p>
<h2 id="what-api-key-governance-and-inference-hooks-cover">What API Key Governance and inference hooks cover</h2>
<p>Four vendor-side controls exist today, and they do not overlap. None of them, alone or together, covers a key already pasted into a local MCP server's config file.</p>
<table>
<thead>
<tr>
<th>Control</th>
<th>What it gates</th>
<th>Maturity (per vendor docs, Oct 2026)</th>
<th>Where it lives</th>
<th>What it misses</th>
</tr>
</thead>
<tbody>
<tr>
<td>GitHub Secret Protection</td>
<td>Commits before push</td>
<td>Generally available</td>
<td>$19 per active committer per month on GitHub Team or Enterprise</td>
<td>Keys never committed to a repo</td>
</tr>
<tr>
<td>OpenAI API Key Governance</td>
<td>Key creation (service-account-only, or block new keys)</td>
<td>Announced 15 September 2026</td>
<td>OpenAI Platform settings</td>
<td>Keys already created before the policy was turned on; no rotation</td>
</tr>
<tr>
<td>Claude Enterprise Inference hooks</td>
<td>Prompt content, before inference</td>
<td>Beta</td>
<td>Claude Enterprise</td>
<td>Anything outside the prompt path: config files, repos</td>
</tr>
<tr>
<td>ChatGPT Enterprise network controls</td>
<td>Workspace membership at the network layer (<code>ChatGPT-Allowed-Workspace-Id</code> header)</td>
<td>Not stated</td>
<td>Your network proxy or SASE, for ChatGPT Enterprise</td>
<td>Prompt content itself, with no documented inline filter</td>
</tr>
</tbody>
</table>
<p>OpenAI's API Key Governance, announced 15 September 2026, lets admins allow only service-account keys or block new key creation outright (<a href="https://developers.openai.com/api/docs/guides/production-best-practices">developers.openai.com</a>, checked October 2026). It narrows who can create a personal key going forward. It does not claim automatic rotation of keys that already exist, so do not plan on one.</p>
<p>For secrets typed into a prompt rather than a config file, Claude Enterprise has Inference hooks, in beta. Each governed prompt is sent to the organization's own security server for an allow or deny verdict before inference, with no redaction step: the verdict is binary, not a scrub (<a href="https://platform.claude.com/docs/en/manage-claude/inference-hooks">platform.claude.com</a>, checked October 2026). ChatGPT Enterprise has no documented native equivalent for inline prompt filtering. Review runs after the fact through Compliance Platform partners, and a <code>ChatGPT-Allowed-Workspace-Id</code> header injected at the network keeps people off personal workspaces, but it does not inspect what's typed into a sanctioned one (<a href="https://help.openai.com/en/articles/20001323-corporate-network-controls-in-chatgpt-enterprise">help.openai.com</a>, checked October 2026).</p>
<p>The asymmetry matters when you decide which assistant gets which data: one vendor documents a prompt-time content gate, the other documents workspace-level network controls plus after-the-fact review. Neither touches a project-scoped key already pasted into a local environment file. That gap is what the next section is about.</p>
<h2 id="remove-the-reason-to-paste-a-key">Remove the reason to paste a key</h2>
<p>People paste keys because the sanctioned path does not exist yet. Build the path and the pasting drops, because the key stops being the only way in.</p>
<p>The rest of this section describes how Elaichi, specifically, implements that path. This is vendor self-report, not an independently audited claim: treat the architecture description as "how one product says it works," and verify against your own vendor's documentation before relying on it for a compliance control.</p>
<p>Elaichi is a governed MCP control plane. Every company SaaS account is connected once, and the tools those accounts expose are served through one organization-wide MCP endpoint at <code>https://api.elaichi.ai/mcp</code>. Claude, ChatGPT, Cursor and any other MCP client all point at that same address and sign in over OAuth (an authorization standard where the client receives a scoped token instead of a shared secret). Clients register themselves through <a href="https://datatracker.ietf.org/doc/html/rfc7591">dynamic client registration</a> with PKCE (a challenge-response extension to OAuth that stops an intercepted authorization code from being replayed), so there is no client ID, secret, or header for a person to type or to leak.</p>
<p>Four properties do the work, as Elaichi documents them:</p>
<ul>
<li><strong>No key to hand out.</strong> Connector credentials never live in Elaichi's application layer. A separate credential service holds per-account secrets, encrypted at rest with AES-256-GCM, and owns token refresh. A failed refresh marks the connection <code>needs_reauth</code> rather than failing silently.</li>
<li><strong>The model never handles the credential.</strong> The model finds a connected tool with <code>search_tools</code> and runs it with <code>execute_tool</code>, two tools Elaichi exposes over MCP. The credential is read and the third-party call made server-side. Tool results are scrubbed for secret-shaped values before they reach the model, as a backstop, not the primary control.</li>
<li><strong>Nothing secret is readable back.</strong> Reading an account's configuration returns public values plus <code>secret_paths</code>, the list of dot-paths that were encrypted, carrying none of the underlying values. Editing one is refused by the API.</li>
<li><strong>Revocation is a database write, not a key rotation.</strong> The grant's <code>revoked_at</code> field is re-read from the organization store on every call, with no cache. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</li>
</ul>
<p>That last point is the one an offboarding checklist cares about. Disabling an identity provider account does nothing to a static key sitting in a config file on a laptop. The key keeps working until someone revokes it at the issuer, which can be days later or never. A grant to a governed endpoint dies on the next tool call, because the revocation check happens per-request rather than per-session. The argument for OAuth over static keys generally, not specific to this vendor, is set out in <a href="/blog/oauth-vs-api-keys-for-ai-agents/">the comparison of the two credential shapes</a>.</p>
<p>There is also no server to install on a laptop in this model. Elaichi authors, maintains and serves most of its connectors from its own infrastructure, and the rest are app vendors' own MCP servers that it governs, so adopting the path does not mean approving somebody else's code onto a laptop. That is a real tradeoff against a registry-based approach, not a strictly better one: you gain a single control plane to audit and lose the option of a community-maintained connector for something niche. <a href="/blog/mcp-registry-vs-first-party-connectors/">Where your connectors come from</a> covers that distinction in more detail.</p>
<p>The path only removes the reason to paste a key if the app people want is actually on it. Elaichi's catalog holds 600+ connectors, and where a connector needs the organization's own OAuth app, an admin with <code>connector:manage</code> adds it. Check <a href="/connectors/">the connector catalog</a> before you write the policy line below, so the policy isn't asking people to use something that doesn't exist yet. The cost side: building or buying this is more setup than flipping on GitHub push protection, and it is only worth it once more than one or two engineers are already pasting keys, which is the trigger condition in the last section of this post.</p>
<h2 id="the-one-policy-line-worth-writing">The one policy line worth writing</h2>
<p>Write one sentence people can remember at the moment they are about to break it.</p>
<blockquote>
<p>No personal API key goes into an AI client's config, a prompt, or a repository. If the app is on the company MCP endpoint, connect it there. If it is not, file a request and we will add it.</p>
</blockquote>
<p>That line works because it names the alternative in the same breath as the prohibition. A rule with no sanctioned path is a rule people route around, and the routing is invisible, which is the whole shadow AI problem. Pair it with a request route. In Elaichi, any member can file an access request with no permission needed, and resolving one takes <code>member:manage</code>.</p>
<h2 id="what-to-do-when-a-key-turns-up">What to do when a key turns up</h2>
<p>Revoke first, then rotate, then read the usage. In that order, because every minute between discovery and revocation is a minute the key still works.</p>
<ol>
<li><strong>Revoke at the issuer.</strong> Not at the gateway, not in the config file. The key is valid until the system that issued it says otherwise.</li>
<li><strong>Rotate the replacement into a sanctioned place.</strong> A service account the platform team owns, or a connection on the governed endpoint. Never back into the same config file.</li>
<li><strong>Read the usage history at the issuer.</strong> You want the window between creation and revocation, and whether any call came from somewhere you do not recognize.</li>
<li><strong>Sweep for copies.</strong> The same key is often in a second config file, a <code>.env</code>, and a chat message. Use the paths listed earlier in this post.</li>
<li><strong>Record what you did.</strong> If the app also sits behind Elaichi, disconnecting that account takes effect on the caller's next request, not on a schedule. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</li>
</ol>
<h2 id="what-a-governed-endpoint-does-not-stop">What a governed endpoint does not stop</h2>
<p>It does not stop someone pasting a key into a chat window. An MCP endpoint sits between a client and a SaaS account. It never sees the prompt, so it cannot inspect one. This is a structural limit of the architecture, not a missing feature.</p>
<p>That half of the problem belongs to the issuer controls and to DLP (data loss prevention tooling that inspects content leaving the company). Four layers, each covering a different point in the path, none of them redundant with the others:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Example control</th>
<th>Catches</th>
</tr>
</thead>
<tbody>
<tr>
<td>Prompt content</td>
<td>Claude Enterprise Inference Hooks</td>
<td>A secret typed into a chat window, before inference</td>
</tr>
<tr>
<td>Commit content</td>
<td>GitHub push protection</td>
<td>A secret committed to a repository</td>
</tr>
<tr>
<td>Key issuance</td>
<td>OpenAI API Key Governance</td>
<td>A personal key being created in the first place</td>
</tr>
<tr>
<td>Tool call / credential</td>
<td>Governed MCP endpoint</td>
<td>A credential being read or misused during a tool call</td>
</tr>
</tbody>
</table>
<p>Treating any one of these as the whole program leaves the other three gaps open. <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">How CASB and DLP see AI traffic</a> covers what each layer observes in more detail, and <a href="/blog/shadow-ai-coo-customer-emails-pasted/">why people paste company data in the first place</a> covers the underlying behavior.</p>
<p>One more specific limit. The prompt-injection write gate in the Elaichi Agent does not apply to <code>POST /mcp</code> and structurally cannot, because an MCP server never sees a user prompt. It only sees a tool call with parameters. What does hold on the endpoint is permission checks per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits, and an audit row for each call that reaches execution.</p>
<p>And there is a case where none of this is yours yet. If nobody has wired an AI client to a company system, and the only keys in play are a handful of model API keys on a platform team's service accounts, the issuer controls plus a rotation habit are the whole program. Buying or building a governed endpoint before that point is solving a problem you don't have yet. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The signs you do not need a gateway yet</a> is the better read in that situation. Come back when the second engineer pastes a production key into a config file, because that is the week the shortcut becomes a pattern instead of an incident.</p>
<p>For the shape of the thing you would be adopting, start with <a href="/blog/what-is-an-mcp-control-plane/">the control plane explainer</a>. For the laptop side of the cleanup, <a href="/blog/replace-personal-mcp-servers/">replacing personal MCP servers</a> picks up where the discovery sweep ends.</p>
<h2>FAQ</h2><dl><dt><strong>Can an admin console show which API keys sit in employees' local AI client config files?</strong></dt><dd>No. As of October 2026, no MCP client vendor documents an admin inventory of the servers sitting in members' local configuration files. Admin consoles report servers that connect through the vendor's own surface. Finding local servers, and the keys in their environment blocks, means reading the files on each device with a device management or endpoint detection script, at paths such as ~/.cursor/mcp.json for Cursor ([cursor.com/docs/mcp](https://cursor.com/docs/mcp)), ~/.claude.json for Claude Code ([code.claude.com](https://code.claude.com/docs/en/mcp)) and ~/.codex/config.toml for Codex ([learn.chatgpt.com](https://learn.chatgpt.com/docs/extend/mcp)).</dd><dt><strong>Does GitHub secret scanning cover private repositories by default?</strong></dt><dd>No. GitHub secret scanning is free and automatic on public repositories. Private and internal repositories need GitHub Secret Protection, which costs $19 per active committer per month on GitHub Team or Enterprise. Push protection for users is on by default for public repositories on GitHub.com, while repository push protection is off by default and also needs Secret Protection ([docs.github.com](https://docs.github.com/en/code-security/concepts/secret-security/push-protection), checked October 2026).</dd><dt><strong>Does disabling someone's identity provider account kill the API keys on their laptop?</strong></dt><dd>No. An API key pasted into a local AI client config file is a standalone credential. It keeps working until someone revokes it at the system that issued it. That is the practical difference with OAuth: a grant to Elaichi's organization-wide MCP endpoint is checked on every call with no cache. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Will a governed MCP endpoint stop employees pasting API keys into chat?</strong></dt><dd>No, and it cannot. An MCP endpoint sits between an AI client and a SaaS account and never sees the user's prompt. Prompt-level secrets belong to other layers: Claude Enterprise Inference hooks send each governed prompt to the organization's own security server for an allow or deny verdict before inference ([platform.claude.com](https://platform.claude.com/docs/en/manage-claude/inference-hooks), checked October 2026), while ChatGPT Enterprise has no documented native equivalent and relies on after-the-fact compliance review plus network controls ([help.openai.com](https://help.openai.com/en/articles/20001323-corporate-network-controls-in-chatgpt-enterprise), checked October 2026).</dd><dt><strong>What is the first step when a personal API key turns up in a config file?</strong></dt><dd>Revoke it at the issuer, before anything else. The key stays valid until the issuing system says otherwise, so deleting it from the file changes nothing. Then rotate the replacement into a sanctioned place, read the key's usage history at the issuer for the window between creation and revocation, and sweep for copies in other config files, .env files and chat messages.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>MCP for coding agents across an engineering org</title>
      <link>https://elaichi.ai/blog/coding-agents-company-tools/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/coding-agents-company-tools/</guid>
      <description>MCP for coding agents needs one endpoint, a sign-in per engineer, and rules the agent cannot edit, because nobody reads each call it makes.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Coding agents such as Claude Code and Cursor's agent run many steps without a person reading each call, and engineers usually wire them to company tools with personal tokens in local config files. Elaichi replaces those tokens with one organization-wide MCP endpoint that each engineer signs in to with OAuth. Restrictions on the destructive tools, frozen arguments and an audit log then hold on the server, where the agent cannot change them.</aside>
<p>An engineer hands Claude Code a Jira ticket at 4:40 PM and goes to a meeting. When she returns, the agent has read the ticket and pulled the Sentry stack trace. It has checked the PagerDuty incident, changed three files and pushed a branch. It has posted in the team's Slack channel. That took dozens of tool calls, and nobody read any of them as they ran.</p>
<p>That run is what MCP for coding agents has to be designed around. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A chat assistant answers a person who reads every reply. A coding agent works a task, and the person reads the result.</p>
<h2 id="what-makes-a-coding-agent-different-from-a-chat-assistant">What makes a coding agent different from a chat assistant?</h2>
<p>Four things: it takes many steps per task, it acts without a person approving each call, it runs on the engineer's machine, and the engineer wires it up in a config file. Each one moves the control away from the person in the chat.</p>
<p>Both clients let engineers turn approval prompts down. Claude Code's <code>auto</code> mode "runs without routine prompts", with a background classifier checking actions instead. Its <code>bypassPermissions</code> mode skips prompts, and the docs say to use it only "in isolated environments like containers or VMs" (<a href="https://code.claude.com/docs/en/permissions">Claude Code permissions</a>, checked October 2026). A scripted <code>claude -p</code> run "shows no workspace trust dialog and no per-server approval prompt" (<a href="https://code.claude.com/docs/en/headless">Claude Code headless docs</a>).</p>
<p>Cursor "asks for approval before using MCP tools by default". Its Run Modes can let approved tools "run immediately" and send everything else to a classifier (<a href="https://cursor.com/docs/mcp">Cursor's MCP docs</a>, checked October 2026).</p>
<p>None of that is a flaw. Speed is the reason teams use coding agents. It does mean the approval prompt is a convenience the engineer controls. The rules that matter have to sit where the call lands.</p>
<h2 id="what-goes-wrong-when-each-engineer-wires-up-their-own-mcp-servers">What goes wrong when each engineer wires up their own MCP servers?</h2>
<p>Four problems arrive together: server sprawl, secrets in dotfiles, slow offboarding and no shared record. They grow with headcount, not with usage.</p>
<p>Sprawl comes from the config model. Claude Code stores a server at local, project or user scope, in <code>~/.claude.json</code> or a project's <code>.mcp.json</code> (<a href="https://code.claude.com/docs/en/mcp">Claude Code MCP docs</a>, checked October 2026). Cursor reads <code>.cursor/mcp.json</code> or <code>~/.cursor/mcp.json</code>. Forty engineers end up with forty different sets of servers, and nobody holds the list.</p>
<p>Secrets follow the same path. Claude Code's own example adds a server with <code>--header "Authorization: Bearer YOUR_GITHUB_PAT"</code>, and <code>.mcp.json</code> can expand <code>${API_KEY}</code> from the environment. Cursor interpolates <code>${env:MY_SERVICE_TOKEN}</code> the same way. The token then lives in a shell profile or an <code>.env</code> file. A personal token usually carries everything its owner can do in that app, and the agent inherits all of it.</p>
<p>Offboarding becomes a hunt. Each token is revoked app by app, and only if someone knows it exists. The record is split too. Each app logs the call against the engineer's token, and a call on a personal token looks the same as the engineer's own.</p>
<h2 id="how-should-mcp-for-coding-agents-work-without-shared-api-keys">How should MCP for coding agents work without shared API keys?</h2>
<p>Through one organization-wide endpoint that each engineer signs in to with OAuth (a sign-in that issues a revocable grant instead of a copied secret). Elaichi serves every connected account at <code>https://api.elaichi.ai/mcp</code>. Claude, ChatGPT, Cursor and any MCP client use that same address.</p>
<p>The config entry holds a URL and nothing else. Claude Code "supports OAuth 2.0 for secure connections", runs the sign-in in the browser from <code>/mcp</code>, and stores tokens securely and refreshes them. Cursor supports OAuth for servers that require it. Both register themselves with Elaichi through dynamic client registration, so nobody types a client ID or a secret. A project <code>.mcp.json</code> holding only the address is safe to commit.</p>
<p>Each SaaS account is connected once, in Elaichi, not on a laptop. A separate credential service holds the account secrets, encrypted at rest, and owns refresh. An engineer's grant issues access tokens that last an hour and refresh tokens that rotate on every use.</p>
<p>The step-by-step setup is in <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">connecting Cursor for a whole team</a> and in the <a href="/blog/connect-elaichi-to-claude-code/">Claude Code setup guide</a>. For why a grant beats a pasted key, read <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth or API keys for AI agents</a>.</p>
<h2 id="how-do-you-give-engineers-ai-access-to-jira-and-pagerduty-with-the-right-permissions">How do you give engineers AI access to Jira and PagerDuty with the right permissions?</h2>
<p>Give engineers one role, share them a toolbox instead of the connections, and restrict the destructive tools on that role. The consent screen then holds back deletes on each engineer's grant.</p>
<p>The role carries <code>tool:execute</code>, which gates the whole endpoint. Each member holds exactly one role, so it has to be complete. A member sees only what they own or what was shared with them, and no admin role widens that view. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Start with the tools whose damage is hard to undo:</p>
<ul>
<li><code>delete_a_jira_issue_by_id</code>, which can take an issue's subtasks with it when <code>deleteSubtasks</code> is true.</li>
<li><code>delete_a_pagerduty_service_by_id</code>. Its description says that once deleted, "new incidents cannot be created for it".</li>
<li><code>delete_a_pagerduty_event_orchestrations_integration_by_id</code>, which removes a routing key, "stopping all future events sent with that key".</li>
<li><code>sentry_organization_issues_bulk_delete</code>. If no issue IDs are passed, "the first 1000 matching issues are removed".</li>
</ul>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema, so an agent chasing a bad idea finds nothing to call. A rule takes about two minutes to apply, so wait before you test it.</p>
<p>The grant adds a second lock. On Elaichi's consent screen, "Delete data and remove access" is never ticked in advance. Without that scope, connected tools whose method is a delete are left out of the tool list and the search index.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The PagerDuty connector page lists every tool a restriction can name, with the setup for Claude, ChatGPT and Cursor.</p><a href="/connectors/pagerduty/" class="cta-button">See the PagerDuty connector</a></aside>
<h2 id="why-shouldnt-a-coding-agents-own-approval-rules-decide-read-versus-delete">Why shouldn't a coding agent's own approval rules decide read versus delete?</h2>
<p>Because every connected Elaichi tool reaches the client through one tool, <code>execute_tool</code>, and the usual approval rules name that tool instead of the one inside it. In Elaichi, connected tools are never listed one by one, however few there are. The agent finds a tool with <code>search_tools</code> and runs it with <code>execute_tool</code>.</p>
<p>Claude Code writes MCP permission rules against a tool name, such as <code>mcp__puppeteer__puppeteer_navigate</code>. For Elaichi, that name is the same for a Sentry read and a Sentry bulk delete. A Cursor approval prompt likewise names <code>execute_tool</code>, with the real tool inside the arguments.</p>
<p>Claude Code can go further, but only on the command line. A deny rule passed with <code>--disallowedTools</code> can match the <code>name</code> parameter of <code>execute_tool</code> by exact value, which names one tool. Settings files skip MCP rules that carry a parameter, and allow rules cannot match a parameter at all.</p>
<p>So keep the read-versus-delete decision in Elaichi's restrictions. <code>execute_tool</code> is only a naming indirection. It unwraps to the real tool and arguments and passes the same checks as a direct call, with no extra privilege.</p>
<h2 id="how-do-frozen-parameters-keep-a-long-running-agent-on-target">How do frozen parameters keep a long-running agent on target?</h2>
<p>They fix the arguments that pick a destination, so the agent cannot choose them. Freeze <code>channel</code> on <code>create_a_slack_chat</code> and the project inside <code>fields</code> on <code>create_a_jira_issue</code>.</p>
<p>A frozen key is stripped from the schema the agent sees, so the model is never offered a channel to pick. At execution, the frozen value is merged over whatever the agent sends. The order is entry defaults, then the agent's arguments, then frozen values last.</p>
<p>That matters most for an agent nobody is watching. A misread ticket cannot send its status update to the company-wide channel. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. The connection owner pins the entry and vouches for it, so pick an owner who will stay. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking a wire transfer's receiver</a> walks through the same setup.</p>
<h2 id="what-does-one-jira-ticket-look-like-call-by-call">What does one Jira ticket look like, call by call?</h2>
<p>Seven steps, five of which run through Elaichi. The code edits and the pull request stay on the engineer's machine.</p>
<ol>
<li>The agent searches for a Jira tool and calls <code>get_single_jira_issue_by_id</code> for the ticket.</li>
<li>It reads the error with <code>get_single_sentry_organization_issue_by_id</code>, then <code>list_all_sentry_issue_events</code> with <code>latest</code> as the event ID.</li>
<li>It checks the incident with <code>get_single_pagerduty_incident_by_id</code>.</li>
<li>It edits files and runs tests locally. Elaichi sees none of this.</li>
<li>It opens the pull request with the engineer's own Git and GitHub credentials. GitHub is not in Elaichi's catalog, so this step stays outside Elaichi.</li>
<li>It links the pull request with <code>create_a_jira_issue_comment</code> and <code>create_a_pagerduty_incident_note</code>.</li>
<li>It posts a summary with <code>create_a_slack_chat</code>, to the frozen channel.</li>
</ol>
<p>Each call through Elaichi passes the engineer's role, the restrictions and the grant's scopes. An agent stuck in a retry loop meets a plain limit: 120 MCP requests a minute per token, then a 429 with <code>Retry-After: 60</code>.</p>
<h2 id="how-do-you-tell-afterward-which-agent-made-a-call">How do you tell afterward which agent made a call?</h2>
<p>From Elaichi's audit trail, which records one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account the call actually reached.</p>
<p>Each tool-call entry also records the surface and the OAuth client the call came through. Elaichi trusts a client's name only when its registered redirect addresses prove it, as with Claude, ChatGPT and Cursor. A terminal client that signs in through a local loopback address, such as Claude Code, carries the name it registered with, marked unverified.</p>
<p>The trail keeps the one path argument that names the object, as the target id, and nothing else about the arguments, so it shows what ran and where without holding the payload. The read-only Auditor seat is free. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> lists the fields.</p>
<h2 id="is-there-an-mcp-gateway-that-supports-claude-code-and-codex-for-engineering-teams">Is there an MCP gateway that supports Claude Code and Codex for engineering teams?</h2>
<p>Elaichi is an <a href="/blog/what-is-an-mcp-control-plane/">MCP control plane</a>, a hosted service rather than a gateway you deploy, and its endpoint is standard MCP over Streamable HTTP behind OAuth. Claude Code, Cursor, Codex, Windsurf and VS Code Copilot connect to it with an OAuth sign-in and no key. Any other client fits under "any MCP client" when it supports remote servers with an OAuth sign-in.</p>
<p>Codex documents both. Its docs describe "Streamable HTTP servers: Servers that you access at an address", and <code>codex mcp login &#x3C;server-name></code> "to start an MCP OAuth login" (<a href="https://learn.chatgpt.com/docs/extend/mcp?surface=cli">Codex MCP docs</a>, checked October 2026). Sign-in needs a browser. An unattended CI run with no browser, in any of these clients, cannot sign in, so plan for engineers to sign in at their own machines.</p>
<h2 id="when-is-an-apps-own-mcp-server-the-better-choice-for-a-coding-agent">When is an app's own MCP server the better choice for a coding agent?</h2>
<p>When the team needs one app, especially one Elaichi does not carry. The app's server runs under its own permission model and puts no second vendor in the path.</p>
<p>GitHub is the clearest case. Its server "connects AI tools directly to GitHub's platform", hosted at <code>https://api.githubcopilot.com/mcp</code>, with a read-only mode that skips write tools (<a href="https://github.com/github/github-mcp-server">GitHub MCP Server</a>, checked October 2026). Sentry runs one at <code>https://mcp.sentry.dev/mcp</code>, and "All connections use OAuth" (<a href="https://mcp.sentry.dev/">Sentry MCP</a>, checked October 2026). <a href="https://github.com/atlassian/atlassian-mcp-server">Atlassian's server</a> connects Jira, Confluence and more to AI tools "using OAuth 2.1 or API tokens" (checked October 2026).</p>
<p>What Elaichi adds is the layer across apps. Engineers add one address instead of one server per app. Restrictions are written once for the engineer role across <a href="/connectors/jira/">Jira</a>, <a href="/connectors/sentry/">Sentry</a>, PagerDuty and <a href="/connectors/slack/">Slack</a>. Frozen arguments, one audit trail, and one removal that ends access through Elaichi come with it. That removal does not close the person's accounts inside each app.</p>
<h2 id="when-does-an-engineering-team-not-need-any-of-this">When does an engineering team not need any of this?</h2>
<p>When the agents only touch local code, or when a few engineers share one read-only account and nobody asks who did what. A coding agent that reads and writes files reaches no SaaS account, so there is nothing to govern.</p>
<p>Elaichi also stops at its own edge. It does not see the shell, Git, or a local server an engineer adds beside it. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. A poisoned ticket can still steer a model toward a tool. Restrictions decide whether that tool exists for the engineer. A call that reaches execution is logged.</p>
<p>A contractor, a second Jira site or an auditor's question changes the math. Run the test in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway</a> first. Gold lists at $15 per user per month in USD.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Start the trial, connect Jira, Sentry and Slack once, and point Claude Code and Cursor at one address the same day.</p><a href="/pricing/" class="cta-button">See pricing</a></aside>
<h2>FAQ</h2><dl><dt><strong>How do you give Cursor access to internal tools across an engineering team without sharing API keys?</strong></dt><dd>Connect each company account once in Elaichi, then have every engineer add the same address, https://api.elaichi.ai/mcp, as a remote MCP server in Cursor. The entry holds a URL and no key. Cursor supports OAuth for servers that require it, so each engineer signs in as themselves and gets a grant that can be revoked on its own. The account credentials stay in Elaichi's separate credential service and never reach a laptop.</dd><dt><strong>Does Elaichi work with Codex, Windsurf or VS Code Copilot?</strong></dt><dd>Yes. Elaichi serves standard MCP over Streamable HTTP behind OAuth, and Codex, Windsurf and VS Code Copilot connect to it, as do Claude, ChatGPT, Cursor and Claude Code. Any other MCP client that supports remote servers with an OAuth sign-in fits under "any MCP client". Sign-in needs a browser, so an unattended CI run with no browser cannot sign in.</dd><dt><strong>Can a coding agent delete things through Elaichi?</strong></dt><dd>Only what the engineer's grant and the organization's rules allow. On Elaichi's consent screen, the box for deleting data is never ticked in advance. Without that scope, connected tools whose method is a delete are left out of the tool list and out of search. Admins can also restrict individual tools for a role. A restricted tool is withheld from the tool list and cannot be called, and search names it, flagged restricted.</dd><dt><strong>What happens to a coding agent's access when an engineer leaves?</strong></dt><dd>It ends with their Elaichi membership. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next call from their Claude Code or Cursor fails. The URL left in their config file is the same public address every engineer uses and carries no token. Their own accounts inside each app are a separate step.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Connect company apps to Claude and ChatGPT</title>
      <link>https://elaichi.ai/blog/connect-company-apps-to-claude-and-chatgpt/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-company-apps-to-claude-and-chatgpt/</guid>
      <description>To connect company apps to Claude and ChatGPT, connect each account once in Elaichi, share it, and add one URL to both. No MCP server to run.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect company apps to Claude and ChatGPT for everyone, connect each account once in Elaichi, share the connections or a toolbox with the people who need them, and add Elaichi's one address, https://api.elaichi.ai/mcp, to each client. Each person then signs in once with OAuth, with no URL, token or client ID to paste. Elaichi runs or governs every connector, so the company runs no MCP server, and a new app is a new connection rather than a new client setup.</aside>
<p>An IT lead gets the same request from three teams in one week. Support wants Zendesk in Claude. Sales wants Salesforce in ChatGPT, and engineering wants Jira in both. Answered one at a time, that is four setups, three permission models and three places to check when someone leaves.</p>
<p>This guide shows how to connect company apps to Claude and ChatGPT once, for the whole company. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected account through one organization-wide endpoint, the web address a client calls. People sign in to it with OAuth, the standard that gives a client a revocable grant instead of a password.</p>
<h2 id="how-do-you-connect-company-apps-to-claude-and-chatgpt-at-once">How do you connect company apps to Claude and ChatGPT at once?</h2>
<p>Connect each account once in Elaichi, share it, and add one address to each AI client. All of your apps then reach both clients in one pass. Work in this order: accounts first, sharing second, clients last.</p>
<ol>
<li>Connect each account, such as Slack, Jira and Salesforce, once in Elaichi.</li>
<li>Share each connection, or a toolbox built from it, with the people who need it.</li>
<li>Bring people into the organization with a role already set.</li>
<li>Add <code>https://api.elaichi.ai/mcp</code> once in Claude and once in ChatGPT.</li>
<li>Sign in as one member, run a read in each app, and check the audit trail.</li>
</ol>
<p>The same address serves Claude, ChatGPT, Cursor and any MCP client. Adding Cursor later is the same work. Under the default consent choice, a new app needs no change in any client.</p>
<h2 id="can-google-workspace-slack-jira-and-salesforce-reach-claude-for-the-whole-company">Can Google Workspace, Slack, Jira and Salesforce reach Claude for the whole company?</h2>
<p>Yes. Each is a connector in Elaichi's catalog. Google Workspace arrives as several: <a href="/connectors/gmail/">Gmail</a>, <a href="/connectors/googledrive/">Google Drive</a>, <a href="/connectors/googlecalendar/">Google Calendar</a> and <a href="/connectors/googledocs/">Google Docs</a>. A separate <a href="/connectors/googleworkspace/">Google Workspace connector</a> covers directory users and groups. <a href="/connectors/slack/">Slack</a>, <a href="/connectors/jira/">Jira</a> and <a href="/connectors/salesforce/">Salesforce</a> are one connector each.</p>
<p>Decide, per app, whose account each connection is. A connection runs on the credential of the person who connected it. Every call through a shared connection therefore reaches the app as that one account.</p>
<p>That suits a team account, such as a Jira site connected by its admin. It does not suit an inbox, or a CRM where each person's own permissions matter. For Gmail and Salesforce, each person connects their own account, once. <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Each rep's own Salesforce access</a> shows that pattern in full.</p>
<p>Connecting can start inside either client. The chat shows a one-time link with no token in it, so the link exposes no secret.</p>
<h2 id="do-you-have-to-build-or-run-an-mcp-server-for-each-app">Do you have to build or run an MCP server for each app?</h2>
<p>No. Elaichi authors, maintains and serves most of its 600+ connectors from its own infrastructure, and the rest are app vendors' own MCP servers, so the company runs no MCP server, hosted or local.</p>
<p>Running your own is real work. Under the MCP specification's local transport, the client launches the server as a subprocess on the person's machine (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports">MCP transports</a>). Multiply that by every app and every laptop, and someone installs, updates and secures each copy. A remote server spares the laptops, but somebody still hosts one per app.</p>
<p>App credentials stay out of the clients and out of Elaichi's organization store. Secrets live in a separate credential service, which encrypts them at rest and refreshes the tokens. If a refresh fails, the connection becomes <code>needs_reauth</code>. That is one account to reconnect, not silent failures in fifty chats.</p>
<p>When the catalog lacks an app, a custom connector is authored from JSON config. Creating one needs the <code>connector:create</code> permission, which Elaichi flags as high trust. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">Running MCP servers yourself</a> compares the two shapes in depth.</p>
<h2 id="how-do-connected-accounts-become-tools-in-a-toolbox">How do connected accounts become tools in a toolbox?</h2>
<p>On their own at first, and on purpose when you need limits. Every connection a person holds <code>use</code> on joins their "All my tools" set as soon as it exists. There is no build step.</p>
<p>A toolbox is a saved set of tools from one or more connections, shared with a team. It earns its place in two cases. The first is a fixed argument, such as the one Slack channel a team may post to. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. The second is delegation. A team runs tools through the toolbox without being able to open, see or reshare the connection behind it.</p>
<p>What a person may call is still decided by restrictions, rules about which connectors and which individual tools a target may reach. Write them against roles before anyone signs in. A change takes about two minutes to apply, so test after that window. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking one tool argument</a> walks through a frozen toolbox entry.</p>
<h2 id="how-do-you-share-one-setup-so-nobody-else-has-to-configure-it">How do you share one setup so nobody else has to configure it?</h2>
<p>Share the connection or the toolbox, and let people join with a role already set. Sharing in Elaichi is a grant of view, use or edit on a resource. It goes to one person, a team or the whole organization, and <code>use</code> lets the grantee run tools through it.</p>
<p>A member sees only what they own or what was shared with them. No org-level permission widens that view, for owners and admins as well.</p>
<p>People join in four ways. An emailed invite link can carry a role and teams. A verified email domain can auto-join new people with a default role. SCIM, a standard for syncing users from a directory, provisions them, and single sign-on can add them on first sign-in. Each member holds exactly one role, so choose the default with care.</p>
<p>What remains for each person is small but real. They connect the connector their admin added, and sign in once. They paste no URL, token or client ID. Under "All my tools", an account shared with them later reaches their client with no new step.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Check that every app on your list is in Elaichi's catalog before you plan the rollout. Each connector page lists its tools.</p><a href="/connectors/" class="cta-button">Browse the connector catalog</a></aside>
<h2 id="where-do-you-add-elaichis-one-address-in-claude-and-chatgpt">Where do you add Elaichi's one address in Claude and ChatGPT?</h2>
<p>Once, in each client's admin settings, as a custom connector or a custom app. The address is <code>https://api.elaichi.ai/mcp</code> for every organization, with no trailing slash. Nobody enters a client ID or secret. Claude registers itself through OAuth dynamic client registration (<a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>).</p>
<p>In Claude Team and Enterprise, an Owner adds it under Organization settings, then Connectors. Members then connect it under Customize, then Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's custom connector guide</a>, as of October 2026). Pro and Max users add it themselves. <a href="/blog/connect-elaichi-to-claude/">The Claude walkthrough</a> has every click.</p>
<p>In ChatGPT, full MCP with write actions is rolling out in beta to Business, Enterprise and Edu (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's developer mode guide</a>, as of October 2026). An admin creates one app under Workspace settings, then Apps, runs Scan Tools and publishes it. Members find it in their Apps settings, labeled custom. <a href="/blog/connect-elaichi-to-chatgpt/">Setting Elaichi up in ChatGPT</a> covers the plan details.</p>
<p>One ChatGPT app covers twenty apps or two hundred. In Elaichi, connected tools are never listed one by one, however few there are. The client sees <code>search_tools</code> and <code>execute_tool</code>, which reach every connected app. A new app is a new connection in Elaichi, not a new app in ChatGPT.</p>
<p>Connect at least one account the admin can use before running Scan Tools. Those two tools appear only while at least one connected tool is reachable, and the scanning admin's own grant decides that.</p>
<h2 id="what-does-each-person-see-at-sign-in-and-consent">What does each person see at sign-in and consent?</h2>
<p>Elaichi's sign-in, then a consent screen with an organization picker and up to four checkboxes. Someone not yet signed in to Elaichi signs in first. If the company enforces SSO for its email domain, other sign-in methods are refused.</p>
<p>A person in one organization finds it preselected. The checkboxes are:</p>
<ul>
<li>Read your organization's data</li>
<li>Create and change data</li>
<li>Run your connected tools</li>
<li>Delete data and remove access</li>
</ul>
<p>Everything the client requested starts ticked except delete, which never does. With "Run your connected tools" ticked, a second step offers "All my tools", the default, or "Only the ones I pick", up to 50 toolboxes. Continue stays disabled until an organization is picked, its plan is active and at least one box is ticked.</p>
<p>Each grant belongs to one person. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so a leaver's next call from either client fails.</p>
<h2 id="how-do-you-check-that-every-app-reached-every-client">How do you check that every app reached every client?</h2>
<p>Sign in as an ordinary member with the default role, and run one read per app. Most people will hold that role, so it is the view that matters.</p>
<ol>
<li>The client's tool list shows <code>search_tools</code> and <code>execute_tool</code>. If both are missing, no connected tool is reachable. The usual causes are a connection that is absent, <code>pending</code> or <code>needs_reauth</code>, a grant without "Run your connected tools", or a role without <code>tool:execute</code>.</li>
<li>Ask for one read per app, such as today's calendar or an open Jira issue. A search naming an app the person never connected returns nothing, plus a line naming up to six apps they can reach.</li>
<li>Open the audit trail. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account each call reached. Each entry records the surface, <code>mcp</code> for a remote client, and the OAuth client the call came through. Claude, ChatGPT and Cursor are named and marked verified.</li>
<li>In Elaichi, Settings, then Connected apps lists the person's client. That is also where they disconnect it.</li>
</ol>
<p>If a tool is missing, <a href="/blog/mcp-tools-not-showing/">the missing-tools checklist</a> walks the checks in order. If sign-in fails, <a href="/blog/mcp-oauth-errors/">the OAuth error guide</a> names the broken step.</p>
<h2 id="when-is-a-clients-own-connector-enough-without-elaichi">When is a client's own connector enough without Elaichi?</h2>
<p>When one person needs one app. A person reading one app through the client's own connector needs nothing more, and a second vendor adds cost without adding control.</p>
<p>The case changes with the second app, the second team or the first contractor. At that point you have several permission models, and no one place to end a person's access. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals in detail.</p>
<p>Cost is the other honest limit. Elaichi's Gold plan lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows your region's price. Auditor, Guest and Billing Admin seats are not billed. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Start the trial, connect your first account, and add the address to Claude and ChatGPT the same day.</p><a href="/pricing/" class="cta-button">See pricing</a></aside>
<p>Engineers on Cursor use the same address, as <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">the Cursor rollout</a> shows. To plan which team goes first, start from <a href="/use-cases/">the use-cases directory</a>. If nobody has the time to set it up, <a href="/services/">forward deployed engineers</a> can do it with you.</p>
<h2>FAQ</h2><dl><dt><strong>Can one setup connect 20 or more SaaS apps to ChatGPT Enterprise?</strong></dt><dd>Yes, with Elaichi. A ChatGPT Enterprise admin creates one custom app from Elaichi's address and publishes it to the workspace. Every app the company connects in Elaichi is reached through that one app, because connected tools are found through two tools, search_tools and execute_tool. Adding a twenty-first app is a new connection in Elaichi, not a new app in ChatGPT.</dd><dt><strong>Does Elaichi host the MCP servers, or do we run them?</strong></dt><dd>Neither is on you. Elaichi authors, maintains and serves most of its connectors from its own infrastructure, and the rest are app vendors' own MCP servers that Elaichi governs, so a company runs no MCP server for any app. A separate credential service holds each connected account's secrets, encrypted at rest, and refreshes their tokens. When the catalog lacks an app, a custom connector can be authored from JSON config.</dd><dt><strong>Does each employee have to configure anything for Claude or ChatGPT?</strong></dt><dd>Very little. An admin adds Elaichi's address once in each client, and the apps are shared in Elaichi. Each employee then connects the connector in their own client and signs in with OAuth once. Nobody pastes a URL, an API token or a client ID, and apps shared with them later need no new step.</dd><dt><strong>How much does a company-wide Elaichi rollout cost?</strong></dt><dd>Elaichi's Gold plan lists at $15 per user per month in USD, or $120 per user per year, and elaichi.ai/pricing shows the price in your region. Auditor, Guest and Billing Admin seats are not billed. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Connect Elaichi to Claude Code</title>
      <link>https://elaichi.ai/blog/connect-elaichi-to-claude-code/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-elaichi-to-claude-code/</guid>
      <description>To connect Elaichi to Claude Code, run one claude mcp add command and sign in with OAuth. The entry holds no secret, so a project .mcp.json is safe to commit.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to Claude Code, add https://api.elaichi.ai/mcp as a remote HTTP server with claude mcp add, then sign in from /mcp in the browser. The entry is a URL with no key or header, so a checked-in .mcp.json gives every engineer the same address while each one signs in as themselves. After that, the engineer's Elaichi role, what is shared with them and any restrictions decide which Jira, Slack and other tools Claude Code can call.</aside>
<p>Claude Code is Anthropic's coding agent for the terminal. Give it a bug, and it reads the Jira issue, searches Slack and edits code over dozens of steps. Each step that reaches a company app needs a credential. The usual answer is a personal token pasted into a config file, one per app, per engineer. One endpoint behind OAuth replaces those tokens.</p>
<h2 id="how-do-you-connect-elaichi-to-claude-code">How do you connect Elaichi to Claude Code?</h2>
<p>Run one <code>claude mcp add</code> command with Elaichi's endpoint, <code>https://api.elaichi.ai/mcp</code>, then sign in from Claude Code in your browser. That is the whole job to connect Elaichi to Claude Code. There is no API key, no header and no server to run.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Its <a href="https://modelcontextprotocol.io/specification/2026-07-28">specification</a> is open for anyone to read. Elaichi exposes all connected SaaS accounts at one organization-wide address, <code>POST /mcp</code>, protected by OAuth.</p>
<h2 id="which-command-adds-elaichi-to-claude-code">Which command adds Elaichi to Claude Code?</h2>
<p><code>claude mcp add</code> with the HTTP transport, a name and the URL. Anthropic's docs give the form <code>claude mcp add --transport http &#x3C;name> &#x3C;url></code> (<a href="https://code.claude.com/docs/en/mcp">Claude Code MCP docs</a>, checked October 2026). For Elaichi, at user scope:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#D7B46A">claude</span><span style="color:#7BC496"> mcp</span><span style="color:#7BC496"> add</span><span style="color:#7BC496"> --transport</span><span style="color:#7BC496"> http</span><span style="color:#7BC496"> elaichi</span><span style="color:#7BC496"> --scope</span><span style="color:#7BC496"> user</span><span style="color:#7BC496"> https://api.elaichi.ai/mcp</span></span></code></pre>
<p>Leave out <code>--header</code>. Elaichi does not take a bearer token you paste. Copy the URL exactly, with no trailing slash and on the <code>api</code> host. With a trailing slash the endpoint returns 404, and on <code>app.elaichi.ai</code> it returns 405. Neither starts sign-in.</p>
<h2 id="should-elaichi-live-at-user-project-or-local-scope">Should Elaichi live at user, project or local scope?</h2>
<p>User scope for one engineer, project scope for a team. Claude Code stores a local or user server in <code>~/.claude.json</code>, and a project server in <code>.mcp.json</code> at the repository root. Local is the default and loads in one project only. User scope loads in all your projects. Project scope is shared through version control.</p>
<p>A project entry for Elaichi looks like this:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">  "</span><span style="color:#D7B46A">mcpServers</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">    "</span><span style="color:#D7B46A">elaichi</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">type</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">http</span><span style="color:#928D84">"</span><span style="color:#928D84">,</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">url</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">  }</span></span>
<span class="line"><span style="color:#928D84">}</span></span></code></pre>
<p>That file is safe to commit, because it holds no secret. Every clone carries the same address, and each engineer still signs in as themselves. In interactive sessions, Claude Code asks each engineer to approve a project server from <code>.mcp.json</code> before it connects. In <code>claude -p</code> runs, Agent SDK sessions and cloud sessions it cannot show that prompt, and the docs say it "loads project-scoped servers without asking". The entry holds no secret, so loading it exposes no credential.</p>
<p>A platform lead can pin the requested scopes in the same file with Claude Code's <code>oauth.scopes</code> field. Add <code>"oauth": { "scopes": "mcp:read mcp:write mcp:tools" }</code> to the entry, and Claude Code asks for those scopes instead of the ones Elaichi's metadata lists. Treat that pin as a default, not a ceiling. Claude Code's precedence runs local, then project, then user, and it uses the whole entry from the highest source with no merging. An engineer who adds a local <code>elaichi</code> entry replaces the project one. To hold deletes back reliably, restrict the delete tools in Elaichi. That binds whichever entry an engineer uses.</p>
<h2 id="what-happens-when-an-engineer-signs-in">What happens when an engineer signs in?</h2>
<p>Claude Code opens Elaichi's sign-in in the browser, and the engineer approves a consent screen. Start it with <code>/mcp</code> inside a session, or with <code>claude mcp login elaichi</code> from the shell. Over SSH, <code>claude mcp login</code> prints the URL instead, and <code>--no-browser</code> forces that.</p>
<p>Sign-in needs a browser. Claude Code running headless in CI, or in a terminal with no access to a browser, cannot complete Elaichi's OAuth sign-in. Connect from a machine where the engineer can open the browser, and do not plan on unattended CI runs.</p>
<p>Claude Code registers itself through dynamic client registration (<a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>), which Elaichi supports, so there is no client ID to enter. It picks a random local port for the callback each time. Elaichi checks the callback address exactly, except that a loopback address may change its port. That is the rule <a href="https://www.rfc-editor.org/rfc/rfc8252">RFC 8252</a> sets for native apps.</p>
<p>On Elaichi's consent screen, the engineer picks one organization. Then come up to four checkboxes: read data, create and change data, run connected tools, and delete data. Everything requested starts ticked except delete, which never does. Keep <strong>Run your connected tools</strong> ticked, or the agent reaches no connected app. The request lasts 30 minutes and works once.</p>
<h2 id="how-do-you-confirm-claude-code-can-see-the-tools">How do you confirm Claude Code can see the tools?</h2>
<p>Check the server first, then ask for one read. <code>claude mcp list</code> shows a health status beside each server, such as Connected or Needs authentication. <code>claude mcp get elaichi</code> shows one server's details, and <code>/mcp</code> shows the same inside a session.</p>
<p>Expect a short tool list. In Elaichi, connected tools are never listed one by one, however few there are. Claude Code calls <code>search_tools</code> to find a connected tool, then <code>execute_tool</code> to run it. Those two, plus any Elaichi operations the engineer's role and grant allow, are the whole list.</p>
<p>Then ask a real question, such as "List my open Jira issues". If the list is empty or an app is missing, <a href="/blog/mcp-tools-not-showing/">the missing-tools checklist</a> walks the causes in order.</p>
<h2 id="how-do-jira-slack-and-github-reach-claude-code">How do Jira, Slack and GitHub reach Claude Code?</h2>
<p>Jira and Slack go through Elaichi, and GitHub does not. An admin or engineer connects each SaaS account once, from a catalog of 600+ connectors, most of them authored by Elaichi. A shared Jira connection reaches Jira as the account that connected it. Elaichi's role, restrictions and audit trail are per engineer. Where Jira's own permissions and log must be the engineer's, each engineer connects their own account once. A separate credential service holds each account's secrets, encrypted at rest, so no Jira or Slack token sits in a dotfile.</p>
<p>GitHub is not in Elaichi's <a href="/connectors/">connector catalog</a>. GitHub runs its own remote server at <code>https://api.githubcopilot.com/mcp</code>. <a href="https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-claude.md">GitHub's guide for Claude Code</a> (checked October 2026) adds that server with a personal access token in a header. That one token stays on the laptop, and calls to it do not pass through Elaichi's restrictions or audit trail. The other route is an Elaichi custom connector, which needs the high-trust <code>connector:create</code> permission.</p>
<p>The <a href="/connectors/jira/">Jira connector</a> and the <a href="/connectors/slack/">Slack connector</a> list every tool a rule can name.</p>
<h2 id="can-one-url-serve-claude-chatgpt-cursor-and-claude-code">Can one URL serve Claude, ChatGPT, Cursor and Claude Code?</h2>
<p>Yes. Elaichi's endpoint is one address for every member, and clients point at it and sign in: Claude, ChatGPT, Cursor and any MCP client. An admin adds it once where a client allows, and each person connects it there and signs in with their own grant.</p>
<p>Claude Code has a shortcut for people who already use Claude. Anthropic's docs say connectors added in claude.ai are available automatically in Claude Code when you log in with a claude.ai account (<a href="https://code.claude.com/docs/en/mcp#use-mcp-servers-from-claude-ai">using claude.ai connectors in Claude Code</a>). So Elaichi, added as a custom connector in Claude, can appear in <code>/mcp</code> with no command at all. That works only with a claude.ai subscription login, not with an API key or a cloud provider. A server you add yourself with the same URL takes precedence, and <code>/mcp</code> then lists the connector as hidden.</p>
<p><a href="/blog/connect-elaichi-to-claude/">The Claude setup</a> and <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">the Cursor setup</a> use the same address unchanged.</p>
<h2 id="what-do-restrictions-and-the-audit-log-add-for-claude-code">What do restrictions and the audit log add for Claude Code?</h2>
<p>Elaichi checks every call against the engineer's role, shares and restrictions, whatever approval mode Claude Code runs in. Restrictions decide which connectors and which individual tools a target may reach, and the audit trail names the engineer and the account each call reached. Claude Code's settings-file permission rules cannot tell a Jira read from a Jira delete, because every connected tool runs through one tool name, <code>execute_tool</code>. Only a deny rule passed on the command line can name one tool. <a href="/blog/coding-agents-company-tools/">MCP for coding agents across an engineering org</a> makes the full argument, including frozen arguments and how to tell which agent made a call. A restriction change takes about two minutes to apply.</p>
<h2 id="how-do-you-disconnect-claude-code-from-elaichi">How do you disconnect Claude Code from Elaichi?</h2>
<p>Remove it in Claude Code, then end the grant in Elaichi. <code>claude mcp logout elaichi</code> clears the credentials Claude Code stores. To be sure the grant has ended in Elaichi, disconnect it in <strong>Settings</strong>, under <strong>Connected apps</strong>. When an admin removes or suspends a member, removing or suspending a member revokes every live grant in the same transaction as the membership change, so that engineer's next call fails.</p>
<h2 id="what-goes-wrong-most-often-and-how-do-you-fix-it">What goes wrong most often, and how do you fix it?</h2>
<p>Most failures are the URL, an expired request or a missing checkbox. Each has a quick fix:</p>
<ul>
<li><strong>Sign-in never opens.</strong> Check the URL for a trailing slash or the <code>app</code> host. In CI or a terminal with no browser access, sign-in cannot finish at all, so connect from a machine with a browser.</li>
<li><strong>The consent screen says the request is no longer valid.</strong> It expired or was used. Run <code>/mcp</code> again.</li>
<li><strong>A tool error names a checkbox.</strong> Elaichi answers with an error telling the engineer to reconnect and allow it. Run <code>claude mcp logout elaichi</code>, then <code>claude mcp login elaichi</code>, and tick the box. If you pinned scopes, add the missing one to <code>oauth.scopes</code> first.</li>
<li><strong>The list is empty for everyone in a role.</strong> The role may lack <code>tool:execute</code>, which an admin fixes.</li>
<li><strong>A 429 mid-task.</strong> Elaichi allows 120 MCP requests a minute per token. Wait a minute.</li>
</ul>
<p><a href="/blog/mcp-oauth-errors/">What each OAuth error means</a> covers the rest, with who fixes each one.</p>
<h2 id="when-is-elaichi-more-than-a-claude-code-user-needs">When is Elaichi more than a Claude Code user needs?</h2>
<p>When one engineer uses Claude Code against one app they own. That app's own MCP server, signed in with OAuth, is enough. Revisit when a second app arrives, a contractor joins, or someone asks which agent changed a ticket. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals.</p>
<p>Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows your region's price. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. For the wider picture, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>, or pick a first app from the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can one MCP server URL work in Claude, ChatGPT, Cursor and Claude Code?</strong></dt><dd>Yes, with Elaichi. Its endpoint, https://api.elaichi.ai/mcp, is the same for every client and every member of the organization. Each client adds it once, and each person signs in with their own OAuth grant, so the address never changes and only the grant behind it differs.</dd><dt><strong>How do I connect Claude Code to Jira and Slack for a whole engineering team?</strong></dt><dd>Connect Jira and Slack once in Elaichi, then point every engineer's Claude Code at Elaichi's endpoint. Each engineer signs in as themselves, so their Elaichi role, what is shared with them and any restrictions decide what their agent can call. A shared Jira connection reaches Jira as the account that connected it. Where Jira's own permissions and log must be the engineer's, each engineer connects their own account once. GitHub is not in Elaichi's connector catalog, so GitHub's own MCP server sits beside Elaichi or a custom connector fills the gap.</dd><dt><strong>How do you give AI agents access to SaaS apps without a shared service account?</strong></dt><dd>Give each person their own OAuth grant to one endpoint instead of one account that everybody's agent uses. With Elaichi, the grant of the person who signed in authorizes every call, the audit trail names that person, and removing them ends that grant without touching anyone else's access. Where the app itself must see the engineer, each engineer connects their own account.</dd><dt><strong>Is it safe to commit an Elaichi entry to .mcp.json?</strong></dt><dd>Yes. The entry holds a public URL and nothing else: no token, no header and no client secret. In interactive sessions, Claude Code asks each engineer to approve a project server before it connects. In claude -p runs, Agent SDK sessions and cloud sessions, it loads project-scoped servers without asking. Either way the entry exposes no credential, and each engineer signs in as themselves.</dd><dt><strong>Why does Claude Code show only a few Elaichi tools?</strong></dt><dd>In Elaichi, connected tools are never listed one by one, however few there are. Claude Code calls search_tools to find a connected tool, then execute_tool to run it. The /mcp list therefore stays short by design, and a short list is not a broken connection.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Connect Elaichi to Codex</title>
      <link>https://elaichi.ai/blog/connect-elaichi-to-codex/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-elaichi-to-codex/</guid>
      <description>To connect Elaichi to Codex, add one URL as a streamable HTTP server and run codex mcp login. No token, no header, and each engineer signs in as themselves.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to Codex, add https://api.elaichi.ai/mcp as a streamable HTTP MCP server, with codex mcp add or in config.toml, then run codex mcp login and finish the sign-in in a browser. The entry holds a URL and no secret, and the Codex CLI, the IDE extension and the ChatGPT desktop app share it. After sign-in, the engineer's Elaichi role, what is shared with them and any restrictions decide which Jira, Slack and other tools Codex can call.</aside>
<p>Codex is OpenAI's coding agent. It runs in a terminal, in an editor and in the ChatGPT desktop app. Hand it a bug, and it wants the Jira issue, the Sentry error and the Slack thread. Each of those needs a credential. The quick fix is a personal token in an environment variable, one per app, per engineer. One endpoint behind OAuth replaces those tokens.</p>
<h2 id="how-do-you-connect-elaichi-to-codex">How do you connect Elaichi to Codex?</h2>
<p>Add Elaichi's endpoint, <code>https://api.elaichi.ai/mcp</code>, to Codex as a streamable HTTP server, then run <code>codex mcp login elaichi</code> and sign in in the browser. There is no API key, no header and no server to run.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Its <a href="https://modelcontextprotocol.io/specification/2026-07-28">specification</a> is public. Elaichi serves every connected SaaS account at one organization-wide address, behind OAuth (a sign-in that issues a revocable grant instead of a copied secret).</p>
<h2 id="which-codex-command-adds-the-elaichi-endpoint">Which Codex command adds the Elaichi endpoint?</h2>
<p><code>codex mcp add</code> with a name and <code>--url</code>. OpenAI's command reference says <code>add</code> registers "a server using a stdio launcher command or a streamable HTTP URL" (<a href="https://learn.chatgpt.com/docs/developer-commands?surface=cli">Codex command line options</a>, checked October 2026). For Elaichi:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#D7B46A">codex</span><span style="color:#7BC496"> mcp</span><span style="color:#7BC496"> add</span><span style="color:#7BC496"> elaichi</span><span style="color:#7BC496"> --url</span><span style="color:#7BC496"> https://api.elaichi.ai/mcp</span></span></code></pre>
<p>Leave out <code>--bearer-token-env-var</code> and <code>--oauth-client-id</code>. Elaichi takes no pasted token and needs no client ID. Copy the URL exactly, with no trailing slash and on the <code>api</code> host. With a trailing slash the endpoint returns 404, and on <code>app.elaichi.ai</code> it returns 405. Neither starts sign-in.</p>
<h2 id="how-do-you-add-elaichi-in-configtoml-or-the-ide-extension">How do you add Elaichi in config.toml or the IDE extension?</h2>
<p>Write one <code>[mcp_servers.elaichi]</code> table, or use the extension's form. Codex keeps MCP servers in <code>~/.codex/config.toml</code>, and a project can scope one in <code>.codex/config.toml</code>, for trusted projects only (<a href="https://learn.chatgpt.com/docs/extend/mcp?surface=cli">Codex MCP docs</a>, checked October 2026). The entry is two lines:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">[</span><span style="color:#E6E1D8">mcp_servers.elaichi</span><span style="color:#928D84">]</span></span>
<span class="line"><span style="color:#E6E1D8">url </span><span style="color:#928D84">=</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span></span></code></pre>
<p>The docs say the ChatGPT desktop app, the Codex CLI and the IDE extension share this configuration. Add Elaichi once, and all three see it.</p>
<p>In the IDE extension, open the gear menu, then <strong>MCP servers</strong>, then <strong>Add server</strong>. Enter <code>elaichi</code>, choose <strong>Streamable HTTP</strong>, paste the URL, save, and select <strong>Restart extension</strong>. The list then marks servers that need OAuth, and <strong>Authenticate</strong> starts the sign-in.</p>
<p>A project file holding only this entry is safe to commit, because it carries no secret. Every clone gets the same address, and each engineer still signs in as themselves.</p>
<h2 id="what-happens-when-you-run-codex-mcp-login">What happens when you run codex mcp login?</h2>
<p>Codex opens Elaichi's sign-in in the browser, and the engineer approves a consent screen. OpenAI's docs say to run <code>codex mcp login &#x3C;server-name></code> "to start an MCP OAuth login". Without it, Codex can connect with no credential at all, and Elaichi answers that request with a sign-in challenge.</p>
<p>Codex registers itself through dynamic client registration (<a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>), which Elaichi supports, so there is no client ID to enter. Its callback listens on <code>127.0.0.1</code>. Elaichi checks the callback address exactly, except that a loopback address may change its port. <a href="https://www.rfc-editor.org/rfc/rfc8252#section-7.3">RFC 8252</a> sets that rule for native apps.</p>
<p>Codex asks for the scopes the server advertises, and Elaichi advertises all of its MCP scopes. The consent screen still holds deletes back. The engineer picks one organization, then sees up to four boxes: read data, create and change data, run connected tools, and delete data. Everything requested starts ticked except delete. Keep <strong>Run your connected tools</strong> ticked, or Codex reaches no connected app. The request lasts 30 minutes and works once.</p>
<p>Sign-in needs a browser. Codex running headless in CI, or in a terminal with no browser access, cannot complete Elaichi's sign-in. Sign in from a machine where the engineer can open a browser.</p>
<h2 id="how-do-you-check-that-codex-can-see-elaichis-tools">How do you check that Codex can see Elaichi's tools?</h2>
<p>List the server, then ask for one read. <code>codex mcp list</code> shows configured servers, and <code>codex mcp get elaichi</code> shows one entry. Inside the <code>codex</code> TUI, <code>/mcp</code> shows the active servers.</p>
<p>Expect a short tool list. In Elaichi, connected tools are never listed one by one, however few there are. Codex calls <code>search_tools</code> to find a connected tool, then <code>execute_tool</code> to run it. Those two, plus any Elaichi operations the engineer's role and grant allow, make up the list.</p>
<p>Then ask a real question, such as "Summarize my open Jira issues". If the list is empty or an app is missing, <a href="/blog/mcp-tools-not-showing/">the missing-tools checklist</a> walks the causes in order.</p>
<h2 id="which-codex-approval-setting-fits-elaichi">Which Codex approval setting fits Elaichi?</h2>
<p>Use Codex's settings for prompts, and Elaichi's restrictions for what Codex may reach. Codex sets approvals per server with <code>default_tools_approval_mode</code>, which takes <code>auto</code>, <code>prompt</code>, <code>writes</code> or <code>approve</code>. The docs say <code>writes</code> "prompts for tools that aren't marked read-only".</p>
<p>Elaichi marks <code>search_tools</code> read-only and marks <code>execute_tool</code> as destructive, because its real effect depends on the tool it runs. Under <code>writes</code>, a search runs freely, and every call into a connected app prompts, reads included.</p>
<p>Codex's <code>enabled_tools</code> and <code>disabled_tools</code> lists name tools too. Every connected Elaichi tool arrives through <code>execute_tool</code>, so those lists cannot tell a Jira read from a Jira delete. Elaichi's restrictions can, and they bind whichever client the engineer uses.</p>
<h2 id="what-do-roles-restrictions-and-the-audit-log-add-for-codex">What do roles, restrictions and the audit log add for Codex?</h2>
<p>Elaichi checks every Codex call against the engineer's role, shares and restrictions, whatever approval mode Codex runs in. The role must carry <code>tool:execute</code>, which gates the whole endpoint. Restrictions decide which connectors and which individual tools a target may reach. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema, so Codex finds nothing to call. A role or restriction change takes about two minutes to apply.</p>
<p>The audit trail writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), under the engineer who signed in, naming the account the call reached. It keeps the one path argument that names the object, as the target id, and nothing else about the arguments. Each entry also records the OAuth client. Codex CLI signs in through a loopback address, so the trail shows the name Codex registered with, marked unverified. <a href="/blog/coding-agents-company-tools/">MCP for coding agents across an engineering org</a> covers frozen arguments and the rest of the case.</p>
<h2 id="which-mcp-gateway-works-with-both-codex-and-claude-code">Which MCP gateway works with both Codex and Claude Code?</h2>
<p>Elaichi does, because both clients speak the same remote MCP and the same OAuth sign-in. An engineering team adds one address to each agent, and one set of rules covers both.</p>
<p>That address is the one the rest of the company uses. Clients point at it and sign in: Claude, ChatGPT, Cursor and any MCP client. The setup differs per client, not the URL. <a href="/blog/connect-elaichi-to-claude-code/">The Claude Code setup</a> and <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a> use it unchanged.</p>
<h2 id="where-do-jira-slack-and-github-fit-in-a-codex-setup">Where do Jira, Slack and GitHub fit in a Codex setup?</h2>
<p>Jira and Slack go through Elaichi, and GitHub does not. An admin or engineer connects each SaaS account once, from a catalog of 600+ connectors that Elaichi serves, most of which it writes itself. A separate credential service holds each account's secrets, encrypted at rest, so no Jira or Slack token sits in an environment variable. <a href="/blog/replace-personal-mcp-servers/">Replacing personal MCP servers on laptops</a> covers the cleanup of tokens already out there.</p>
<p>No shared service account is needed. Each engineer's own grant authorizes their calls, and the audit trail names them. A shared Jira connection still reaches Jira as the account that connected it. Where Jira's own permissions must be the engineer's, each engineer connects their own account. The <a href="/connectors/jira/">Jira connector</a> and the <a href="/connectors/slack/">Slack connector</a> list every tool a rule can name.</p>
<p>GitHub is not in Elaichi's <a href="/connectors/">connector catalog</a>. <a href="https://github.com/github/github-mcp-server/blob/main/docs/installation-guides/install-codex.md">GitHub's guide for Codex</a> (checked October 2026) adds GitHub's own server with a personal access token in <code>bearer_token_env_var</code>. Calls to it skip Elaichi's restrictions and audit trail.</p>
<h2 id="what-goes-wrong-when-codex-connects-to-elaichi">What goes wrong when Codex connects to Elaichi?</h2>
<p>Most failures are the URL, an expired request or a missing checkbox. Each has a quick fix:</p>
<ul>
<li><strong>Sign-in never starts.</strong> Check the URL for a trailing slash or the <code>app</code> host. With no browser, sign-in cannot finish.</li>
<li><strong>The consent screen says the request is no longer valid.</strong> It expired or was used. Run <code>codex mcp login elaichi</code> again.</li>
<li><strong>A tool error names a checkbox.</strong> Run <code>codex mcp logout elaichi</code>, then log in again and tick the box.</li>
<li><strong>The list is empty for a whole role.</strong> The role may lack <code>tool:execute</code>, which an admin fixes.</li>
<li><strong>A 429 mid-task.</strong> Elaichi allows 120 MCP requests a minute per token. Wait a minute.</li>
</ul>
<p><a href="/blog/mcp-oauth-errors/">What each OAuth error means</a> covers the rest, with who fixes each one.</p>
<h2 id="how-do-you-disconnect-codex-from-elaichi">How do you disconnect Codex from Elaichi?</h2>
<p>Log out in Codex, then end the grant in Elaichi. <code>codex mcp logout elaichi</code> removes the OAuth credentials Codex stored for the server. To be sure the grant has ended, disconnect it in Elaichi under <strong>Settings</strong>, then <strong>Connected apps</strong>. When an admin removes or suspends a member, removing or suspending a member revokes every live grant in the same transaction as the membership change, so that engineer's next Codex call fails.</p>
<h2 id="when-does-a-codex-user-not-need-elaichi">When does a Codex user not need Elaichi?</h2>
<p>When one engineer uses Codex against one app they own. That app's own MCP server, signed in with OAuth, is enough. Revisit when a second app arrives, a contractor joins, or someone asks which agent changed a ticket. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals.</p>
<p>Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows your region's price. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. For the wider picture, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Is there an MCP gateway that supports Claude Code and Codex for engineering teams?</strong></dt><dd>Elaichi serves one organization-wide MCP endpoint over Streamable HTTP behind OAuth, and both Claude Code and Codex connect to it. Each engineer adds https://api.elaichi.ai/mcp once and signs in as themselves. Roles, restrictions and one audit trail then apply to both agents, because both reach company apps through the same address.</dd><dt><strong>Does one MCP server URL work in Claude, ChatGPT, Cursor, Claude Code and Codex?</strong></dt><dd>Yes, with Elaichi. Its endpoint, https://api.elaichi.ai/mcp, is the same for every client and every member of the organization. Each client adds it once, and each person signs in with their own OAuth grant. The address never changes, and only the grant behind it differs.</dd><dt><strong>How do you give Codex access to SaaS apps without a shared service account?</strong></dt><dd>Point Codex at one endpoint that each engineer signs in to with their own OAuth grant. With Elaichi, that grant authorizes every call, the audit trail names the engineer, and removing the engineer ends the grant without touching anyone else. Where the app itself must see the engineer, each engineer connects their own account once.</dd><dt><strong>Can Codex use Elaichi in CI?</strong></dt><dd>Not unattended. Elaichi's sign-in needs a browser, so a Codex run in CI or in a terminal with no access to a browser cannot complete it. Engineers sign in on their own machines, where a browser can open.</dd><dt><strong>Is it safe to commit an Elaichi entry to .codex/config.toml?</strong></dt><dd>Yes. The entry holds a public URL and nothing else: no token, no header and no client secret. Codex reads a project's .codex/config.toml only in trusted projects, and each engineer still signs in as themselves.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Connect Elaichi to VS Code and Windsurf</title>
      <link>https://elaichi.ai/blog/connect-elaichi-to-vs-code-and-windsurf/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-elaichi-to-vs-code-and-windsurf/</guid>
      <description>To connect Elaichi to VS Code and Windsurf, add one URL to each editor&apos;s MCP config and sign in with OAuth. No personal API keys on any laptop.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to VS Code and Windsurf, add https://api.elaichi.ai/mcp as a remote HTTP server in each editor's MCP config file, then have each engineer sign in through Elaichi's OAuth screen in the browser. The entry holds a URL and nothing else, so no personal API key sits on any laptop. Elaichi's roles, restrictions and audit log then govern what GitHub Copilot agent mode and Windsurf's agent can call, the same way they govern Claude, ChatGPT and Cursor.</aside>
<p>A platform team rarely gets to pick one editor. Half the engineers run GitHub Copilot in agent mode inside VS Code, and the other half run Windsurf. Both agents want Jira, Slack and Sentry. The vendor examples show the usual answer. <a href="https://docs.devin.ai/desktop/cascade/mcp">Windsurf's MCP docs</a> configure a Slack server with a <code>SLACK_BOT_TOKEN</code> in its <code>env</code> block. <a href="https://code.visualstudio.com/docs/agents/reference/mcp-configuration">VS Code's reference</a> shows an <code>Authorization</code> header. Forty engineers and four apps means a lot of tokens in a lot of dotfiles.</p>
<h2 id="how-do-you-connect-elaichi-to-vs-code-and-windsurf-without-personal-api-keys">How do you connect Elaichi to VS Code and Windsurf without personal API keys?</h2>
<p>To connect Elaichi to VS Code and Windsurf, point both editors at one URL, <code>https://api.elaichi.ai/mcp</code>, and have each engineer sign in with OAuth. The config entry holds no key, no header and no client ID. That is how Windsurf and VS Code Copilot reach internal tools without a personal API key on any laptop.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected SaaS account through one organization-wide endpoint, <code>POST /mcp</code>, behind OAuth (a sign-in standard that issues each person a grant instead of a shared password). VS Code Copilot and Windsurf (Devin Desktop) both connect to it.</p>
<p>Sign-in needs a browser. An editor agent or CLI running headless in CI cannot complete it, so plan on interactive use only.</p>
<h2 id="how-do-you-add-elaichi-to-vs-code">How do you add Elaichi to VS Code?</h2>
<p>Run <strong>MCP: Add Server</strong> from the Command Palette, or add one entry by hand. The guided flow offers <strong>.mcp.json</strong>, a portable file at the workspace root, or <strong>Copilot Global</strong>, saved in <code>~/.copilot/mcp-config.json</code> by default. VS Code's docs say to prefer those portable destinations for new servers (<a href="https://code.visualstudio.com/docs/agent-customization/mcp-servers">VS Code MCP servers</a>, checked October 2026).</p>
<p>The portable format keeps servers under <code>mcpServers</code>, and the configuration reference lists two required fields for a remote server, <code>type</code> and <code>url</code>:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">  "</span><span style="color:#D7B46A">mcpServers</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">    "</span><span style="color:#D7B46A">elaichi</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">type</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">http</span><span style="color:#928D84">"</span><span style="color:#928D84">,</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">url</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">  }</span></span>
<span class="line"><span style="color:#928D84">}</span></span></code></pre>
<p>The older <code>.vscode/mcp.json</code> file uses a top-level <code>servers</code> key instead. Leave out <code>headers</code>, and leave out the <code>oauth</code> block too. That block exists to supply a client ID, and Elaichi needs none, because clients register themselves through dynamic client registration (<a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>).</p>
<p>Copy the URL exactly. With a trailing slash the endpoint returns 404, and on <code>app.elaichi.ai</code> it returns 405. Neither starts sign-in. A workspace <code>.mcp.json</code> inherits Workspace Trust, so the server starts once the engineer trusts the repository.</p>
<h2 id="what-does-a-vs-code-engineer-see-at-sign-in">What does a VS Code engineer see at sign-in?</h2>
<p>A browser window opens on Elaichi's sign-in, then its consent screen. VS Code's security page says it "implements the MCP authorization specification" for OAuth between VS Code and outside services (<a href="https://code.visualstudio.com/docs/agents/run/security">VS Code security</a>).</p>
<p>On Elaichi's consent screen, the engineer picks one organization. Then come up to four checkboxes: read data, create and change data, run connected tools, and delete data. Everything requested starts ticked except delete, which never does. Keep <strong>Run your connected tools</strong> ticked, or the agent reaches no connected app. The request lasts 30 minutes and works once.</p>
<p>To confirm, select <strong>Configure Tools</strong> in the chat input. If the server fails to start, run <strong>MCP: List Servers</strong>, pick it and choose <strong>Show Output</strong> for its logs. Expect a short list. In Elaichi, connected tools are never listed one by one, however few there are. Copilot calls <code>search_tools</code> to find a Jira or Slack tool, then <code>execute_tool</code> to run it.</p>
<p>That shape matters for one VS Code limit. A chat request can have at most 128 tools enabled (<a href="https://code.visualstudio.com/docs/agents/run/tools">VS Code tools</a>), and connected apps add nothing to that count. VS Code may also ask the engineer to confirm tool calls. Every connected app runs through <code>execute_tool</code>, so a prompt on it covers every app. Keep the per-tool decisions in Elaichi's restrictions.</p>
<h2 id="how-do-you-add-elaichi-to-windsurf">How do you add Elaichi to Windsurf?</h2>
<p>Add one entry with <code>url</code> to the MCP config file. Windsurf is named Devin Desktop (<a href="https://devin.ai/desktop">Devin Desktop</a>), and it has two agents. Devin Local is the default for new tabs, and Cascade is the legacy agent.</p>
<p>Both agents' docs put the user file at <code>~/.config/devin/mcp_config.json</code>, or <code>%APPDATA%\devin\mcp_config.json</code> on Windows. Cascade accepts <code>serverUrl</code> or <code>url</code> for a remote server (<a href="https://docs.devin.ai/desktop/cascade/mcp">Cascade MCP docs</a>). Devin Local reads the Devin CLI files, where <code>url</code> is the required field (<a href="https://docs.devin.ai/cli/extensibility/mcp/configuration">Devin CLI MCP configuration</a>). So this entry fits both:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">  "</span><span style="color:#D7B46A">mcpServers</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">    "</span><span style="color:#D7B46A">elaichi</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">url</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">  }</span></span>
<span class="line"><span style="color:#928D84">}</span></span></code></pre>
<p>In Cascade, open the file from the <strong>...</strong> menu at the top right of the Cascade panel, then <strong>Open MCP config file</strong>. For Devin Local, a project's <code>.devin/mcp_config.json</code> is shared through version control. With Devin CLI installed, <code>devin mcp add -s user elaichi https://api.elaichi.ai/mcp</code> writes the user entry for you.</p>
<h2 id="what-does-a-windsurf-engineer-see-at-sign-in">What does a Windsurf engineer see at sign-in?</h2>
<p>The same Elaichi consent screen, opened in the browser. Devin's docs say an OAuth server prompts for sign-in the first time it is used, and <code>devin mcp login elaichi</code> starts it directly. Devin's CLI docs say it registers itself through dynamic client registration, so nobody enters a client ID.</p>
<p>Each editor registers itself and signs in on its own, so an engineer signs in once per editor.</p>
<p>To confirm, open the MCPs section of Cascade's <strong>...</strong> menu, which shows each server and its enabled tool count. With Devin CLI, <code>devin mcp list</code> shows the configured servers. When stored sign-in credentials expire, the Devin Local MCP list shows <strong>Needs auth</strong>, and <strong>Authenticate</strong> runs the browser flow again.</p>
<p>Two Windsurf limits apply. Cascade has a limit of 100 total tools at a time, and Elaichi's connected apps add nothing to it. Devin Local asks for approval before any MCP tool call by default. A permission rule on <code>mcp__elaichi__*</code> covers every connected app at once, because every app runs through <code>execute_tool</code>.</p>
<h2 id="how-do-you-stop-engineers-pasting-personal-api-keys-into-editors">How do you stop engineers pasting personal API keys into editors?</h2>
<p>Give them a config with nothing to paste, then close the side door. A committed <code>.mcp.json</code> and <code>.devin/mcp_config.json</code> each hold a public URL and no secret. Every clone carries the same entry, and each engineer still signs in as themselves.</p>
<p>The app credentials live in Elaichi, not on laptops. A member connects each SaaS account once, from a catalog of 600+ connectors served through Elaichi. A separate credential service holds each account's secrets, encrypted at rest.</p>
<p>Then use each editor's policy so personal servers stop running:</p>
<ul>
<li><strong>VS Code.</strong> The <code>ChatMCP</code> policy can limit MCP servers to a curated registry or turn MCP off. Copilot Business and Enterprise organizations can also set MCP access in GitHub organization settings (<a href="https://code.visualstudio.com/docs/enterprise/manage-ai-settings">VS Code AI settings</a>).</li>
<li><strong>Windsurf.</strong> Once a team admin allowlists one server, every server not on the list is blocked. The allowlist's Server ID must match the entry's key, so name the entry <code>elaichi</code> in every file.</li>
</ul>
<p>Editor policy decides which servers may run. It cannot see inside Elaichi, so it cannot tell a Jira read from a Jira delete. <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth versus API keys for AI agents</a> covers the wider case against long-lived keys, and <a href="/blog/replace-personal-mcp-servers/">replacing personal MCP servers on laptops</a> covers the cleanup.</p>
<h2 id="which-admin-controls-cover-claude-chatgpt-cursor-and-both-editors">Which admin controls cover Claude, ChatGPT, Cursor and both editors?</h2>
<p>Elaichi's, because they sit at the endpoint every client shares. Claude, ChatGPT, Cursor, VS Code and Windsurf all reach the same address, so one set of rules governs them.</p>
<ul>
<li><strong>Roles.</strong> Each member holds exactly one role, and a role without <code>tool:execute</code> reaches no connected tool.</li>
<li><strong>Restrictions.</strong> They decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A change takes about two minutes to apply.</li>
<li><strong>Audit log.</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the engineer and the account the call reached. Each entry records the surface and the OAuth client. VS Code's <code>vscode.dev</code> redirect forwards the code to whatever the request names, so Elaichi cannot verify the client name. Its calls show the name VS Code registered with, marked unverified.</li>
<li><strong>Revocation.</strong> In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so that engineer's next call from either editor fails.</li>
</ul>
<p><a href="/blog/coding-agents-company-tools/">MCP for coding agents across an engineering org</a> goes further into frozen arguments and team rollouts.</p>
<h2 id="which-errors-come-up-most-in-vs-code-and-windsurf">Which errors come up most in VS Code and Windsurf?</h2>
<p>Most failures are the URL, an expired request or a missing checkbox. Each has a quick fix:</p>
<ul>
<li><strong>Sign-in never opens.</strong> Check for a trailing slash or the <code>app</code> host. Devin CLI retries over SSE after a 404 or 405, so a wrong URL there can surface as an SSE error.</li>
<li><strong>The consent screen says the request is no longer valid.</strong> It expired or was used. Start the sign-in again from the editor.</li>
<li><strong>A tool error names a checkbox.</strong> Reconnect and tick it. In Windsurf, run <code>devin mcp logout elaichi</code>, then <code>devin mcp login elaichi</code>.</li>
<li><strong>The list is empty for a whole role.</strong> The role may lack <code>tool:execute</code>, which an admin fixes.</li>
<li><strong>A 429 mid-task.</strong> Elaichi allows 120 MCP requests a minute per token. Wait a minute.</li>
</ul>
<p><a href="/blog/mcp-oauth-errors/">What each OAuth error means</a> lists who fixes each one, and <a href="/blog/mcp-tools-not-showing/">the missing-tools checklist</a> walks an empty list in order.</p>
<h2 id="when-is-elaichi-more-than-an-editor-team-needs">When is Elaichi more than an editor team needs?</h2>
<p>When one engineer uses one app that runs its own OAuth MCP server. That server is enough until a second app, a contractor or an audit question arrives. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals.</p>
<p>GitHub is not in Elaichi's <a href="/connectors/">connector catalog</a>. VS Code's own docs use GitHub's server as their example, and that server sits beside Elaichi, outside its restrictions and audit log.</p>
<p>Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows your region's price. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. The same address works in <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">the Cursor setup</a>, <a href="/blog/connect-elaichi-to-claude-code/">the Claude Code setup</a> and <a href="/blog/connect-elaichi-to-codex/">the Codex setup</a>. For the wider picture, read <a href="/blog/what-is-an-mcp-control-plane/">what an MCP control plane is</a>, or start from the <a href="/connectors/jira/">Jira connector</a> and the <a href="/connectors/slack/">Slack connector</a>.</p>
<h2>FAQ</h2><dl><dt><strong>How do you give Windsurf and VS Code Copilot access to internal tools without personal API keys?</strong></dt><dd>Connect each app once in Elaichi, then point both editors at Elaichi's endpoint, https://api.elaichi.ai/mcp. Each engineer signs in with OAuth in the browser, so the config file holds only a URL. The app credentials stay in Elaichi's credential service, encrypted at rest, and never reach a laptop.</dd><dt><strong>What admin controls does IT get for MCP connectors across Claude, ChatGPT and Cursor?</strong></dt><dd>With Elaichi, one set: roles decide what each person may do, restrictions decide which connectors and individual tools a role or user may reach, and the audit log records each tool call that reaches execution, with the person and the account it reached. All of it applies at the one endpoint every client uses, so Claude, ChatGPT, Cursor, VS Code and Windsurf share the same rules.</dd><dt><strong>How do you stop employees from sharing personal API keys with AI tools?</strong></dt><dd>Remove the reason to have one. Give each AI client a config that holds only an OAuth-protected URL, connect the apps once in a control plane such as Elaichi, and use the client's own policy to stop other servers from running. VS Code has an MCP access policy, and Windsurf has a team allowlist that blocks every server not on it.</dd><dt><strong>Can VS Code or Windsurf use Elaichi in CI?</strong></dt><dd>No. Elaichi's sign-in needs a browser, so an editor agent or CLI running headless in CI cannot complete it. Each engineer signs in from a machine where they can open the browser.</dd><dt><strong>Why do VS Code and Windsurf show only a few Elaichi tools?</strong></dt><dd>In Elaichi, connected tools are never listed one by one, however few there are. The agent finds a connected tool with search_tools and runs it with execute_tool, so a short list is expected. It also means adding Jira, Slack or Sentry adds no tools to the editor's tool count.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Docker MCP Gateway vs a managed MCP platform</title>
      <link>https://elaichi.ai/blog/docker-mcp-gateway-vs-managed-mcp-platform/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/docker-mcp-gateway-vs-managed-mcp-platform/</guid>
      <description>Docker MCP Gateway vs a managed MCP platform: Docker runs MCP servers in containers you operate. Elaichi serves connectors behind one sign-in URL.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Docker's MCP Gateway runs open-source MCP servers as containers on a machine you operate, which suits developers who want local tools with strong isolation. Elaichi is a managed MCP platform: it serves the connectors from its own infrastructure behind one organization-wide URL, and each employee signs in with their own OAuth grant. For a company rollout to support, finance and sales, Elaichi adds roles, restrictions, frozen parameters, one audit log and next-call offboarding. You can run both, split by audience.</aside>
<h2 id="docker-mcp-gateway-vs-a-managed-mcp-platform-which-fits-a-whole-company">Docker MCP Gateway vs a managed MCP platform: which fits a whole company?</h2>
<p>Docker MCP Gateway vs a managed MCP platform comes down to who runs the servers. Docker's gateway runs MCP servers as containers on a machine you operate, usually a developer's laptop. A managed MCP platform such as Elaichi serves the connectors itself, so staff in support, finance and sales connect an AI client and sign in.</p>
<p>The request usually starts in engineering. A few developers switched on Docker's MCP Toolkit and gave Cursor a GitHub tool. It worked, so IT is asked whether the same setup can serve the whole company. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The answer turns on whether the people asking can run containers, and whether you need one record of every call.</p>
<h2 id="what-is-dockers-mcp-gateway-in-dockers-own-words">What is Docker's MCP Gateway, in Docker's own words?</h2>
<p>It is an open source proxy that starts MCP servers in containers and routes client requests to them. Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">MCP Gateway page</a> (checked October 2026) describes it as a centralized proxy that manages configuration, credentials and access control.</p>
<p>Three parts work together, per Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/">MCP Catalog and Toolkit overview</a> (checked October 2026). The MCP Catalog lists 300+ verified servers packaged as container images. The MCP Toolkit is the Docker Desktop interface for adding servers and connecting clients. Underneath, the gateway starts a server's container when a tool is called, injects credentials and forwards the request.</p>
<p>The code is MIT-licensed in the <a href="https://github.com/docker/mcp-gateway">docker/mcp-gateway repository</a>. Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/profiles/">profiles page</a> marks profiles as Early Access on Docker Desktop 4.63 or later, and the Toolkit and Catalog as Beta (both checked October 2026).</p>
<h2 id="where-does-dockers-gateway-run-and-who-keeps-it-running">Where does Docker's gateway run, and who keeps it running?</h2>
<p>It runs wherever Docker runs, and someone on your side operates it. With the MCP Toolkit enabled, it runs in the background in Docker Desktop. On Docker Engine alone, you install the binary yourself (<a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">MCP Gateway docs</a>, checked October 2026).</p>
<p>The default transport is stdio, which is local to the client that launched the gateway. Docker's <a href="https://github.com/docker/mcp-gateway/blob/main/docs/mcp-gateway.md">gateway guide on GitHub</a> also shows it under Docker Compose, serving several clients over HTTP on any Docker engine. Per Docker's <a href="https://github.com/docker/mcp-gateway/blob/main/docs/security.md">security model</a>, those HTTP requests need a Bearer token by default, set in an environment variable or generated (both checked October 2026).</p>
<p>So a company gets two shapes: a gateway on each laptop, or a shared one on a server. The first means one configuration per machine. The second means one token that every client presents.</p>
<h2 id="how-does-dockers-gateway-handle-secrets-and-oauth">How does Docker's gateway handle secrets and OAuth?</h2>
<p>Credentials stay with the Docker installation that runs the gateway. API keys go into Docker Desktop's secrets store, or a local <code>.env</code> file as a fallback. Docker's <a href="https://github.com/docker/mcp-gateway/blob/main/docs/security.md">security model</a> says each server receives only the secrets it declares (checked October 2026).</p>
<p>For apps such as GitHub and Notion, the <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/toolkit/">MCP Toolkit</a> runs OAuth in the browser. It lists authorized services in an OAuth tab, where each one can be revoked. Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/profiles/">profiles page</a> adds two details that matter for a rollout (both checked October 2026). OAuth credentials are shared across all profiles, so a second account means revoking and authorizing again. And a pushed profile carries no credentials, so each teammate configures OAuth after pulling it.</p>
<p>So each person authorizes each service in their own Docker installation, on whichever machine they use.</p>
<h2 id="what-do-profiles-tool-filters-and-call-logs-give-an-admin">What do profiles, tool filters and call logs give an admin?</h2>
<p>They give a developer, or a team sharing a profile, control over which tools are offered. A profile is a named set of servers whose Tools tab can switch single tools on or off. Teammates can pull a profile from an OCI registry (<a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/profiles/">MCP Profiles</a>, checked October 2026).</p>
<p>A custom catalog narrows Docker's list to approved servers and can add private ones (<a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/">MCP Catalog</a>, checked October 2026). Per the <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/toolkit/">MCP Toolkit page</a>, each tool runs in its own container, capped at 1 CPU and 2 GB of memory, with no host files unless the user grants a mount.</p>
<p>Call logging and secret blocking are on by default. Per Docker's <a href="https://github.com/docker/mcp-gateway/blob/main/docs/security.md">security model</a>, the call log holds the tool name and the shape of its arguments, never raw values. Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">gateway page</a> also says the gateway as part of Docker AI Governance is invite-only, through Docker Sales (all checked October 2026). Ask Docker what it adds.</p>
<h2 id="what-does-a-company-wide-rollout-to-non-engineers-need">What does a company-wide rollout to non-engineers need?</h2>
<p>It needs one address, a personal sign-in, nothing to run, and rules an admin sets once. Here is how Elaichi meets each need for Claude, ChatGPT, Cursor and any other MCP client.</p>
<ul>
<li><strong>One URL per organization.</strong> Every client connects to <code>https://api.elaichi.ai/mcp</code>, standard MCP over Streamable HTTP. The client registers itself through OAuth, so nobody types a client ID, secret or token.</li>
<li><strong>A personal sign-in.</strong> Each member connects once and signs in with their own OAuth grant, an access approval that belongs to that person.</li>
<li><strong>Connectors, not containers.</strong> Elaichi serves 600+ connectors, and authors and maintains most of them on its own infrastructure. A separate credential service holds account secrets, encrypted with AES-256-GCM, and owns token refresh.</li>
<li><strong>Roles and restrictions.</strong> Each member holds exactly one role. Restrictions decide which connectors and which individual tools a target may reach, for a role or one user. A change takes effect within about two minutes.</li>
<li><strong>Frozen parameters.</strong> An admin can fix an argument so the model cannot change it. Note that a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</li>
<li><strong>One audit log.</strong> It keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account reached and the AI client used, and stores the one path argument that names the object, as the target id, and nothing else about the arguments.</li>
<li><strong>Offboarding.</strong> Removal or suspension ends access on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</li>
<li><strong>Region.</strong> Pick <code>eu</code>, <code>us</code> or <code>apac</code> when the organization is created; it is fixed afterwards. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region.</li>
</ul>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Frozen arguments on a payment tool</a> show the freeze in practice.</p>
<h2 id="how-do-dockers-gateway-and-elaichi-compare-row-by-row">How do Docker's gateway and Elaichi compare, row by row?</h2>
<p>Docker's gateway gives developers control of local runtimes; Elaichi gives admins control of company-wide access. The Docker column comes from Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/">documentation</a> and its <a href="https://github.com/docker/mcp-gateway">GitHub repository</a>, both checked October 2026.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Docker MCP Gateway</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who operates it</td>
<td>You: Docker Desktop on each machine, or Docker Engine on a server</td>
<td>Elaichi; no server on your side</td>
</tr>
<tr>
<td>Who writes the code</td>
<td>Docker, partners and contributors through its catalog, plus your private servers</td>
<td>Elaichi authors most of its 600+ connectors; vendors write their own MCP servers</td>
</tr>
<tr>
<td>How clients connect</td>
<td>Client config that launches the gateway over stdio, or HTTP with a Bearer token</td>
<td>One URL; each person signs in with OAuth</td>
</tr>
<tr>
<td>Credentials</td>
<td>Docker Desktop secrets or <code>.env</code>; OAuth through the Toolkit, shared across profiles</td>
<td>Separate credential service, AES-256-GCM, owns refresh</td>
</tr>
<tr>
<td>Tool control</td>
<td>Enable or disable tools per profile; custom catalogs</td>
<td>Restrictions per role or user, per connector and tool; frozen parameters</td>
</tr>
<tr>
<td>The record</td>
<td>Call log of tool name and argument shape, on by default</td>
<td>One audit log per organization, naming the account and client</td>
</tr>
<tr>
<td>A leaver</td>
<td>A question to ask Docker</td>
<td>Access ends on the next call</td>
</tr>
<tr>
<td>Isolation</td>
<td>A container per tool, CPU and memory caps, no host files by default</td>
<td>Elaichi runs the connectors it authors on its own infrastructure; a native MCP connector runs on the vendor's server</td>
</tr>
<tr>
<td>Location</td>
<td>Wherever you run Docker</td>
<td><code>eu</code>, <code>us</code> or <code>apac</code>, chosen at creation</td>
</tr>
</tbody>
</table>
<h2 id="managed-mcp-connectors-vs-open-source-mcp-servers-what-changes-for-a-company">Managed MCP connectors vs open-source MCP servers: what changes for a company?</h2>
<p>The difference is who writes, runs and repairs the code. With Docker's catalog, the code comes from many authors and your side runs it. With managed connectors, one vendor writes, runs and repairs them.</p>
<p>Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/">MCP Catalog</a> holds Docker-built local servers, partner servers, and remote servers that run on the provider's infrastructure (checked October 2026). New servers are submitted through Docker's public registry repository on GitHub. That breadth is its strength.</p>
<p>Three things move for a company. Upkeep: an app's API change becomes the connector author's work, not your deploy. Rules: Elaichi pins each rule to the underlying operation, so renaming a tool does not slip it past a restriction. Record: every call that reaches execution lands in one audit log with one shape, whichever connector made it. The trade is that Elaichi, not you, fixes the connectors it authors. You can fork one as a custom connector if you need your own change. <a href="/blog/mcp-registry-vs-first-party-connectors/">Registries and first-party connectors</a> are compared in more depth elsewhere.</p>
<h2 id="is-there-a-hosted-mcp-service-for-all-our-business-apps-so-we-run-nothing">Is there a hosted MCP service for all our business apps, so we run nothing?</h2>
<p>Yes, and that is the job a managed MCP platform does. Elaichi serves 600+ connectors, most of them from its own infrastructure and the rest from their vendors' own MCP servers, so there is no server, container or token to look after.</p>
<p>Check the catalog against your app list first. As of October 2026, GitHub is not in Elaichi's catalog. Jira, Slack, Salesforce and the Google Workspace apps are, and Datadog and Linear are there as their vendors' own MCP servers. For a missing app, use the app's own MCP server, or build a custom connector from JSON config. The <a href="/connectors/">connector catalog</a> shows what is there.</p>
<p>Hosted also means someone else keeps tokens fresh. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The refresh and credential costs</a> are priced in that post.</p>
<h2 id="when-is-dockers-mcp-gateway-the-better-choice">When is Docker's MCP Gateway the better choice?</h2>
<p>Choose Docker's gateway when the users are developers and the tools are local. In these cases Elaichi is the wrong fit, per Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/">catalog</a> and <a href="https://github.com/docker/mcp-gateway/blob/main/docs/mcp-gateway.md">gateway guide</a> (checked October 2026):</p>
<ul>
<li><strong>The tools touch the developer's own machine.</strong> A filesystem, a local database or a browser automation server belongs in an isolated container on that machine. Elaichi is hosted and does not run local tools.</li>
<li><strong>The work stays offline or inside your network.</strong> Docker says its local catalog servers work offline once downloaded.</li>
<li><strong>You want code you can read and run.</strong> Docker's gateway is MIT-licensed open source.</li>
<li><strong>Agents run unattended.</strong> Elaichi's sign-in needs a browser, so a headless agent in CI cannot complete it. Docker's guide shows the gateway under Docker Compose for other services to use.</li>
<li><strong>The app is GitHub.</strong> Docker's catalog lists it, and Elaichi's catalog does not.</li>
</ul>
<h2 id="can-you-run-dockers-gateway-and-elaichi-side-by-side">Can you run Docker's gateway and Elaichi side by side?</h2>
<p>Yes, and the clean split is by audience and by where the tool runs. Developers keep Docker's gateway for local, container-isolated tools. Everyone, developers included, reaches the company's SaaS accounts through Elaichi.</p>
<p>In Cursor, that means two entries: the Docker gateway for local tools, and Elaichi's URL for Jira, Slack and Salesforce. Keep each business app in one place only. If Salesforce is reachable through both, Elaichi's restrictions and audit log miss the path through the laptop. <a href="/blog/replace-personal-mcp-servers/">Finding personal MCP servers on laptops</a> covers the inventory step.</p>
<h2 id="which-questions-should-you-ask-docker-before-a-company-rollout">Which questions should you ask Docker before a company rollout?</h2>
<p>Ask the questions a rollout to non-engineers depends on, and get the answers in writing. Docker's <a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/toolkit/">MCP Toolkit</a> and <a href="https://github.com/docker/mcp-gateway">gateway repository</a> describe developer workflows (checked October 2026). Five questions close the gap:</p>
<ol>
<li>How does an employee without Docker Desktop, on a managed laptop, connect Claude or ChatGPT?</li>
<li>On a shared gateway with one Bearer token, how is each call tied to a named person?</li>
<li>Where does an admin see every call from every machine in one log, and what does Docker AI Governance add?</li>
<li>When someone leaves, how are the OAuth authorizations on their machine revoked, and how fast?</li>
<li>Can a rule fix an argument's value, not only switch a tool on or off?</li>
</ol>
<p>Put the same five to Elaichi. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The full cost of running MCP servers yourself</a> prices the self-run side, <a href="/blog/kong-cloudflare-mcp-gateway-vs-managed-connectors/">cloud API gateways with MCP</a> are another option, and <a href="/use-cases/">team-by-team starting points</a> show where to begin.</p>
<h2>FAQ</h2><dl><dt><strong>Docker MCP Gateway vs a managed MCP platform: which is better for a company?</strong></dt><dd>It depends on who will use it. Docker's MCP Gateway runs MCP servers as containers on a machine you operate, which suits developers who already run Docker Desktop (Docker docs, checked October 2026). A managed MCP platform such as Elaichi serves the connectors itself behind one organization-wide URL, and each employee signs in with their own OAuth grant. For staff in support, finance or sales, Elaichi also gives admins per-tool restrictions, frozen parameters and one audit log. Removing a member cuts their access on the next call.</dd><dt><strong>Should a company use managed MCP connectors or open-source MCP servers?</strong></dt><dd>Use open-source MCP servers when developers need local tools, want to read the code, and can run and patch it themselves. Use managed connectors when many non-engineers need the same SaaS apps. Then one vendor writes, hosts and repairs the connectors, holds the credentials, and records each call that reaches execution in one audit log. Elaichi is a managed option: it authors most of its connectors and governs vendors' own MCP servers for the rest, so nobody at the company runs a server or a container.</dd><dt><strong>Is there a hosted MCP service for all our business apps so we do not have to run servers?</strong></dt><dd>Yes. Elaichi serves its connectors behind one URL, https://api.elaichi.ai/mcp, so there is no server, container or token to host. Claude, ChatGPT, Cursor and any other MCP client connect to it, and each person signs in once. Check the catalog against your app list first: as of October 2026, GitHub is not in it, while Jira, Slack, Salesforce, the Google Workspace apps, and Datadog's and Linear's own MCP servers are.</dd><dt><strong>Can Docker MCP Gateway and Elaichi be used together?</strong></dt><dd>Yes. A clean split gives developers Docker's MCP Gateway for local, container-isolated tools such as a filesystem or a browser automation server, and gives everyone Elaichi for the company's SaaS accounts. Keep each business app in one place only, so restrictions and the audit log cover its calls.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>EU data residency for AI agents, leg by leg</title>
      <link>https://elaichi.ai/blog/eu-data-residency-ai-agents/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/eu-data-residency-ai-agents/</guid>
      <description>EU data residency for AI agents spans three legs: the app, the control plane and the model. Elaichi&apos;s eu region pins the data store and tool calls to the EU.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> EU data residency for AI agents is three separate promises: the SaaS app's hosting region, the control plane's region and the model provider's region. In Elaichi's eu region, the organization's data store and the execution of its org-scoped requests and tool calls are pinned to the EU, and its audit trail is stored there. User accounts, sign-in sessions, API tokens, SSO settings and MCP OAuth token records are kept globally. The model provider and the apps keep their own settings, which Elaichi does not control, so each needs its own answer in your transfer records.</aside>
<p>A support lead in Munich wants Claude on the help desk. A finance team in Dublin wants ChatGPT on the accounting system. The data protection officer asks whether customer data stays in the EU. A US company with EU customers hears the same question in every security review.</p>
<h2 id="what-does-eu-data-residency-for-ai-agents-actually-cover">What does EU data residency for AI agents actually cover?</h2>
<p>EU data residency for AI agents is three promises, made by three different vendors. The SaaS app keeps its records where its vendor hosts them. The control plane between the agent and the app keeps its own records. The model provider processes the prompt and every tool result the agent reads. Each leg has its own region setting, and no single setting covers all three.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi is a governed MCP control plane. Each SaaS account is connected once, and its tools are served through one organization-wide endpoint, the single address every AI client points at: <code>https://api.elaichi.ai/mcp</code>. Claude, ChatGPT, Cursor and any other MCP client all use it. Each member signs in with OAuth, which gives the client a revocable grant instead of a password.</p>
<p>This post describes the mechanism, not the law. For the legal reading, start with the regulation. Chapter V allows a transfer to a third country only when its conditions are met (<a href="https://eur-lex.europa.eu/eli/reg/2016/679/oj">GDPR Article 44, EUR-Lex</a>). Article 28 requires a binding contract with every processor. The European Data Protection Board's <a href="https://www.edpb.europa.eu/our-work-tools/our-documents/recommendations/recommendations-012020-measures-supplement-transfer_en">Recommendations 01/2020</a> cover the measures that supplement transfer tools. A map of the legs is where that work starts.</p>
<h2 id="how-do-we-keep-data-in-the-eu-when-employees-use-ai-agents-on-saas-tools">How do we keep data in the EU when employees use AI agents on SaaS tools?</h2>
<p>Pin each leg separately, then write down the legs you cannot pin. No vendor owns all three legs, so no vendor can do this for you. Work in this order:</p>
<ol>
<li><strong>The app.</strong> Check where each SaaS vendor hosts your tenant. If the help desk tenant sits in the US, no agent setup moves it.</li>
<li><strong>The model provider.</strong> Check which region the AI client offers for prompts, conversations and inference on your plan. Tool results enter the model's context, so whatever the agent reads is processed here.</li>
<li><strong>The control plane.</strong> Choose a vendor whose region covers its own records: who connected what, which rules apply, and the log of each call that reaches execution. In Elaichi, that is the <code>eu</code> region.</li>
<li><strong>The gaps.</strong> List every leg that is not pinned, with the safeguard your lawyers rely on for it. Article 46 names standard contractual clauses as one such safeguard (<a href="https://eur-lex.europa.eu/eli/reg/2016/679/oj">GDPR text</a>).</li>
</ol>
<p>The fourth step carries the most weight. A rollout can include a leg outside the EU, but not one nobody wrote down.</p>
<h2 id="which-leg-does-elaichis-eu-region-cover">Which leg does Elaichi's eu region cover?</h2>
<p>The control plane leg, and no other leg. In the <code>eu</code> region, the organization's data store and the execution of its org-scoped requests and tool calls are pinned to the EU. Elaichi has three regions, <code>eu</code>, <code>us</code> and <code>apac</code>, chosen when the organization is created and fixed afterwards. The <code>eu</code> region is available on every plan.</p>
<p><strong>The data store.</strong> Elaichi keeps one data store per organization, and for an <code>eu</code> organization it is pinned to the EU. It holds the members, teams, roles, sharing grants, connection records, toolboxes, restrictions, access requests, OAuth grants and Elaichi Agent conversations.</p>
<p><strong>The credentials.</strong> Connections created since 2026-10-05 have their credentials placed in the organization's region, inside the EU for an <code>eu</code> organization. Older connections stay where they were until they are reconnected, which copies them into the region. Credentials are encrypted at rest with AES-256-GCM, and each ciphertext records the ID of the key that wrote it, so keys can be rotated.</p>
<p><strong>The execution.</strong> Requests and tool calls that act inside an <code>eu</code> organization run in the EU. That covers the REST API inside the organization, <code>POST /mcp</code>, SCIM, file downloads, invites and OAuth callbacks. Requests that do not act inside an organization run at the edge, wherever the request lands. Those are sign-in and sign-up, a person's own profile, creating and listing organizations, OAuth server endpoints and webhook intake.</p>
<p><strong>The audit trail.</strong> Every organization's audit trail, whatever its region, is stored in one log instance in the EU (see the <a href="/privacy/">privacy policy</a>). An <code>eu</code> organization's records go only to the EU endpoint.</p>
<p><strong>Stored tool files.</strong> Files Elaichi keeps from tool results go to one private bucket in the EU for every organization, whatever its region.</p>
<p><strong>Kept globally.</strong> User accounts, the organization record, sign-in sessions, API tokens, SSO settings and MCP OAuth token records are global stores, not part of the EU region. List them in your vendor review and your transfer records.</p>
<p>The region is fixed at creation, so choose it before the first member joins.</p>
<p>Read the region as a statement about the control plane, not about every system in the path. The model provider and the app are separate legs.</p>
<h2 id="where-does-the-model-provider-process-the-prompt">Where does the model provider process the prompt?</h2>
<p>Wherever the AI client's vendor processes it, under that vendor's settings on your plan. Elaichi has no say in it.</p>
<p>Anthropic's API documentation lists two inference geographies, <code>global</code> and <code>us</code>, and says workspace geo, where data is stored at rest, is <code>us</code> only (<a href="https://platform.claude.com/docs/en/manage-claude/data-residency">Anthropic data residency</a>, checked October 2026). This covers the Claude API. Ask Anthropic separately about Claude Team or Enterprise workspaces. On Amazon Bedrock and Google Cloud, the same page says, the endpoint sets the region. Claude also reaches a custom connector from Anthropic's cloud, not from the user's device, on every Claude client.</p>
<p>OpenAI offers European data residency for new ChatGPT Enterprise and Edu workspaces and for new API Projects (<a href="https://openai.com/index/introducing-data-residency-in-europe/">OpenAI, data residency in Europe</a>, checked October 2026). Its help center lists Europe as an inference residency region for eligible ChatGPT Enterprise and Edu customers. The same page excludes data processed outside OpenAI's infrastructure "through external integrations (e.g., Apps &#x26; MCP, Web Search, if enabled)" (<a href="https://help.openai.com/en/articles/9903489-data-residency-and-inference-residency">OpenAI Help Center</a>, checked October 2026).</p>
<p>That exclusion is why the MCP leg, where the agent reaches your apps, needs its own answer.</p>
<p>The Elaichi Agent, which works inside the app, is the one place where you choose the model leg yourself. Its model access is bring-your-own-key only. An admin sets a key for Anthropic, OpenRouter, Fireworks, or an OpenAI-compatible gateway at a base URL the admin enters. So a team can use a provider endpoint whose processing location it already has under contract.</p>
<h2 id="why-does-the-control-plane-leg-matter-if-it-is-only-one-of-three">Why does the control plane leg matter if it is only one of three?</h2>
<p>It holds the records a regulator or a customer asks about first: who reached what, through which account, and when. It also holds the credentials and runs the calls. Those records describe your people and your customers' accounts, even without the payload.</p>
<p><strong>The audit trail.</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and each names the account the call actually reached. Of the arguments, it keeps the one path argument that names the object, as the target id, and nothing else about the arguments. The error text in the trail is never derived from the third party's response, so a remote error body cannot carry customer data into the log. Every region's audit trail is stored in one EU log instance, with each organization's records kept apart, and a free read-only Auditor seat can review it. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon.</p>
<p><strong>What the agent can reach.</strong> Restrictions decide which connectors and which individual tools a target may reach. They are enforced on the server, not left to the model. A tool you withhold keeps its schema out of the model's context, so this leg also shrinks what the model provider receives.</p>
<p><strong>Credentials.</strong> Connector credentials never live in the organization store. A separate credential service holds them, encrypted with AES-256-GCM, and owns refresh. Connections created since 2026-10-05 are placed in the organization's region. A connect URL is a one-time session that carries no token.</p>
<p><strong>Deletion.</strong> Deleting an organization tears down the rest of the workspace and deletes every connected account's credential. Three stores keep residue: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi has no purge path for them and returns that residue by name. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written. Describe it that way in an erasure answer, with all three stores named.</p>
<h2 id="is-there-an-enterprise-mcp-platform-with-eu-data-residency">Is there an enterprise MCP platform with EU data residency?</h2>
<p>Yes. Elaichi offers it for the control plane leg, on every plan. Choose <code>eu</code> when the organization is created. The data store and the execution of its org-scoped requests and tool calls are then pinned to the EU, and the audit trail is stored there. User accounts and sign-in sessions are kept globally. The model provider and the apps keep their own regions.</p>
<p>One address serves every client, so there is no per-team or per-user server to place in a region. Elaichi authors and serves most of its connectors from its own infrastructure, and the rest are vendors' own MCP servers, so you do not run MCP servers in your own EU cloud.</p>
<p>SAML and OIDC sign-in are built in-house, with SCIM v2 provisioning and group-to-role mapping. A role or restriction change takes effect within about two minutes. Offboarding holds on the next call: removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Elaichi has two plans, Gold and Black. Gold is $15 per user per month at the USD list price, and the pricing page shows your local price. Pick the region when you create the organization, because it is fixed after that.</p><a href="/pricing/" class="cta-button">See pricing</a></aside>
<h2 id="where-do-i-check-elaichis-compliance-statements">Where do I check Elaichi's compliance statements?</h2>
<p>Check the Trust Center at <a href="https://trust.elaichi.ai">trust.elaichi.ai</a>, the page Elaichi points to for what it attests. Attribute any SOC 2 or HIPAA statement for a compliance file to that page. For the control mapping, see <a href="/blog/soc2-evidence-ai-agents-cc-controls/">SOC 2 evidence for CC6 and CC7</a>. For ChatGPT, OpenAI's residency excludes Apps and MCP, so the endpoint's region is a separate question. <a href="/blog/connect-elaichi-to-chatgpt/">The ChatGPT setup guide</a> covers connecting that endpoint.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page covers how credentials are held, how access is shared, and where the Trust Center sits.</p><a href="/security/" class="cta-button">Check what the Trust Center covers</a></aside>
<h2 id="when-does-elaichis-eu-region-not-solve-the-problem">When does Elaichi's eu region not solve the problem?</h2>
<p>When the leg that breaks your policy is not the control plane. Elaichi's region cannot move a model, an app tenant or a retention clock.</p>
<ul>
<li><strong>Your policy requires EU inference for Claude through Anthropic's API.</strong> Anthropic's page lists <code>global</code> and <code>us</code> as the geographies (checked October 2026). The region is chosen at the provider, for example through a cloud endpoint, not in Elaichi.</li>
<li><strong>The app tenant is hosted outside the EU.</strong> Moving it is a conversation with that vendor.</li>
<li><strong>An erasure deadline requires everything purged on request.</strong> Three stores survive organization deletion: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written.</li>
<li><strong>No AI client points at company data.</strong> Then the work is policy first, as laid out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you may not need an MCP gateway</a>.</li>
</ul>
<p>For what a good record should hold, see <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must capture</a>. For the wider category, start with <a href="/blog/what-is-an-mcp-gateway/">what an MCP gateway is</a>, and browse the 600+ connectors at <a href="/connectors/">/connectors/</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Is there an enterprise MCP platform with EU data residency?</strong></dt><dd>Elaichi offers EU data residency for the control plane, on every plan. An organization created in the eu region has its data store and the execution of its org-scoped requests and tool calls pinned to the EU, and its audit trail is stored there. User accounts and sign-in sessions are kept globally. Claude, ChatGPT, Cursor and any other MCP client reach the apps through one endpoint, https://api.elaichi.ai/mcp, under roles, restrictions and an audit log. The model provider and each SaaS app keep their own region settings, which Elaichi does not control.</dd><dt><strong>How do we keep data in the EU when employees use AI agents on our SaaS tools?</strong></dt><dd>Pin each leg of the data path separately. Check where each SaaS vendor hosts your tenant. Check which region the AI client's vendor offers for prompts, conversations and inference on your plan. Choose a control plane with an EU region for its own records. Then document every leg you could not pin, with the transfer safeguard your lawyers rely on for it. No single vendor setting covers all three legs.</dd><dt><strong>Does choosing an EU control plane keep prompts in the EU?</strong></dt><dd>No. The prompt, the conversation and every tool result the agent reads are processed by the model provider, such as Anthropic or OpenAI, under that provider's own region settings. An EU control plane such as Elaichi's eu region pins the organization store and the execution of its org-scoped requests and tool calls to the EU, and stores the audit trail there. It cannot move inference.</dd><dt><strong>Can an existing Elaichi organization move to the eu region?</strong></dt><dd>No. The region is chosen when the organization is created and is fixed from then on. The choices are eu, us and apac. The eu region is available on every plan. For EU and US, the data store and the execution of the organization's org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. So an EU commitment needs the eu region from day one.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Human approval for AI agent actions: the layers</title>
      <link>https://elaichi.ai/blog/human-approval-for-ai-agent-actions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/human-approval-for-ai-agent-actions/</guid>
      <description>Human approval for AI agent actions comes in layers: a prompt for the person asking, then the role rules, frozen values and requests an admin decides.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Claude, ChatGPT and Cursor can ask before a tool runs, but the person who approves is the person who asked. Elaichi adds the decisions an admin makes ahead of time: a restriction takes a write away from a role, frozen parameters narrow a write to its safe version, and access requests let someone with member:manage open a restricted tool for one person. The audit log then records each call that reaches execution and how it was approved.</aside>
<h2 id="how-do-you-get-human-approval-for-ai-agent-actions-like-crm-writes-and-email">How do you get human approval for AI agent actions like CRM writes and email?</h2>
<p>Human approval for AI agent actions comes in two kinds. The first is a prompt in the AI client, answered by the person who asked. The second is a decision an admin makes ahead of time about which roles may run the write at all. Elaichi handles the second kind, and its audit log records how each call was approved.</p>
<p>A RevOps lead sees the request coming. Reps want Claude to update close dates in Salesforce and to send follow-up email from Gmail. The lead wants a person to sign off before either happens. Security wants the same thing, written down somewhere an auditor can read.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected app through one organization endpoint, the single address each client signs in to. Claude, ChatGPT, Cursor and any other MCP client all use it. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> asks for a human in the loop who can deny a tool call. It also says servers must implement proper access controls. Approval needs both halves, and they live in different places.</p>
<h2 id="what-does-an-approval-prompt-in-claude-chatgpt-or-cursor-check">What does an approval prompt in Claude, ChatGPT or Cursor check?</h2>
<p>It checks with the person in front of the client, at the moment of the call. That is useful, and it is not a second pair of eyes. The approver is the same person who asked for the action.</p>
<p>Each client handles it differently (all checked October 2026):</p>
<ul>
<li><strong>Claude.</strong> Each connector has tool permissions set to Always allow, Needs approval or Blocked, per tool or per group (<a href="https://support.claude.com/en/articles/11176164">Claude Help Center</a>). On Team and Enterprise plans, owners can restrict a connector's tool actions for the whole company, and members cannot override that.</li>
<li><strong>ChatGPT.</strong> For a write, ChatGPT may ask for confirmation, depending on the app's permissions and the context. Some risky actions are refused rather than offered for approval (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI Help Center</a>).</li>
<li><strong>Cursor.</strong> "Cursor asks for approval before using MCP tools by default" (<a href="https://cursor.com/docs/mcp">Cursor docs</a>). In its Auto-review mode, allowlisted tools run without asking, and Enterprise admins can limit which tools may run automatically.</li>
</ul>
<p>There is one catch with Elaichi behind any of them. In Elaichi, connected tools are never listed one by one, however few there are. The model finds a tool with <code>search_tools</code> and runs it with <code>execute_tool</code>. A client permission therefore names <code>execute_tool</code>, so one setting covers a Salesforce read and a Gmail send alike. The real tool name sits inside the call's arguments.</p>
<p>A client prompt suits a careful person double-checking their own request. It is not a second person's decision on that call.</p>
<h2 id="does-the-elaichi-agent-ask-before-it-writes">Does the Elaichi Agent ask before it writes?</h2>
<p>Yes. In the Elaichi Agent, a write stops at an approval card before it runs. The card offers Deny, Allow once and Always allow. The person can also edit the arguments first, and the button then reads "Save &#x26; allow once".</p>
<p>Deletes get stricter treatment. Always allow is offered for writes only, so a delete asks every time. Always allow is remembered per person and per operation.</p>
<p>Calls from Claude, ChatGPT or Cursor take a different route. Over MCP, Elaichi cannot put an approval step in the client's own window. So the approval is the OAuth grant (the permission a person gives a client at sign-in). On Elaichi's consent screen, the person ticks what the client may do. "Create and change data" covers writes, and "Delete data and remove access" is never ticked in advance. Without the write box, a client cannot change Elaichi's own records. A connected app's create and update tools ride on "Run your connected tools", and only its deletes need the delete box. Holding a connected app to reads is a restriction on the role, not a consent checkbox.</p>
<p>Both routes still ask the person who started the request. The layers below are the ones an admin holds.</p>
<h2 id="how-do-you-take-a-write-away-from-a-role">How do you take a write away from a role?</h2>
<p>Write a restriction. A restriction decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Restrict the write on the Sales role, and no rep's client is offered it again.</p>
<p>For a sales team, the rule names four tools. <code>update_a_salesforce_opportunity_by_id</code> changes close dates, stages and amounts. <code>create_a_gmail_message</code> sends a message straight away, and <code>gmail_drafts_send</code> sends a saved draft. <code>create_a_gmail_batch</code> groups Gmail requests, including sends, into one call. Reads stay, and so does <code>create_a_gmail_draft</code>.</p>
<p>That is the answer to read but not delete or send. Restrict the send and delete tools by name, and keep the reads. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. A block always beats an allow.</p>
<p>Here, the draft is where the human approval happens. The agent writes the email into Gmail. The rep reads it there and presses send. While the send tools are restricted, the agent cannot send. It can only save a draft. No setting in a client can skip that step.</p>
<p>This follows <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP's guidance on excessive agency</a>. It advises putting authorization in the downstream system, not in the model's judgment. Its mailbox example makes the same cut: read, do not send. A saved restriction reaches every surface within about two minutes. <a href="/blog/per-tool-vs-per-app-restrictions/">Restricting one tool or the whole app</a> covers when to name tools and when to name the connector.</p>
<h2 id="can-you-narrow-a-write-instead-of-removing-it">Can you narrow a write instead of removing it?</h2>
<p>Yes, with frozen parameters. A frozen parameter is a value an admin fixes on one tool inside a toolbox, a saved set of tools paired with connected accounts. Elaichi removes the field from the schema the model sees. It then writes the frozen value over the call's arguments, so sending the field anyway changes nothing.</p>
<p>Take a support team that hands leads to sales and holds no Salesforce login. RevOps connects its own Salesforce account and keeps that connection unshared. It pins <code>create_a_salesforce_task</code> into a toolbox and freezes the owner field to the deal desk's Salesforce user, using the field name from the tool's schema. It then shares the toolbox with the support team at <code>use</code>. Every task the support team's agent creates lands with the deal desk. The write itself becomes the request for a person to look.</p>
<p>A template carries the same tool list, with renames, defaults and frozen values, and no account. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A rep with their own Salesforce connection reaches the same tool unfrozen. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking a tool argument</a> works the payment version through.</p>
<h2 id="what-happens-when-someone-needs-a-restricted-tool">What happens when someone needs a restricted tool?</h2>
<p>They file an access request, and someone else decides it. Any member can file one with no permission needed. Resolving it needs <code>member:manage</code>, which People Admin, Org Admin and Org Owner hold. An admin cannot decide their own request.</p>
<p>Approving a request caused by a restriction creates an access grant for that one requester. A rep restricted through the Sales role has that one tool lifted out of their role rules, so the role's other rules still bind them and nobody else changes. No rule is written and the role is not edited. Like any restriction change, it reaches every surface within about two minutes.</p>
<p>Two limits keep this honest. First, no access request can be approved or denied from the Elaichi Agent or an MCP client. Restrictions stay read-only on every AI surface, so a model cannot approve its own access. Second, an approval is a standing grant, not approval of one call. It lasts until the member is removed or an admin approves a replacement.</p>
<h2 id="what-does-the-audit-log-show-after-the-fact">What does the audit log show after the fact?</h2>
<p>Every call that reaches execution, and how it got past the approval step. The audit log is the record Elaichi keeps of each action. It holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the person, the client and the account reached.</p>
<p>Each tool call states its approval in plain words:</p>
<table>
<thead>
<tr>
<th>Route</th>
<th>What the audit log says</th>
</tr>
</thead>
<tbody>
<tr>
<td>A read</td>
<td>Didn't need approval because it only read data</td>
</tr>
<tr>
<td>Elaichi Agent card</td>
<td>Approved by the person, in chat</td>
</tr>
<tr>
<td>Edited arguments</td>
<td>Edited by the person before it ran</td>
</tr>
<tr>
<td>Remembered choice</td>
<td>Allowed automatically by an "always allow" choice</td>
</tr>
<tr>
<td>Claude, ChatGPT or Cursor</td>
<td>Allowed by the access that client was granted</td>
</tr>
</tbody>
</table>
<p>Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. So the log shows that an opportunity update ran, through which account. It does not show the new close date. Give the reviewer an Auditor seat, which is read-only, cannot call tools and costs no license. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> covers the full record.</p>
<h2 id="how-does-the-setup-look-for-a-sales-team">How does the setup look for a sales team?</h2>
<p>Two roles, four restricted tools and one review habit. Each member holds exactly one role, so a role describes a whole job. Custom roles are a Gold feature.</p>
<table>
<thead>
<tr>
<th>Role</th>
<th>Read Salesforce</th>
<th>Draft email</th>
<th>Update opportunities</th>
<th>Send email</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sales (custom)</td>
<td>Yes</td>
<td>Yes</td>
<td>Restricted</td>
<td>Restricted</td>
</tr>
<tr>
<td>Sales Ops (custom)</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>A rep with an approved request</td>
<td>Yes</td>
<td>Yes</td>
<td>Opened for them</td>
<td>Restricted</td>
</tr>
</tbody>
</table>
<p>Set it up in this order:</p>
<ol>
<li>Create both as custom roles carrying Member's permissions, including <code>tool:execute</code>.</li>
<li>Restrict <code>update_a_salesforce_opportunity_by_id</code>, <code>create_a_gmail_message</code>, <code>gmail_drafts_send</code> and <code>create_a_gmail_batch</code> on the Sales role.</li>
<li>Have each rep connect <a href="/connectors/salesforce/">Salesforce</a> and <a href="/connectors/gmail/">Gmail</a> under their own login. Each rep's own Salesforce permissions then apply to what they reach.</li>
<li>Wait about two minutes. Then, as a test rep, search for a restricted tool and confirm it comes back only by name, flagged restricted.</li>
<li>Each month, filter the audit log by the Salesforce connection and read the writes.</li>
</ol>
<p>The same shape answers how to give sales, engineering and HR different AI tool access. Give engineering and HR their own roles and restrict the Salesforce connector for both. The CRM then cannot be reached from their clients. <a href="/blog/designing-roles-for-ai-agents/">Designing roles for AI agents</a> covers the role chain. For the full Salesforce tool list a sales role should lose, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the sales team playbook</a>.</p>
<h2 id="when-is-a-client-prompt-enough">When is a client prompt enough?</h2>
<p>When one team uses one client, and the source app already says no. A Claude Team owner can restrict a connector's tools for the whole company in Claude's own settings. If reps hold a read-only Salesforce profile, the write fails at Salesforce too. A restriction layer on top would add review work and little safety.</p>
<p>The admin layers earn their cost later. That point comes when more than one client reaches more than one app, and a reviewer asks who approved last Tuesday's change. The <a href="/blog/what-is-an-mcp-control-plane/">MCP control plane overview</a> explains where Elaichi sits. The risks these layers answer are listed in <a href="/blog/mcp-security-risks/">the MCP security risks guide</a>, and <a href="/pricing/">pricing</a> has the price for your region.</p>
<h2>FAQ</h2><dl><dt><strong>Can an admin approve AI agent actions before they run?</strong></dt><dd>In Claude, ChatGPT and Cursor, an approval prompt goes to the person using the client, who is usually the person who asked for the action. In Elaichi, an admin decides ahead of time instead. A restriction takes a tool away from a role, and a member who needs it files an access request that someone with the member:manage permission approves or denies. Each call that reaches execution is then recorded in the audit log with how it was approved.</dd><dt><strong>How do I let an AI agent read the CRM but not send email?</strong></dt><dd>In Elaichi, write a restriction on the role that withholds the send tools, which for Gmail are create_a_gmail_message, gmail_drafts_send and create_a_gmail_batch, and leave the read and draft tools alone. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. The person then reviews each draft in Gmail and sends it by hand.</dd><dt><strong>Does a Needs approval setting in Claude work per tool through Elaichi?</strong></dt><dd>Not per connected tool. Elaichi serves connected tools through two tools, search_tools and execute_tool, so a Claude tool permission on execute_tool covers every connected tool at once. Use the client setting as a prompt for the person in the chat, and use an Elaichi restriction on the role to decide which tools that role can reach at all.</dd><dt><strong>Who can approve an access request in Elaichi?</strong></dt><dd>Anyone whose role holds the member:manage permission, such as a People Admin, Org Admin or Org Owner, and never the person who filed it. Any member can file a request. Approving a request creates an access grant for that requester only, and lifts exactly the approved tool or connector out of their role rules. No access request can be approved or denied from the Elaichi Agent or an MCP client.</dd><dt><strong>How do you give sales, engineering and HR different AI tool access?</strong></dt><dd>In Elaichi, give each department its own role and write restrictions for each role. Each member holds exactly one role, so a rule on the Sales role reaches every rep and nobody else. Custom roles are a Gold feature. A role or restriction change reaches every surface within about two minutes.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Kong vs Cloudflare MCP gateway, or managed connectors?</title>
      <link>https://elaichi.ai/blog/kong-cloudflare-mcp-gateway-vs-managed-connectors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/kong-cloudflare-mcp-gateway-vs-managed-connectors/</guid>
      <description>Kong vs Cloudflare MCP gateway: both govern MCP servers you build or bring. A managed connector platform ships the SaaS connectors already written.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Kong AI Gateway turns APIs you describe into MCP tools, and Cloudflare hosts MCP servers you write on Workers and puts servers you bring behind an MCP server portal. In both, someone on your side builds or adds the tools for each SaaS app. Elaichi serves 600+ connectors, most of them its own, through one organization-wide MCP endpoint, with per-person sign-in, roles, restrictions and one audit log.</aside>
<p>Your platform team already runs Kong in front of the company's APIs, or your network sits on Cloudflare. Then operations asks for Claude to reach Salesforce, Jira, Slack and Google Workspace for three hundred people, most of them outside engineering. Both vendors document MCP features (<a href="https://developer.konghq.com/ai-gateway/">Kong</a> and <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">Cloudflare</a>, checked October 2026), so the Kong vs Cloudflare MCP gateway question looks like the whole decision. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>It is not the whole decision. The harder question is who writes the tools for each SaaS app, who signs each person in to it, and who keeps it working when the app changes. For the general gateway shape, <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">this comparison of API gateways and MCP-native servers</a> covers it. This post is the narrower buyer's version, for Kong and Cloudflare by name.</p>
<h2 id="kong-vs-cloudflare-mcp-gateway-or-a-managed-connector-platform">Kong vs Cloudflare MCP gateway, or a managed connector platform?</h2>
<p>Pick Kong or Cloudflare when the tools are your own: APIs you already run, or MCP servers you write. Pick a managed connector platform such as Elaichi when the request is a list of SaaS apps and the people asking are not engineers.</p>
<p>The split follows from what each product starts with (vendor docs checked October 2026). <a href="https://developer.konghq.com/ai-gateway/entities/ai-mcp-server/">Kong</a> starts from your APIs and asks you to describe them as tools. <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">Cloudflare</a> starts from MCP servers, either ones you deploy on Workers or remote ones you add to a portal. Elaichi starts from the apps. It serves 600+ connectors, most of which it authors, through one organization-wide endpoint, <code>https://api.elaichi.ai/mcp</code>. An endpoint here is the one address every client points at.</p>
<p>Between the two, Kong fits when the tools are APIs you already run behind it, and Cloudflare fits when engineers build servers on Workers or put remote servers behind a portal. Cloudflare's gateway-style MCP product is MCP server portals.</p>
<p>None of these is better in general. Each fits a different upstream, and the sections below show where each one's work lands.</p>
<h2 id="what-does-kong-ai-gateway-do-with-mcp">What does Kong AI Gateway do with MCP?</h2>
<p>Kong AI Gateway turns APIs into MCP tools and proxies MCP traffic, inside a gateway your team operates. Kong's <a href="https://developer.konghq.com/ai-gateway/">AI Gateway documentation</a> (checked October 2026) says it "is managed through Konnect", with data plane nodes running "in your environment". It lists the job as "Turn existing APIs into tools an AI agent can discover and call over Model Context Protocol".</p>
<p>The building block is the <a href="https://developer.konghq.com/ai-gateway/entities/ai-mcp-server/">AI MCP Server entity</a> (checked October 2026). Kong's page says "Each tool needs at minimum a description and an HTTP method". Kong's <a href="https://developer.konghq.com/ai-gateway/map-api-to-mcp-tools/">API-to-tools tutorial</a> has the reader write each tool's name, description, method and path, against the Swagger Petstore sample. The <a href="https://developer.konghq.com/plugins/ai-mcp-proxy/">AI MCP Proxy plugin</a> can also pass MCP requests through to an upstream MCP server. Kong marks that plugin "only available as part of our AI Gateway Enterprise offering".</p>
<p>Kong's access control is fine-grained. The proxy plugin evaluates allow and deny lists against Kong Consumers and Consumer Groups, at a default level and per tool. The <a href="https://developer.konghq.com/plugins/ai-mcp-oauth2/">AI MCP OAuth2 plugin</a> (checked October 2026) validates tokens by introspection or JWKS. It also notes that "Access tokens are not forwarded to upstream services by default".</p>
<h2 id="what-does-cloudflare-offer-for-mcp-servers">What does Cloudflare offer for MCP servers?</h2>
<p>Cloudflare documents two MCP products that matter here: a place to run MCP servers you write, and a portal that puts several remote MCP servers behind one address. Cloudflare's <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/">remote MCP server guide</a> (checked October 2026) deploys a server to a <code>workers.dev</code> subdomain. In its authentication example, "your users are redirected to GitHub to authenticate".</p>
<p>The second product is MCP server portals, part of Cloudflare Access in Cloudflare One. Cloudflare's <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">MCP server portals page</a> (checked October 2026) says a portal "centralizes multiple Model Context Protocol (MCP) servers onto a single HTTP endpoint". Users sign in through Access and "are prompted to authenticate separately to each server that requires OAuth". Admins choose and rename tools per portal, and Access logs each tool request.</p>
<p>The same page sets the limits. "Only remote HTTP MCP servers are supported", and "Each portal supports up to 80 MCP servers." An admin adds each server by its URL. So the portal works best when every app already publishes a remote MCP server, or when your team builds one on Workers.</p>
<h2 id="who-writes-the-salesforce-jira-and-slack-tools-on-each-path">Who writes the Salesforce, Jira and Slack tools on each path?</h2>
<p>On Kong and Cloudflare, your side builds or adds the tools. On Elaichi, Elaichi writes and maintains most of the connectors, the app vendor runs the rest, and your side connects accounts.</p>
<p>With Kong AI Gateway, someone describes each tool: name, description, method and path, per endpoint, per app. When Salesforce changes an endpoint, that description is yours to fix. With Cloudflare, a Workers server is code your engineers write and deploy. A portal can instead front an app's own remote MCP server, such as <a href="https://github.com/atlassian/atlassian-mcp-server">Atlassian's for Jira</a> or <a href="https://docs.slack.dev/ai/slack-mcp-server/">Slack's</a> (both checked October 2026). Each one still needs adding, an OAuth setup and a check on its tool names.</p>
<p>Elaichi starts from the other end. It serves 600+ connectors and authors most of them, including <a href="/connectors/salesforce/">Salesforce</a>, <a href="/connectors/jira/">Jira</a> and <a href="/connectors/slack/">Slack</a>, and serves them from its own infrastructure. Google Workspace arrives as several connectors, such as Gmail, Drive and Calendar. A missing app can be a custom connector, written from JSON config or forked from a public one. <a href="/blog/mcp-registry-vs-first-party-connectors/">Why first-party authorship matters</a> covers the repair path in detail.</p>
<h2 id="how-does-each-path-sign-a-person-in-to-the-saas-app">How does each path sign a person in to the SaaS app?</h2>
<p>In Elaichi, each person signs in to each app with their own account, and a separate service holds and refreshes those tokens. On Kong and Cloudflare, the per-person path to the app is something you configure.</p>
<p>Kong's <a href="https://developer.konghq.com/ai-gateway/entities/ai-mcp-server/">AI MCP Server page</a> says that, by default, "AI Gateway proxies these requests without adding credentials", and <code>config.upstream.auth</code> sets what Kong adds. Kong's <a href="https://developer.konghq.com/plugins/ai-mcp-oauth2/">OAuth2 plugin</a> can swap the client's token for another one before forwarding (both checked October 2026). Ask Kong which token endpoint would issue a per-person Salesforce token, and who registers that app. On Workers, Cloudflare's <a href="https://developers.cloudflare.com/agents/model-context-protocol/authorization/">authorization docs</a> (checked October 2026) say "the MCP Server (your Worker) generates and issues its own token to the MCP client" when a third-party provider signs the user in. Cloudflare's <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">portal</a> supports per-user OAuth to each upstream server through its "Require user auth" setting. With it disabled, users reach the server through its admin credential. Ask Cloudflare which account each tool call reaches in each mode.</p>
<p>In Elaichi, a Member can connect any catalog app with their own account unless a restriction stops it. Credentials live in a separate credential service, encrypted at rest with AES-256-GCM, and that service owns refresh. A failed refresh marks the connection <code>needs_reauth</code>, so the failure shows. An OAuth connector connects through a default OAuth app that every organization inherits unless it brings its own. Where none exists, the catalog marks the connector, and an admin with connector-management permission stores the organization's own client ID and secret first.</p>
<h2 id="how-do-kong-cloudflare-and-elaichi-compare-side-by-side">How do Kong, Cloudflare and Elaichi compare side by side?</h2>
<p>They differ most on who supplies the tools and how a person reaches each app. Vendor columns come from <a href="https://developer.konghq.com/ai-gateway/">Kong's AI Gateway docs</a> and <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">Cloudflare's portal docs</a>, checked October 2026.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Kong AI Gateway</th>
<th>Cloudflare (Workers and MCP server portals)</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Where tools come from</td>
<td>Tool definitions you write over your APIs</td>
<td>MCP servers you write, or remote servers you add by URL</td>
<td>600+ connectors, most authored by Elaichi</td>
</tr>
<tr>
<td>Where it runs</td>
<td>Data planes in your environment, managed through Konnect</td>
<td>Workers, and portals on a domain you hold on Cloudflare</td>
<td>Elaichi's infrastructure. The organization's data store sits in the region chosen at creation</td>
</tr>
<tr>
<td>Address for clients</td>
<td>Route paths you configure; a listener aggregates several</td>
<td>One portal URL per portal</td>
<td>One URL for every organization</td>
</tr>
<tr>
<td>Access rules</td>
<td>Allow and deny lists per tool, on Consumers</td>
<td>Access policies per portal and server; tool selection</td>
<td>One role per member, restrictions per role or user, frozen parameters</td>
</tr>
<tr>
<td>Record</td>
<td>Plugin logs each access attempt</td>
<td>Access logs each tool request</td>
<td>one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account reached</td>
</tr>
</tbody>
</table>
<h2 id="can-you-connect-a-whole-tech-stack-to-ai-assistants-without-building-mcp-servers">Can you connect a whole tech stack to AI assistants without building MCP servers?</h2>
<p>Yes, if the platform already wrote the connectors. That is the case a managed connector platform is built for, and the case where a gateway leaves the most work on your side.</p>
<p>In Elaichi, an admin adds <code>https://api.elaichi.ai/mcp</code> once, each member signs in with their own OAuth grant, and members connect their apps from the catalog. On the other paths, you describe each tool in Kong, or add each server to a Cloudflare portal by its URL. <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">The endpoint, sign-in and audit details</a> are covered in the gateway comparison.</p>
<p>Two Elaichi points matter next to Kong and Cloudflare. Frozen parameters lock an argument, such as a Slack channel, so the model cannot change it. The model can still see a short frozen value in the tool description. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. And the organization picks a region, EU, US or APAC, when it is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee.</p>
<h2 id="when-is-kong-or-cloudflare-the-better-choice">When is Kong or Cloudflare the better choice?</h2>
<p>Kong is the better choice when the tools are your own APIs and Kong already fronts them. Cloudflare is the better choice when your engineers are building MCP servers and want them on Workers, or want one portal over remote servers they already trust.</p>
<p>With Kong, an internal order API becomes tools through an AI MCP Server entity, with Consumer allow and deny lists your team already knows how to review. With Cloudflare, an engineering team writing custom servers gets <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/">Workers hosting</a>, <a href="https://developers.cloudflare.com/agents/model-context-protocol/authorization/">OAuth options</a> and Access in one account (checked October 2026). If your apps all publish remote MCP servers, a portal over them is a reasonable shape too.</p>
<p>Elaichi does not fit those cases well. It is not built to front a fleet of servers you run, and it governs an app's own MCP server only when that server is in its catalog or added as your own remote MCP connector. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The cost of running your own servers</a> is the honest test for the build path.</p>
<h2 id="how-does-elaichi-run-alongside-kong-or-cloudflare">How does Elaichi run alongside Kong or Cloudflare?</h2>
<p>Split by who owns the upstream: internal APIs stay behind Kong, servers your engineers write stay on Cloudflare, SaaS accounts go through Elaichi. Kong keeps request policy over APIs you deploy, and Cloudflare keeps hosting and Access for servers you build, so neither has to front Salesforce. <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">The side-by-side split</a> is covered in the gateway comparison.</p>
<p>To compare more shapes, read <a href="/blog/what-is-an-mcp-gateway/">what an MCP gateway is</a>, <a href="/blog/best-mcp-gateways/">the shortlist of MCP gateways</a>, or <a href="/blog/docker-mcp-gateway-vs-managed-mcp-platform/">the Docker MCP Gateway comparison</a>. To check your own stack, browse the <a href="/connectors/">connector catalog</a> and the <a href="/use-cases/">team rollouts</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Should we use Kong or Cloudflare as an MCP gateway, or a managed connector platform?</strong></dt><dd>Use Kong AI Gateway or Cloudflare when the tools are yours: APIs you already run behind Kong, or MCP servers you write and deploy on Cloudflare Workers. Use a managed connector platform such as Elaichi when the request is a list of SaaS apps like Salesforce, Jira and Slack. Kong's docs have you describe each tool, and Cloudflare's portal fronts MCP servers that already exist (vendor docs checked October 2026). Elaichi authors most connectors itself and serves them through one organization-wide endpoint.</dd><dt><strong>Are there managed MCP connectors for hundreds of SaaS apps?</strong></dt><dd>Yes. Elaichi serves 600+ connectors and authors most of them on its own infrastructure, including Salesforce, Jira and Slack, and serves them through one MCP endpoint at https://api.elaichi.ai/mcp. Each person signs in to each app with their own account, and a separate credential service holds and refreshes the tokens. No one at the customer runs an MCP server.</dd><dt><strong>How do we connect our whole tech stack to AI assistants without building MCP servers?</strong></dt><dd>Pick a platform that already wrote the connectors. With Elaichi, an admin adds one MCP address in Claude, ChatGPT or Cursor where the client allows it, and each member connects their apps from the catalog with their own sign-in. Roles and restrictions decide who reaches which tools, and every tool call that reaches execution lands in one audit log that names the account it reached.</dd><dt><strong>Can Elaichi run alongside Kong or Cloudflare?</strong></dt><dd>Yes. Internal APIs stay behind Kong, MCP servers your engineers write stay on Cloudflare Workers, and third-party SaaS accounts go through Elaichi. Assign each tool to exactly one of them, so a policy change is made once and never has to be reconciled across products.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>MCP security review checklist: ten questions</title>
      <link>https://elaichi.ai/blog/mcp-security-review-checklist/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-security-review-checklist/</guid>
      <description>An MCP security review checklist: ten questions to ask before approving an MCP server or gateway, what a good answer looks like, and Elaichi&apos;s answers.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An MCP security review checklist asks ten questions of any MCP server or gateway, in seven areas: sign-in and tokens, consent, how narrow access can get, how fast it ends, what the record holds, where data lives, and what the product does not cover. Elaichi answers with per-person OAuth using PKCE and no embedded tokens, a consent screen where delete is never pre-ticked, per-tool restrictions checked at execution, and one entry for each connected-tool call that reaches execution (a call refused earlier writes none). It does not stop prompt injection, and its certification status is published in its Trust Center, not claimed here.</aside>
<p>A sales lead asks to connect Claude to the CRM, and the request lands on the security team's desk. This MCP security review checklist is the set of questions to send before approving an MCP server, or a gateway or control plane in front of several. Each comes with what a good answer looks like, and with the answer Elaichi gives.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An MCP server exposes one app's actions as tools. A gateway or control plane puts one address and one set of rules in front of several. Either way, the review asks the same thing: who can make an AI act in which system, and what record is left behind. The same ten questions are the CISO's approval checklist for an MCP server or control plane, and the evidence table below turns them into go or no-go items.</p>
<h2 id="what-belongs-on-an-mcp-security-review-checklist">What belongs on an MCP security review checklist?</h2>
<p>Ten questions, in seven areas: sign-in and tokens, consent, how narrow access can get, how fast it ends, what the record holds, where data lives, and what the product does not cover. Copy the table into your vendor review and ask for every answer in writing.</p>
<table>
<thead>
<tr>
<th>#</th>
<th>Ask the vendor</th>
<th>A good answer</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>How does each person sign in?</td>
<td>OAuth per person, with PKCE, and no token in a URL</td>
</tr>
<tr>
<td>2</td>
<td>Where do the app credentials live?</td>
<td>Outside the gateway, AES-256-GCM at rest, with failed refreshes visible</td>
</tr>
<tr>
<td>3</td>
<td>What does consent show and pre-tick?</td>
<td>The client's name and redirect, and nothing destructive by default</td>
</tr>
<tr>
<td>4</td>
<td>Can a rule cover one tool for one role?</td>
<td>Yes, written against the operation, not the tool's label</td>
</tr>
<tr>
<td>5</td>
<td>Where is a rule enforced?</td>
<td>At execution, not only when tools are listed</td>
</tr>
<tr>
<td>6</td>
<td>How fast does access end?</td>
<td>Removal on the next request, and a stated figure for rule changes</td>
</tr>
<tr>
<td>7</td>
<td>What does one audit record hold?</td>
<td>The person, the client that made the call, the account reached, the outcome</td>
</tr>
<tr>
<td>8</td>
<td>What does the log leave out?</td>
<td>Argument contents and third-party error text</td>
</tr>
<tr>
<td>9</td>
<td>Where does data live, and what survives deletion?</td>
<td>A named region, a stated guarantee, a named residue</td>
</tr>
<tr>
<td>10</td>
<td>What does the product not protect against?</td>
<td>A written list, with prompt injection on it</td>
</tr>
</tbody>
</table>
<h2 id="how-does-each-person-sign-in-and-where-do-tokens-sit">How does each person sign in, and where do tokens sit?</h2>
<p>Each person should sign in with their own OAuth grant, and no token should travel in a URL. OAuth is the standard for delegated sign-in that never hands the client a password. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization specification</a> requires authorization on every HTTP request and bans tokens from the query string. It also says a server must not accept or pass along tokens issued for anything else.</p>
<p>Elaichi has one address for every organization, <code>https://api.elaichi.ai/mcp</code>. There are no per-toolbox URLs and no embedded tokens. Clients register themselves through dynamic client registration (RFC 7591), and PKCE with <code>S256</code> is required. The redirect address must match the registered one exactly (a loopback address may change port, never host), and a <code>resource</code> on any other origin is refused with <code>invalid_target</code>. That <code>resource</code> check runs when the token is issued.</p>
<p>An access token lasts one hour. A refresh token lasts 30 days and rotates on every use, and reusing an old one revokes the whole grant. Elaichi stores only a keyed hash of each token, never the raw value.</p>
<p>App credentials are not in Elaichi at all. A separate credential service holds them with AES-256-GCM at rest and owns refresh. Each ciphertext records the ID of the key that wrote it, so the encryption key can be rotated. A failed refresh marks the connection <code>needs_reauth</code> instead of failing quietly.</p>
<p>One gap to record: the current specification prefers client ID metadata documents and keeps dynamic registration for backward compatibility. Elaichi does not advertise metadata documents. <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth versus long-lived keys for agents</a> covers why a per-person grant beats a shared key.</p>
<h2 id="what-does-the-consent-screen-ask-a-person-to-approve">What does the consent screen ask a person to approve?</h2>
<p>It should name the client, show where the tokens go, and leave destructive access unticked. The MCP <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices">security best practices</a> require a proxy's consent page to name the requesting client, list the scopes and show the registered redirect URI.</p>
<p>Elaichi's consent screen names the requesting app and shows the host it sends the person to, with the full address one click away. It also warns that anyone can register an app under any name and logo. The person picks one organization, then chooses from four boxes: read data, create and change data, run connected tools, and delete data and remove access.</p>
<p>Every scope the client requested is pre-ticked except delete, which is never pre-ticked. A client that requests no scope gets read only. Consent can narrow a request but never widen it.</p>
<p>When "run connected tools" is ticked, a second step asks which toolboxes the grant reaches. "All my tools" is the default and includes accounts connected later. "Only the ones I pick" allows up to 50. If you want tighter grants, tell people which option to choose.</p>
<h2 id="can-access-be-narrowed-to-one-tool-for-one-role">Can access be narrowed to one tool for one role?</h2>
<p>It should be, and the rule should run on the server, not in the model. OWASP's <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">LLM06 Excessive Agency</a> traces agent damage to excessive functionality, permissions and autonomy. It recommends the minimum necessary permissions, enforced in downstream systems rather than left to the model.</p>
<p>Elaichi keeps three layers apart. Each member holds exactly one role. A member sees only what they own or what was explicitly shared with them. Restrictions then decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks beat allows.</p>
<p>Rules bind the operation, not the advertised label, because whoever edits a connector's documentation can rename a tool. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. A delete also needs the <code>mcp:destructive</code> scope.</p>
<p>Test one trap before go-live: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks and allows match differently</a> explains the operation rule.</p>
<h2 id="how-quickly-does-access-end-when-someone-leaves">How quickly does access end when someone leaves?</h2>
<p>Removal should land on the next request, and the vendor should give a figure for rule changes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the removed person's next call fails. Revoking a share or disconnecting an account also takes effect on the next request.</p>
<p>A role or restriction change takes about two minutes, through a 60-second cache and edge propagation. Write that figure into the control description before a tester measures it. During an incident, suspend the member or revoke the grant. Do not edit a rule and wait.</p>
<p>SCIM is the standard an identity provider uses to provision and deprovision users. A SCIM deprovision in Elaichi suspends the member and never removes them. Suspension still ends every live grant. Removal is a separate step, with an offboarding preflight that refuses while a toolbox entry still references the leaver's personal connection. <a href="/blog/offboarding-when-the-agent-holds-access/">A contractor's last day, step by step</a> walks through that sequence.</p>
<h2 id="what-should-one-audit-record-hold-for-an-ai-tool-call">What should one audit record hold for an AI tool call?</h2>
<p>The person, the client that made the call, the account actually reached and the outcome, with nothing secret in it. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the operation and tool, the connection, the classification, whether the call was approved, the outcome and an error code. The account recorded is the one the call reached, taken from the execution rather than the request.</p>
<p>Each entry also records which client made the call. Claude, ChatGPT and Cursor are marked verified. A loopback client such as Claude Code shows its self-registered name, marked unverified. Each person can see and disconnect their own clients in Settings, under Connected apps.</p>
<p><code>actor_kind</code> is a stored field, not a guess. Its values include <code>user</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks Elaichi's own in-app agent. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with the surface and the client named. The trail keeps the one path argument that names the object, as the target id, and nothing else about the arguments. The error written to the audit trail is never derived from the third party's response, which keeps a remote error body out of your log pipeline.</p>
<p>The trail is append-only, newest first, and kept apart for each organization. It is eventually consistent, so a row may take a moment to appear. A reviewer reads it from the Auditor role, a free read-only seat that cannot call tools. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an agent audit log needs</a> lists the full record.</p>
<h2 id="where-does-the-data-live-and-what-survives-deletion">Where does the data live, and what survives deletion?</h2>
<p>A good answer names the region, says exactly what the region covers, and names what deletion leaves behind. Elaichi has three regions, EU, US and APAC, chosen when the organization is created and fixed after. For an EU or US organization, the data store is pinned to that jurisdiction, and so is the execution of its org-scoped requests and tool calls. That store holds members, roles, connections, restrictions and OAuth grants. APAC uses best-effort placement and is not a residency guarantee.</p>
<p>Connector credentials are encrypted with AES-256-GCM. Connections created since 2026-10-05 have their credentials placed in the organization's region: inside the EU or US jurisdiction for those regions, and by best-effort placement for APAC. Older connections stay where they were until reconnected, which copies them into the region.</p>
<p>Several things sit outside the region. User accounts, sign-in sessions, API tokens, SSO settings and MCP OAuth token records (as keyed hashes) are kept globally. Requests that do not act inside an organization, such as sign-in and sign-up, run at the edge wherever the request lands. Tool-result files go to one private EU bucket for every organization, whatever its region. Every organization's audit trail is stored in one log instance in the EU, as the <a href="/privacy/">privacy policy</a> states. The EU region is available on every plan.</p>
<p>Deletion has a gap that belongs in your data map. Deleting an organization tears down the workspace and deletes the connector credentials. Three stores keep residue: the audit history, analytics events, and the credential service's connector configuration rows. Elaichi returns that residue by name rather than hiding it. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written. For key custody, customer-managed keys in AWS KMS come with the Black plan, which is launching soon.</p>
<p>Whether Elaichi holds SOC 2, ISO 27001 or HIPAA attestations is answered in the <a href="https://trust.elaichi.ai">Trust Center</a>. <a href="/blog/soc2-evidence-ai-agents-cc-controls/">SOC 2 evidence for agent access</a> maps a control plane's records to the criteria, and <a href="/blog/hipaa-ai-agents-baa-reviewer-questions/">what a BAA reviewer asks about agents</a> covers health data.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page sets out how Elaichi holds credentials, shares access and records each tool call that reaches execution.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="which-mcp-security-risks-does-a-gateway-or-control-plane-leave-open">Which MCP security risks does a gateway or control plane leave open?</h2>
<p>Prompt injection is the largest, and no gateway or control plane closes it. OWASP's <a href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/">LLM01 Prompt Injection</a> describes the indirect kind: instructions hidden in a web page or file the model reads. OWASP adds that a fool-proof prevention may not exist. An MCP server never sees the user's prompt, so it has nothing to judge. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call.</p>
<p>What holds on Elaichi's side limits the damage. It enforces role-based permissions per operation, a <code>forbidden</code> classification that no OAuth scope can reach, output redaction, OAuth scope limits and an audit row for each call that reaches execution. OWASP recommends two defenses that match: least privilege, and human approval for high-risk actions. Approval belongs in the client, so switch it on for writes wherever the client offers it.</p>
<p>Two other risks sit outside any remote gateway. The MCP security best practices describe local server compromise, where a server installed on a laptop runs code with the client's privileges. A control plane never sees that server. Text pasted into a chat window never reaches it either. Both belong to endpoint controls, a CASB (cloud access security broker) and DLP (data loss prevention), as <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">what a CASB can and cannot see</a> explains.</p>
<h2 id="what-evidence-does-a-ciso-need-before-approving-an-mcp-server">What evidence does a CISO need before approving an MCP server?</h2>
<p>Screenshots and log rows from a trial organization, not vendor assurances. These areas cover the decision, and each one has a pass condition a reviewer can mark go or no-go.</p>
<table>
<thead>
<tr>
<th>Check</th>
<th>Evidence to collect</th>
<th>Pass condition</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sign-in</td>
<td>The client's configuration file and a recording of the sign-in</td>
<td>No token is pasted into a config file, and each person holds their own grant</td>
</tr>
<tr>
<td>Consent</td>
<td>A screenshot of the consent screen with every box visible</td>
<td>Delete is not pre-ticked</td>
</tr>
<tr>
<td>Narrowing</td>
<td>A rule that reaches one tool for one role, written against the role, plus the tool list from a test account</td>
<td>The restricted tool appears in <code>search_tools</code> results only by name, flagged restricted and with no schema, while the role's other tools are found normally</td>
</tr>
<tr>
<td>Revocation timing</td>
<td>A timed member removal and a timed rule edit</td>
<td>The removed member's next call fails. A role or restriction change applies within about two minutes.</td>
</tr>
<tr>
<td>Audit</td>
<td>One entry per tool call that reaches execution, run or failed</td>
<td>The entry names the account reached, and carries no argument value except the target id</td>
</tr>
<tr>
<td>Data location</td>
<td>The organization's region setting</td>
<td>The region is named, and the vendor states what runs and is stored there</td>
</tr>
<tr>
<td>Deletion</td>
<td>The response to an organization deletion</td>
<td>The residue is named: the audit history, analytics events, and the credential service's connector configuration rows</td>
</tr>
<tr>
<td>Connector authorship</td>
<td>A written statement of who writes and maintains each connector</td>
<td>A named maintainer, and a stated route for an app that is missing</td>
</tr>
<tr>
<td>Stated limit</td>
<td>The vendor's written list of what the product does not cover</td>
<td>Prompt injection is on the list, because the endpoint never sees the prompt</td>
</tr>
</tbody>
</table>
<h2 id="how-do-you-test-it-in-an-afternoon">How do you test it in an afternoon?</h2>
<p>Create two test members in a trial organization and run five tests. Each one checks a claim from the evidence table rather than a feature description.</p>
<ol>
<li>Sign in from one MCP client with the first test member, and confirm the consent screen names the client and leaves delete unticked.</li>
<li>Call a tool the role should reach, then open the audit entry and check it names the account the call reached.</li>
<li>Restrict one tool for that role, then confirm a <code>search_tools</code> query returns it only by name, flagged restricted and with no schema, while the same query still finds the tools the role keeps.</li>
<li>Remove or suspend the second test member, then confirm their next call fails.</li>
<li>Change the first member's role, then confirm the new rule applies within about two minutes.</li>
</ol>
<h2 id="how-do-you-take-ai-agents-on-company-data-through-a-security-review">How do you take AI agents on company data through a security review?</h2>
<p>Arrive with an inventory, the rules and a record, not a promise. Reviewers approve a design they can test, and six steps produce one.</p>
<ol>
<li>List the AI clients people already use and the apps they have connected, including personal tokens.</li>
<li>Move everyone to one address with per-person sign-in, and retire shared tokens.</li>
<li>Write roles before access. Start everyone on Member and restrict destructive tools at the role level.</li>
<li>Add the reviewer as an Auditor. The seat is free and read-only.</li>
<li>Send the ten questions to each vendor and attach the written answers to the review.</li>
<li>Pilot with one team for two weeks, then sample the audit log against the roles you wrote.</li>
</ol>
<p>On cost, Elaichi's Gold plan is $15 per user per month at the USD list price. Auditor, Guest and Billing Admin seats are free.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Gold includes the in-app audit trail. Where a regional price applies, the pricing page shows it.</p><a href="/pricing/" class="cta-button">See plans and pricing</a></aside>
<h2 id="when-is-an-mcp-gateway-the-wrong-control-for-the-risk">When is an MCP gateway the wrong control for the risk?</h2>
<p>When nobody has connected an AI client to a system of record yet. Assistant use that is only reading, copying and pasting is a content problem. DLP is the right instrument for it, and a gateway adds an address that answers nothing you were asked.</p>
<p>One team using one app may not need a second vendor either. Many apps now ship their own MCP server that runs under the app's own permission model. That holds until a second app or client arrives, and the question becomes one set of rules and one trail across them.</p>
<p><a href="/blog/when-you-dont-need-an-mcp-gateway/">The case for waiting on a gateway</a> lists the signals that say you have waited long enough. When they appear, the <a href="/connectors/">connector catalog</a> runs to 600+, and the rest of the <a href="/blog/category/governance/">governance writing</a> covers the rules underneath.</p>
<h2>FAQ</h2><dl><dt><strong>How should a security team evaluate an MCP gateway?</strong></dt><dd>Ask every vendor the same written questions: how each person signs in, where app credentials live, what the consent screen pre-ticks, whether a rule can cover one tool for one role, where rules are enforced, how fast access ends, what an audit record holds and leaves out, where data lives, and what the product does not protect against. Then test the answers. Revoke a grant and confirm the next call fails. Change a rule and time it. In Elaichi, a role or restriction change takes about two minutes.</dd><dt><strong>Is it safe to connect Claude to our CRM?</strong></dt><dd>It can be, if three things hold: each person signs in with their own grant, the agent can reach only the tools its role needs, and every call that runs is recorded against the account it reached. The usual risks are a shared token, an agent that can delete records, a change nobody can attribute, and instructions hidden in CRM content. Through Elaichi, delete is never pre-ticked on the consent screen, a role can be restricted to read tools, and the audit log names the account each call that ran reached. Elaichi does not stop prompt injection, so keep approval for writes switched on in the client.</dd><dt><strong>Is Elaichi SOC 2 certified?</strong></dt><dd>This answer makes no certification claim. Whether Elaichi holds SOC 2, ISO 27001 or HIPAA attestations is published in its Trust Center at trust.elaichi.ai, and any statement for a compliance file should be taken from there. What the product's code backs can be described directly: an append-only audit trail kept apart for each organization, a per-organization store pinned to the EU or US jurisdiction for organizations in those regions, AES-256-GCM encryption at rest, SSO with SCIM provisioning, TOTP MFA, passkeys, and a free read-only Auditor role.</dd><dt><strong>Does an MCP gateway protect against prompt injection?</strong></dt><dd>No gateway closes it, because an MCP server never sees the user's prompt. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What limits the damage is least privilege and approval: role-based permissions per operation, a forbidden classification no OAuth scope can reach, no delete scope unless someone ticks it, human approval for writes in the client, and an audit log that shows what happened afterwards.</dd><dt><strong>How fast can we cut off an employee's AI access?</strong></dt><dd>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the person's next call fails. A SCIM deprovision suspends the member, which has the same effect. Editing a role or a restriction is slower, at about two minutes, so suspend the member during an incident rather than editing a rule.</dd><dt><strong>What should a CISO do first if an MCP-connected agent misbehaves?</strong></dt><dd>Suspend or remove the member whose grant the agent holds. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the agent's next call is refused. If the account behind the calls should stop for everyone, disconnect that connection, which also takes effect on the next call. Then tighten the role's restriction, which takes about two minutes, and read the audit trail to see which calls already ran and which account each one reached.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>MCP security risks and how to reduce them</title>
      <link>https://elaichi.ai/blog/mcp-security-risks/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-security-risks/</guid>
      <description>The MCP security risks a company faces, from prompt injection to keys in local configs, with an example and a fix for each, and who owns the fix.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> MCP security risks for a company come from three places: the content a model reads, the servers that hand it tools, and the credentials behind them. Elaichi reduces the server and credential risks with per-person OAuth, first-party connectors, per-tool restrictions, frozen arguments, credentials held outside the client and one audit log. Prompt injection happens inside the model's context, so it stays a client and model problem that Elaichi narrows but does not solve.</aside>
<p>An engineer pastes a personal CRM token into a local MCP config. A support lead installs a community server from a registry. Neither asked security, and both agents now act inside company systems.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. MCP security risks come from three places: the content the model reads, the servers that hand it tools, and the credentials behind those servers. Each risk here has a source, an example, a fix and an owner.</p>
<h2 id="what-are-the-mcp-security-risks-for-companies-and-how-do-you-reduce-them">What are the MCP security risks for companies, and how do you reduce them?</h2>
<p>Nine risks recur across the MCP specification and OWASP's lists. Most are reduced by where credentials live and how narrow each grant is. Prompt injection is not, because it happens inside the model.</p>
<p>The sources are the MCP <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices">Security Best Practices</a>, the <a href="https://owasp.org/www-project-mcp-top-10/">OWASP MCP Top 10</a> (a beta release) and the OWASP Top 10 for LLM applications.</p>
<table>
<thead>
<tr>
<th>Risk</th>
<th>What reduces it</th>
<th>Who owns the fix</th>
</tr>
</thead>
<tbody>
<tr>
<td>Prompt injection through tool results</td>
<td>Least privilege, approval for writes, a record of each call that runs</td>
<td>The client and the model</td>
</tr>
<tr>
<td>Tool poisoning and rug pulls</td>
<td>Tools from one accountable author, rules bound to operations</td>
<td>Whoever authors the server</td>
</tr>
<tr>
<td>Token passthrough and confused deputy</td>
<td>Tokens issued only for the server, consent on every sign-in, exact redirects</td>
<td>The MCP server</td>
</tr>
<tr>
<td>Personal keys in local configs</td>
<td>Per-person OAuth, app credentials held on the server</td>
<td>IT, with a control plane</td>
</tr>
<tr>
<td>Over-broad scopes and shared accounts</td>
<td>Narrow consent, per-tool rules per role, frozen arguments</td>
<td>Admins, with a control plane</td>
</tr>
<tr>
<td>Unvetted community and local servers</td>
<td>First-party connectors, an inventory, client sandboxing</td>
<td>IT and endpoint security</td>
</tr>
<tr>
<td>Tool sprawl</td>
<td>Search instead of a long list, restrictions applied first</td>
<td>The control plane</td>
</tr>
<tr>
<td>Missing audit</td>
<td>One record per executed call, naming the person, client and account</td>
<td>The control plane</td>
</tr>
<tr>
<td>Access that outlives the person</td>
<td>Grant revocation on removal</td>
<td>IT, with a control plane</td>
</tr>
</tbody>
</table>
<h2 id="how-does-prompt-injection-reach-an-agent-through-tool-results">How does prompt injection reach an agent through tool results?</h2>
<p>Through content the agent reads. A ticket, email or document can contain text written as an instruction, and the model may follow it. OWASP's <a href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/">LLM01 Prompt Injection</a> calls this indirect injection, and says it is unclear whether any method prevents it fully.</p>
<p>Example: a support ticket tells the assistant summarizing it to email the customer list to an outside address. If the agent holds a tool that can do that, the instruction has somewhere to go.</p>
<p>Elaichi does not stop this, because an MCP server never sees the user's prompt. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call.</p>
<p>OWASP lists least privilege and human approval for high-risk actions among its mitigations. In Elaichi, a restriction can withhold named write tools, or a whole connector, from a role, and every call that reaches execution leaves a record. Approval for writes belongs in the client, as <a href="/blog/human-approval-for-ai-agent-actions/">human approval for agent actions</a> explains.</p>
<h2 id="what-are-tool-poisoning-and-rug-pulls">What are tool poisoning and rug pulls?</h2>
<p>Tool poisoning hides instructions in a tool's description, which the model reads in full and the person rarely sees. A rug pull is a server changing a description after you approved it.</p>
<p><a href="https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks">Invariant Labs described both in April 2025</a>. Their test server offered a harmless-looking <code>add</code> tool to Cursor. Its description told the agent to read the user's MCP config file and SSH private key and pass them out. OWASP lists the same attack as MCP03, Tool Poisoning. Invariant recommends showing users full descriptions and pinning server versions by hash.</p>
<p>Elaichi authors, maintains and serves most of its connectors from its own infrastructure, and their tool descriptions come from one accountable vendor. A native MCP connector is different: its tool names and descriptions come from the vendor's own server, per connection, so that vendor is accountable for them. A custom connector is written by the organization that creates it. Allow rules also bind the operation, not the label, because whoever edits a connector's documentation can rename a tool.</p>
<p>A custom connector forked from a public one takes upstream changes only through a review, where conflicts and destructive removals start unchecked. A description is still text the model reads, so an accountable author narrows who writes it, not how the model treats it.</p>
<h2 id="what-are-token-passthrough-and-the-confused-deputy-problem">What are token passthrough and the confused deputy problem?</h2>
<p>Token passthrough is a server forwarding a client's token to a downstream API without checking it was issued for itself. The MCP specification forbids it: a server must not accept tokens that were not issued for it.</p>
<p>In the confused deputy attack, a proxy holds one OAuth app (OAuth is the standard for delegated sign-in) at a third party, lets clients register themselves, and the third party remembers consent in a cookie. An attacker registers a client with their own redirect address and sends the user a link. Consent is skipped, and the code lands with the attacker. The specification's fix is per-client consent naming the client, its scopes and its redirect address, plus exact redirect matching.</p>
<p>In Elaichi, the client holds an Elaichi grant, never the app's credential, and each authorization request lands on a consent screen that names the app, requires PKCE and matches the redirect address exactly. <a href="/blog/mcp-security-review-checklist/">The review checklist</a> lists what a consent screen should show.</p>
<h2 id="why-are-personal-api-keys-in-local-mcp-configs-a-risk">Why are personal API keys in local MCP configs a risk?</h2>
<p>A key in a file is a long-lived secret that anyone with the file can use, and it does not end when its owner leaves. OWASP's MCP01, Token Mismanagement and Secret Exposure, names hard-coded secrets in config files, long-lived tokens and shared service accounts.</p>
<p>Invariant Labs' tool-poisoning test targeted exactly that file, so a key stored there can leave with it.</p>
<p>Elaichi puts no secret in the config. The address, <code>https://api.elaichi.ai/mcp</code>, is the same for every organization and carries no token. Each person signs in with OAuth.</p>
<p>Elaichi stores only a keyed hash of each token, and app credentials live in a separate credential service, encrypted at rest with AES-256-GCM (<a href="/blog/mcp-security-review-checklist/">the checklist</a> has the detail). As a backstop, tool results pass through a scrubber that replaces values under secret-named keys, such as <code>api_key</code> or <code>password</code>, with <code>[redacted]</code>. <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth versus long-lived keys</a> compares the two, and <a href="/blog/replace-personal-mcp-servers/">replacing personal MCP servers</a> covers finding them on laptops.</p>
<h2 id="where-do-over-broad-scopes-and-shared-accounts-go-wrong">Where do over-broad scopes and shared accounts go wrong?</h2>
<p>A broad token turns one leak into access to everything it covers, and a shared account hides who acted. The MCP specification's scope minimization section warns that a stolen broad token enables lateral access. It recommends starting small and asking for more when needed. OWASP's MCP02 calls the slow version privilege escalation via scope creep.</p>
<p>The common failure is one admin-scoped service account in the CRM, used by five people's agents. The CRM's log then shows one name for every change.</p>
<p>On Elaichi's consent screen, delete is never pre-ticked and a client that requests no scope gets read only. <a href="/blog/mcp-security-review-checklist/">The checklist's consent questions</a> show what to ask any vendor.</p>
<p>The trade-off: a shared connection runs on its owner's credential, so calls through it reach the app as that account. Sharing one connection with the whole organization rebuilds the shared account. Where the app's own permissions matter, have each person connect their own account.</p>
<h2 id="how-do-you-enforce-least-privilege-for-ai-agents-across-saas-apps">How do you enforce least privilege for AI agents across SaaS apps?</h2>
<p>Run each call as the person who made it, then narrow it by role and by tool on the server, not in the prompt. OWASP's <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">LLM06 Excessive Agency</a> traces agent damage to excess functionality, permissions and autonomy. It recommends acting in the user's own context, with authorization enforced downstream rather than by the model.</p>
<p>Each Elaichi member holds exactly one role, and restrictions decide which connectors and which individual tools a target may reach. Rules are enforced at execution, and a change takes about two minutes. <a href="/blog/per-tool-vs-per-app-restrictions/">Restricting one tool or the whole app</a> works through six cases.</p>
<p>Where a tool is right but one argument is dangerous, a frozen parameter locks it, such as the payee on a payment tool. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</p>
<h2 id="why-are-unvetted-community-mcp-servers-a-supply-chain-risk">Why are unvetted community MCP servers a supply chain risk?</h2>
<p>Installing a server means running someone else's code with your client's privileges, or sending your data to someone else's host. The MCP specification's local server section describes malicious startup commands and data exfiltration. It requires clients to show the exact command and get consent first, and recommends sandboxing.</p>
<p>OWASP's MCP09, Shadow MCP Servers, sets a blunt test: if security cannot list every active server, unapproved ones already exist.</p>
<p>Elaichi leaves nothing to install. The catalog runs to 600+ connectors, most authored and served by Elaichi and the rest vendors' own MCP servers it governs. A control plane never sees a server someone installs on a laptop, though. That stays with endpoint controls and client policy. <a href="/blog/mcp-registry-vs-first-party-connectors/">First-party connectors against a registry</a> covers the authorship trade-off.</p>
<h2 id="does-tool-sprawl-make-an-agent-less-safe">Does tool sprawl make an agent less safe?</h2>
<p>Yes. Every tool an agent does not need is functionality OWASP's Excessive Agency entry tells you to remove. <a href="/blog/context-window-problem-mcp-tools/">Why long tool lists fill the context window</a> has the detail.</p>
<p>Search also fails without a relevance floor, returning a tool from an app nobody asked about, which the model then calls. Elaichi's search requires a match to carry at least half the query's weight.</p>
<p>In Elaichi, connected tools are never listed one by one, however few there are. The model finds a tool with <code>search_tools</code> and runs it with <code>execute_tool</code>. A restricted tool is withheld from the tool list and cannot be called. Search names it only as restricted, with no schema.</p>
<h2 id="what-happens-when-nobody-can-say-what-an-agent-did">What happens when nobody can say what an agent did?</h2>
<p>The incident review stalls, and nobody can prove access ended. OWASP's MCP08, Lack of Audit and Telemetry, warns that without logs there is no trace of agent actions.</p>
<p>Elaichi records one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the person, the client that made the call, the account actually reached and the outcome. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an agent audit log needs</a> lists the rest.</p>
<p>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the person's next call fails, and <a href="/blog/offboarding-when-the-agent-holds-access/">a contractor's last day</a> walks through the rest of the order.</p>
<h2 id="where-do-you-start-a-vendor-review">Where do you start a vendor review?</h2>
<p>Send every vendor the same written questions, then test the answers. Ask how people sign in, where credentials live, what consent pre-ticks and how fast access ends. Revoke a grant and confirm the next call fails. Then change a rule and time how long it takes.</p>
<p>The <a href="/blog/mcp-security-review-checklist/">ten-question MCP security review</a> has each question and what a good answer looks like.</p>
<h2 id="when-do-you-not-need-a-control-plane-for-these-risks">When do you not need a control plane for these risks?</h2>
<p>When nobody has connected an AI client to a company system yet. Copying and pasting into an assistant is a content problem, and DLP (data loss prevention) fits it better, as <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">what a CASB can see</a> explains.</p>
<p>One team using one app may not need one either, because many apps ship their own MCP server under their own permissions. That holds until a second app or client arrives and you need one set of rules across them. <a href="/blog/what-is-an-mcp-control-plane/">What an MCP control plane is</a> sets out that shape, and the <a href="/connectors/">connector catalog</a> shows which apps it covers.</p>
<h2>FAQ</h2><dl><dt><strong>What are the main MCP security risks for a company?</strong></dt><dd>The recurring ones are prompt injection through content the agent reads, poisoned or silently changed tool descriptions, token passthrough and the confused deputy problem, personal API keys in local config files, over-broad scopes and shared accounts, unvetted community servers, tool sprawl, and missing audit records. Most are fixed on the server side by per-person sign-in, narrow grants and a record of each call that runs. Prompt injection is the exception: it happens inside the model, so least privilege and human approval limit the damage rather than prevent it.</dd><dt><strong>What is MCP tool poisoning?</strong></dt><dd>Tool poisoning hides instructions in an MCP tool's description. The model reads the full description and the person usually sees only the tool's name, so the hidden text can steer the agent, for example toward reading a local key file and sending it out. A rug pull is the same attack delivered later, when a server changes a description after it was approved. The defenses are tools from an accountable author, showing the full description, pinning server versions, and access rules that bind the operation rather than the tool's label.</dd><dt><strong>Is token passthrough allowed in MCP?</strong></dt><dd>No. The MCP specification forbids it. An MCP server must not accept a token that was not issued for that server, and it must not forward a client's token to a downstream API. Passing tokens through breaks the audience boundary, lets a stolen token use the server as a proxy, and leaves the downstream log showing the wrong identity.</dd><dt><strong>How do you enforce least privilege for AI agents across SaaS apps?</strong></dt><dd>Run each call as the person who made it, with their own OAuth grant, and decide on the server which tools each role may reach. In Elaichi, every member holds one role, restrictions name which connectors and which individual tools a role or user may reach, delete access is never pre-ticked on the consent screen, and a frozen parameter can lock one argument, such as a payee, so the model cannot change it. A role or restriction change takes about two minutes to apply.</dd><dt><strong>Does Elaichi protect against prompt injection?</strong></dt><dd>No. An MCP server never sees the user's prompt, so it cannot judge whether an instruction came from the person or from content the model read. What Elaichi enforces limits what an injected instruction can reach: role-based permissions per operation, per-tool restrictions, OAuth scope limits with delete never pre-ticked, and an audit record for every call that reaches execution. Approval for writes belongs in the AI client.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Replace personal MCP servers on employee laptops</title>
      <link>https://elaichi.ai/blog/replace-personal-mcp-servers/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/replace-personal-mcp-servers/</guid>
      <description>Find the MCP servers employees run from each client&apos;s config file, then replace personal MCP servers and their tokens with one governed endpoint.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Local MCP servers live in config files on disk: claude_desktop_config.json, .cursor/mcp.json, .vscode/mcp.json and .mcp.json, often with a personal API token beside them. An MDM script can read those files and report server names and token key names, but Elaichi does not scan laptops. To replace personal MCP servers, connect each app once in Elaichi, swap every config to the one organization endpoint with per-person OAuth sign-in, then revoke the old tokens in each app.</aside>
<p>A security lead wants to replace personal MCP servers with something the company can audit. First comes one list: every MCP server on a company laptop. Say the endpoint team's script comes back with config files on 90 machines. Most entries look like this one:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">  "</span><span style="color:#D7B46A">mcpServers</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">    "</span><span style="color:#D7B46A">jira</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">command</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">npx</span><span style="color:#928D84">"</span><span style="color:#928D84">,</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">args</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> [</span><span style="color:#928D84">"</span><span style="color:#7BC496">-y</span><span style="color:#928D84">"</span><span style="color:#928D84">,</span><span style="color:#928D84"> "</span><span style="color:#7BC496">a-community-jira-server</span><span style="color:#928D84">"</span><span style="color:#928D84">],</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">env</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span><span style="color:#928D84"> "</span><span style="color:#D7B46A">JIRA_API_TOKEN</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">&#x3C;one engineer's personal token></span><span style="color:#928D84">"</span><span style="color:#928D84"> }</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">  }</span></span>
<span class="line"><span style="color:#928D84">}</span></span></code></pre>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. That entry starts a program on the laptop and gives it one person's Jira token. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports">MCP transport spec</a> calls this stdio: the client launches the server as a subprocess and talks to it over standard input and output. Jira sees only that engineer's token, no company system records which assistant made the call, and the token works until someone revokes it.</p>
<p>To replace personal MCP servers, connect each app once in Elaichi, point every client at <code>https://api.elaichi.ai/mcp</code>, then revoke the old tokens. This post covers both halves: finding the servers, then swapping them.</p>
<h2 id="how-do-you-find-which-mcp-servers-employees-have-installed">How do you find which MCP servers employees have installed?</h2>
<p>Read the config files each AI client keeps on disk. Most store them in JSON and Codex uses TOML, at paths its vendor documents.</p>
<table>
<thead>
<tr>
<th>Client</th>
<th>Where its MCP servers are listed</th>
</tr>
</thead>
<tbody>
<tr>
<td>Claude Desktop</td>
<td><code>~/Library/Application Support/Claude/claude_desktop_config.json</code> (macOS), <code>%APPDATA%\Claude\claude_desktop_config.json</code> (Windows)</td>
</tr>
<tr>
<td>Cursor</td>
<td><code>~/.cursor/mcp.json</code> (all projects), <code>.cursor/mcp.json</code> (one project)</td>
</tr>
<tr>
<td>VS Code</td>
<td><code>.vscode/mcp.json</code> or a root <code>.mcp.json</code> (workspace), <code>mcp.json</code> in the user profile, <code>~/.copilot/mcp-config.json</code> (Copilot Global)</td>
</tr>
<tr>
<td>Claude Code</td>
<td><code>~/.claude.json</code> (user and local scope), <code>.mcp.json</code> (project)</td>
</tr>
<tr>
<td>Windsurf (Devin Desktop)</td>
<td><code>~/.config/devin/mcp_config.json</code>, <code>%APPDATA%\devin\mcp_config.json</code> (Windows), <code>.devin/mcp_config.json</code> (project)</td>
</tr>
<tr>
<td>Codex</td>
<td><code>~/.codex/config.toml</code>, <code>.codex/config.toml</code> (project; TOML, <code>[mcp_servers.&#x3C;name>]</code> tables)</td>
</tr>
</tbody>
</table>
<p>The sources are the <a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">MCP guide to local servers</a> for Claude Desktop, <a href="https://cursor.com/docs/mcp">Cursor's MCP docs</a>, <a href="https://code.visualstudio.com/docs/copilot/customization/mcp-servers">VS Code's MCP guide</a> and <a href="https://code.claude.com/docs/en/mcp">Claude Code's MCP docs</a>, <a href="https://docs.devin.ai/desktop/cascade/mcp">Devin Desktop's MCP docs</a>, <a href="https://docs.devin.ai/cli/extensibility/mcp/configuration">Devin CLI's MCP configuration</a> and <a href="https://learn.chatgpt.com/docs/extend/mcp?surface=cli">Codex's MCP docs</a>, all checked October 2026.</p>
<p>Project files matter as much as home-directory files. A <code>.cursor/mcp.json</code> or <code>.mcp.json</code> committed to a repository puts the same server on every clone.</p>
<h2 id="what-should-an-endpoint-script-report-from-each-file">What should an endpoint script report from each file?</h2>
<p>Server names, the command or URL, and the names of credential keys. Never the values.</p>
<p>An entry with <code>command</code> is a stdio server that runs on the laptop. An entry with <code>url</code> is a remote server. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a> says stdio servers should take credentials from the environment, so look in <code>env</code>, in <code>envFile</code>, and in <code>headers</code> on remote entries. This loop reads every config under a home directory with <code>jq</code> and prints one line per server:</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#D7B46A">find</span><span style="color:#928D84"> "$</span><span style="color:#7BC496">HOME</span><span style="color:#928D84">"</span><span style="color:#7BC496"> \(</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> claude_desktop_config.json</span><span style="color:#7BC496"> -o</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> mcp.json</span><span style="color:#7BC496"> -o</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> .mcp.json</span><span style="color:#7BC496"> \</span></span>
<span class="line"><span style="color:#7BC496">  -o</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> .claude.json</span><span style="color:#7BC496"> -o</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> mcp_config.json</span><span style="color:#7BC496"> -o</span><span style="color:#7BC496"> -name</span><span style="color:#7BC496"> mcp-config.json</span><span style="color:#7BC496"> \)</span><span style="color:#7BC496"> -not</span><span style="color:#7BC496"> -path</span><span style="color:#928D84"> "</span><span style="color:#7BC496">*/node_modules/*</span><span style="color:#928D84">"</span><span style="color:#D7B46A"> 2></span><span style="color:#7BC496">/dev/null</span><span style="color:#D7B46A"> |</span></span>
<span class="line"><span style="color:#D7B46A">while</span><span style="color:#7BC496"> read</span><span style="color:#7BC496"> -r</span><span style="color:#7BC496"> f</span><span style="color:#928D84">;</span><span style="color:#D7B46A"> do</span></span>
<span class="line"><span style="color:#D7B46A">  jq</span><span style="color:#7BC496"> -r</span><span style="color:#7BC496"> --arg</span><span style="color:#7BC496"> f</span><span style="color:#928D84"> "$</span><span style="color:#7BC496">f</span><span style="color:#928D84">"</span><span style="color:#928D84"> '</span><span style="color:#7BC496">.. | objects | (.mcpServers? // .servers? // empty) | to_entries[]</span></span>
<span class="line"><span style="color:#7BC496">    | [$f, .key, (.value.command // .value.url // "?"),</span></span>
<span class="line"><span style="color:#7BC496">       ((.value.env // {}) + (.value.headers // {}) | keys | join(","))] | @tsv</span><span style="color:#928D84">'</span><span style="color:#928D84"> "$</span><span style="color:#7BC496">f</span><span style="color:#928D84">"</span></span>
<span class="line"><span style="color:#D7B46A">done</span></span></code></pre>
<p>Codex keeps servers in TOML, so list them with <code>grep -n '^\[mcp_servers' ~/.codex/config.toml</code>.</p>
<p>It prints key names such as <code>JIRA_API_TOKEN</code> and leaves the secret on the laptop. Two cases hide the secret from the file. Cursor can interpolate <code>${env:NAME}</code> from the shell, and VS Code can prompt for a password input and store it. A key name with no value still tells you a token exists.</p>
<h2 id="what-can-device-policy-turn-off-and-what-can-it-not-see">What can device policy turn off, and what can it not see?</h2>
<p>Some clients take a policy that turns local servers off. None of them tells you which tokens already leaked.</p>
<ul>
<li><strong>Claude Desktop.</strong> On Team and Enterprise plans, <code>isLocalDevMcpEnabled</code> is a Boolean that defaults to true (<a href="https://support.claude.com/en/articles/12622667-enterprise-configuration-for-claude-desktop">Anthropic's enterprise configuration</a>, checked October 2026). Set it through a configuration profile on macOS or Group Policy on Windows.</li>
<li><strong>VS Code.</strong> The <code>ChatMCP</code> policy sets <code>chat.mcp.access</code> to <code>all</code>, <code>registry</code> or <code>none</code> (<a href="https://code.visualstudio.com/docs/enterprise/manage-ai-settings">VS Code enterprise settings</a>, checked October 2026).</li>
<li><strong>Cursor.</strong> Enterprise teams can allowlist the MCP servers members may use. Adding a server "does not push it to users' machines" (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor's enterprise docs</a>, checked October 2026).</li>
</ul>
<p>The limits are real. A personal laptop, a token in a shell profile, or a client you have not listed sits outside this view. Elaichi does not scan laptops either, and it has no feature that lists local servers. The inventory is your device management tool's job. <a href="/blog/mcp-security-risks/">The wider set of MCP security risks</a> covers what a local server can do beyond holding a token.</p>
<h2 id="how-do-you-replace-personal-mcp-servers-with-company-managed-ones">How do you replace personal MCP servers with company-managed ones?</h2>
<p>Connect each app once in Elaichi, then point every client at one organization endpoint where each person signs in with OAuth. The new config entry holds a URL and no token.</p>
<p>Elaichi is a governed MCP control plane. Its endpoint is <code>https://api.elaichi.ai/mcp</code>, the same address for every organization and every person. OAuth (the sign-in standard that gives a client a scoped grant instead of a password) ties each call to the person who approved it. Claude, ChatGPT, Cursor and any other MCP client all use that one address.</p>
<p>The app credentials leave the laptop. A separate credential service holds each connected account's secrets, encrypted at rest with AES-256-GCM, and owns token refresh. If a refresh fails, the connection is marked <code>needs_reauth</code> instead of failing silently.</p>
<p>Three layers decide what each person reaches:</p>
<ul>
<li><strong>A role</strong> sets what a member may do, and each member holds exactly one.</li>
<li><strong>Sharing</strong> decides what they can see: their own connections and those shared with them.</li>
<li><strong>A restriction</strong> decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</li>
</ul>
<p>Restrictions are checked at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A role or restriction change applies within about two minutes. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">Running your own MCP servers</a> compares the hosted path with keeping servers in-house.</p>
<h2 id="in-what-order-should-the-migration-run">In what order should the migration run?</h2>
<p>Inventory, pick the top apps, connect them, swap the configs, then revoke the old tokens. Revoking last means nobody loses access mid-week.</p>
<ol>
<li><strong>Inventory.</strong> Run the script and count servers by app. Start with the three to five apps that appear most often.</li>
<li><strong>Pick the top apps.</strong> Check each one in the <a href="/connectors/">connector catalog</a>, which lists 600+ connectors, most of them written by Elaichi. <a href="/connectors/jira/">Jira</a>, <a href="/connectors/notion/">Notion</a> and <a href="/connectors/sentry/">Sentry</a> are all in it.</li>
<li><strong>Connect them in Elaichi.</strong> With no restriction in place, a member can connect any catalog app with their own account. A shared connection runs on its owner's credential, so decide which apps should be personal and which shared. Write restrictions before people switch.</li>
<li><strong>Swap configs to the one URL.</strong> In Cursor the entry becomes <code>"url": "https://api.elaichi.ai/mcp"</code>. In Claude, an owner on Team or Enterprise adds it once as a custom connector, and members connect it. Each person signs in once.</li>
<li><strong>Revoke the old personal tokens.</strong> Do it in each app's own token settings, then delete the old entries and run the inventory again.</li>
</ol>
<p><a href="/blog/roll-out-claude-and-chatgpt-to-employees/">Rolling out Claude and ChatGPT to employees</a> covers the client-side steps per department.</p>
<h2 id="what-does-each-person-do-on-switch-day">What does each person do on switch day?</h2>
<p>Delete the old entry, add the one URL, and sign in. Nothing else goes in the config file.</p>
<p>The client registers itself with Elaichi through OAuth dynamic client registration, so nobody types a client ID, a secret or a header. A browser opens Elaichi's sign-in, and the person lands on a consent screen. With several organizations, they pick one, and that connection sees only that one.</p>
<p>The consent screen lists four boxes: read data, create and change data, run connected tools, and delete data. Every scope the client asked for is pre-ticked except delete, which never is. With "Run your connected tools" ticked, the person chooses all their tools or only the toolboxes they pick. Each person can later see and disconnect their own grants under Settings, then Connected apps.</p>
<h2 id="how-do-you-stop-employees-from-sharing-personal-api-keys-with-ai-tools">How do you stop employees from sharing personal API keys with AI tools?</h2>
<p>Give them a path that needs no key, then close the old one. A ban without a replacement moves the token to a shell profile.</p>
<p>The sanctioned path removes the reason to paste a key. In Elaichi, the person signs in with OAuth and the app credential sits in the credential service, not in a file on the laptop. Revocation is one action: removing or suspending a member revokes every live grant in the same transaction as the membership change, so that person's next call is refused.</p>
<p>Close the old path in three moves. Revoke the personal tokens the inventory found. Turn off local servers through device policy where the client supports one. Then rerun the inventory each month, because new configs appear when new tools ship.</p>
<p>Expect people to hit a rule they did not know about. In Elaichi, any member can file an access request when a restriction stops them, with no permission needed. Someone with <code>member:manage</code> resolves it, and approving it opens that connector or tool for that one person. A request is slower than a personal key, but it leaves a record and keeps the old path closed. <a href="/blog/oauth-vs-api-keys-for-ai-agents/">OAuth or API keys for AI agents</a> sets out why a revocable grant beats a long-lived string.</p>
<h2 id="what-does-the-audit-log-show-after-the-switch">What does the audit log show after the switch?</h2>
<p>Every connected-tool call through the endpoint that reaches execution, filed under the person who approved the sign-in, with the account it reached. A local server leaves only the app's own record of a personal token.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the connection the call actually reached and the outcome. It records the one path argument that names the object, as the target id, and nothing else about the arguments. It also records the surface, here <code>mcp</code>, and the OAuth client the call came through.</p>
<p>Claude, ChatGPT and Cursor show as verified client names. A client that signs in through a loopback address, such as Claude Code, shows the name it registered with, marked unverified. The call is recorded under the person, not as an AI actor. That settles the first question after an unexpected change: which of two Notion workspaces did the write reach. A compliance reviewer can read the trail from the free, read-only Auditor seat.</p>
<h2 id="when-should-a-personal-mcp-server-stay">When should a personal MCP server stay?</h2>
<p>When it reaches something only the laptop can reach. Elaichi is hosted, so it cannot read local files or a service on the developer's own machine.</p>
<p>A filesystem server, a local database or a build tool belongs on the laptop. So does an internal server for one team's own system. Some apps are not in the catalog at all. GitHub is one, so a team that needs it uses GitHub's own MCP server, which Elaichi does not govern, or writes a custom connector. Keep those servers on a short, named list and leave them out of the token revocation step.</p>
<p>For everything else, the swap is one URL per client. <a href="/blog/offboarding-when-the-agent-holds-access/">The offboarding guide</a> covers what happens to that access when someone leaves, and the wider <a href="/blog/category/shadow-ai/">Shadow AI</a> series covers the rest of the paper trail.</p>
<h2>FAQ</h2><dl><dt><strong>Where do Claude Desktop, Cursor and VS Code store MCP server settings?</strong></dt><dd>Claude Desktop uses claude_desktop_config.json, under ~/Library/Application Support/Claude on macOS and %APPDATA%\Claude on Windows. Cursor reads ~/.cursor/mcp.json for every project and .cursor/mcp.json inside a project. VS Code reads .vscode/mcp.json or a root .mcp.json in a workspace, plus an mcp.json in the user profile. Claude Code keeps servers in ~/.claude.json and in a project's .mcp.json.</dd><dt><strong>Can Elaichi detect the MCP servers installed on employee laptops?</strong></dt><dd>No. Elaichi is a hosted MCP control plane and does not scan devices. Use your device management tool to read each client's config file. Elaichi covers the other half: once people use its one organization endpoint, every connected-tool call that reaches execution lands in its audit log, attributed to the person who connected.</dd><dt><strong>Is a local stdio MCP server a security risk?</strong></dt><dd>It can be. A stdio server is a program the AI client starts on the laptop, and it runs with that user's permissions. The MCP specification says stdio servers take their credentials from the environment, so the token usually sits in a config file or shell profile. The app it calls sees only the token's owner, not which assistant made the call.</dd><dt><strong>How do you stop employees putting personal API keys in AI tools?</strong></dt><dd>Give them a path that needs no key, then close the old one. A governed endpoint signs each person in with OAuth and keeps app credentials in a separate service. After the swap, revoke the personal tokens in each app and use device policy, such as Claude Desktop's isLocalDevMcpEnabled or VS Code's ChatMCP policy, to turn off local servers.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>How to roll out Claude and ChatGPT to employees</title>
      <link>https://elaichi.ai/blog/roll-out-claude-and-chatgpt-to-employees/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/roll-out-claude-and-chatgpt-to-employees/</guid>
      <description>Roll out Claude and ChatGPT to employees in order: approve apps, connect them once, build team toolboxes, map roles, pilot, onboard and offboard.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To roll out Claude and ChatGPT to employees with company tools, connect each approved app once in Elaichi and point every client at one organization-wide endpoint. Teams decide what each department uses, roles and restrictions decide what it may reach, and a role or restriction change takes effect within about two minutes. Pilot one team, read the audit log, then onboard everyone through invites, domain auto-join, SCIM or just-in-time SSO.</aside>
<p>The usual starting point is a pile of tickets. Sales pastes pipeline notes into ChatGPT. An engineer runs a Jira server on a laptop for Cursor. HR asks whether Claude can read Rippling. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The job is to replace that pile with one path the company owns.</p>
<h2 id="how-do-you-roll-out-claude-and-chatgpt-to-employees-without-a-server-per-person">How do you roll out Claude and ChatGPT to employees without a server per person?</h2>
<p>Connect each approved app once, behind one organization-wide endpoint, and let each person sign in to it from their own client. Then decide reach with team sharing, roles and restrictions, and check the result in the audit log.</p>
<p>Elaichi is built for that path. Claude, ChatGPT, Cursor and any other MCP client all reach the same address, <code>https://api.elaichi.ai/mcp</code>. There are no per-person URLs, tokens or servers. Each member still connects once and signs in with their own OAuth grant, the revocable permission a client receives at sign-in. For the engineering case, see <a href="/blog/shadow-ai-cto-engineers-already-have-chatgpt/">what happens when engineers already have ChatGPT</a>.</p>
<h2 id="how-does-a-head-of-it-approve-which-apps-employees-can-connect-to-claude">How does a head of IT approve which apps employees can connect to Claude?</h2>
<p>Write an allow rule for each role that names the approved connectors. In Elaichi, a connector the rule does not name is then refused at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A member cannot connect it or call it, from any client.</p>
<p>Start with a list of the apps people already use with AI. Mark each one approved for everyone, approved for one department, or not yet. The <a href="/connectors/">connector catalog</a> holds 600+ connectors, most authored by Elaichi and some run by the app's own vendor.</p>
<p>Then turn the list into restrictions. A restriction decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. That default matters here. The Member role holds <code>connection:create</code>, so with no rule a member can connect any app in the catalog with their own account.</p>
<p>One trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Save the allow rule with its connectors already in it.</p>
<p>A member who meets a restricted connector can file an access request. Approving a request opens that connector or tool for that one person only, and the role's other rules keep binding them. An administrator cannot decide their own request, so a second person signs off.</p>
<h2 id="which-it-admin-controls-do-claude-chatgpt-and-cursor-give-you-for-mcp">Which IT admin controls do Claude, ChatGPT and Cursor give you for MCP?</h2>
<p>Each client controls how a server reaches its own users. Elaichi controls what is behind the server. You add the one address in each client, and the rules on roles, apps and tools live in one place behind it.</p>
<p>Here is what each vendor documents:</p>
<ul>
<li><strong>Claude.</strong> On Team plans, only Owners and Primary Owners add a custom connector, under Organization settings > Connectors > Add > Custom > Web. Members then connect it themselves under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's help center</a>, checked October 2026).</li>
<li><strong>ChatGPT.</strong> Full MCP support, including write actions, is a beta on Business, Enterprise and Edu. An admin creates the app under Workspace settings > Apps > Create and publishes it. It then appears in users' Apps settings labeled custom, and OpenAI says functionality, UI and permissions may change (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help center</a>, checked October 2026).</li>
<li><strong>Cursor.</strong> Enterprise admins can allowlist MCP servers, but the allowlist does not push a server to anyone's machine. Team admins can instead distribute a server through a team marketplace, where teammates install and configure it themselves (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor's enterprise docs</a> and <a href="https://cursor.com/docs/mcp">MCP docs</a>, checked October 2026).</li>
</ul>
<p>Those are distribution controls, one per client. Elaichi's restrictions sit behind the endpoint, so one rule holds for every client. The per-client steps are in <a href="/blog/connect-elaichi-to-claude/">the Claude setup guide</a>, the <a href="/blog/connect-elaichi-to-chatgpt/">ChatGPT walkthrough</a> and <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">Cursor for a whole team</a>.</p>
<h2 id="how-does-a-platform-team-centrally-manage-mcp-servers-for-the-whole-company">How does a platform team centrally manage MCP servers for the whole company?</h2>
<p>By not running any. Elaichi runs the connectors it authors and governs vendors' own MCP servers for the rest, so the platform team manages connections, sharing and rules instead of servers, versions and tokens.</p>
<p>Connect each company account once. Connector credentials do not live in Elaichi. A separate credential service holds them, encrypted at rest with AES-256-GCM, and owns token refresh. A failed refresh marks the connection Needs sign-in rather than failing silently.</p>
<p>Ownership is the next decision. A connection can stay private to one person, or be shared at <code>use</code> with a team or the whole organization. A shared connection runs on its owner's credential, so every call through it reaches the app as that account. Share one team-wide only when the whole team is meant to act as that account. For per-person access, share a template and let each person stamp it against their own account. A member sees only what they own or what was shared with them, admins included. Treat <code>connector:create</code> as high trust, because a custom connector can be pointed at any destination.</p>
<h2 id="how-do-you-give-sales-engineering-and-hr-different-ai-tool-access">How do you give sales, engineering and HR different AI tool access?</h2>
<p>Use teams for what each department uses, and roles with restrictions for what each department may reach. In Elaichi, a team is a named group you share connections, toolboxes and templates with.</p>
<p>A toolbox is a saved set of tool entries, each pairing one tool with one connected account. A template is the same tool list with no accounts in it, carrying tool renames, defaults and frozen arguments. Teammates with <code>use</code> on a template stamp their own toolbox from it and pick their own connections. Stamping copies the template once, so a later edit leaves stamped toolboxes alone.</p>
<p>A workable split for three departments:</p>
<ul>
<li><strong>Sales.</strong> Build a <a href="/connectors/salesforce/">Salesforce</a> template and share it with Sales at <code>use</code>. Each rep stamps a toolbox against their own Salesforce account, so Salesforce's own permissions still apply per rep. The <a href="/blog/sales-team-chatgpt-salesforce-accounts/">sales playbook</a> covers which tools to restrict.</li>
<li><strong>Engineering.</strong> Build a <a href="/connectors/jira/">Jira</a> template with the issue tools engineers use, renamed in the team's own words. Share it with Engineering, and each engineer stamps a toolbox against their own Jira account.</li>
<li><strong>HR.</strong> Connect <a href="/connectors/rippling/">Rippling</a> as a private connection, pin it into a toolbox with frozen arguments, and share only the toolbox with HR. Every call runs on the owner's Rippling account, so choose an owner whose access fits the whole team and who will stay. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. The <a href="/blog/hr-team-claude-rippling-employees/">HR team's setup</a> works through it.</li>
</ul>
<p>Teams carry shares, not rules. Restrictions target roles and users, never teams. Where two departments need different restrictions, give each its own custom role. Each person can also narrow a client at consent, from the default All my tools to Only the ones I pick, up to 50 toolboxes.</p>
<h2 id="which-roles-and-restrictions-should-each-department-start-with">Which roles and restrictions should each department start with?</h2>
<p>Start every working seat on Member, and add a custom role only where a department's restrictions must differ. Each member holds exactly one role, so a department role has to describe a whole job.</p>
<p>Member is the working seat. Team Admin adds managing teams, and People Admin adds managing members. Guest, Billing Admin and Auditor lack <code>tool:execute</code>, so they cannot call a tool at all. Auditor is a free, read-only seat. <a href="/blog/designing-roles-for-ai-agents/">Designing one role per person</a> covers the reasoning.</p>
<p>If your directory is the source of truth, map groups to roles. SCIM is how a directory pushes users and groups into an app, and in Elaichi each group mapping can confer at most one role. The Sales group lands on the sales role, Engineering on the engineering role. <a href="/blog/identity-provider-scim-vs-mcp-grants/">Where SCIM provisioning stops</a> explains what a group cannot express.</p>
<p>Then write the rules for each role. Allow the approved connectors, and restrict the destructive tools a role does not need. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. <a href="/blog/per-tool-vs-per-app-restrictions/">Tool rules versus app rules</a> works through six cases.</p>
<p>A role or restriction change takes effect within about two minutes, on MCP, the console and REST alike.</p>
<h2 id="what-should-a-one-team-pilot-prove-before-the-company-wide-rollout">What should a one-team pilot prove before the company-wide rollout?</h2>
<p>It should prove that the rules match the calls people actually make. Pick one team with a clear need, run it for two weeks, and read the audit log instead of collecting opinions. If the pilot keeps stalling, read <a href="/blog/why-ai-pilots-fail/">why AI pilots fail</a>.</p>
<p>Sales makes a good pilot, with one main app and clear read and write tools. Before day one, give one reviewer the Auditor seat, so the record has a reader who cannot act.</p>
<p>The audit log is the chronological record of who did what. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and each entry names the account the call actually reached. A call from Claude, ChatGPT or Cursor is recorded under the employee who signed in, with the client it came through. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p>Read the log for three things. Tools nobody called can leave the toolbox. Access requests show a rule that is too tight. Calls to an unexpected account show a sharing gap. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> lists the fields to check.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The pricing page shows what each plan includes and how the 14-day trial works, so you can run the pilot before anyone buys a seat.</p><a href="/pricing/" class="cta-button">See plans and the free trial</a></aside>
<h2 id="how-does-a-new-hires-assistant-get-the-right-app-access-automatically">How does a new hire's assistant get the right app access automatically?</h2>
<p>Through the role and the shares they arrive with. Elaichi has four ways in, and each one sets a role on day one.</p>
<table>
<thead>
<tr>
<th>Path</th>
<th>Role on arrival</th>
<th>Teams on arrival</th>
</tr>
</thead>
<tbody>
<tr>
<td>Emailed single-use invite</td>
<td>Preset by the inviter</td>
<td>Preset by the inviter</td>
</tr>
<tr>
<td>Verified-domain auto-join</td>
<td>The domain's default role</td>
<td>Added afterward</td>
</tr>
<tr>
<td>Just-in-time SSO</td>
<td>The SSO connection's default role</td>
<td>Added afterward</td>
</tr>
<tr>
<td>SCIM provisioning</td>
<td>The role mapped to the person's group</td>
<td>Added afterward</td>
</tr>
</tbody>
</table>
<p>Where no default role is configured, an automatic join lands on Member. Anything shared with the whole organization reaches the new hire at once. A team share reaches them within about two minutes of being added to the team. SCIM and group mapping set the role, not team membership, so a Team Admin or above adds the person to their team. Keep that step in the joiner checklist.</p>
<p>The new hire then connects each client once and signs in. The default consent choice, All my tools, also picks up connections shared with the person later, so team shares arrive without reconnecting.</p>
<h2 id="how-do-you-close-ai-access-when-an-employee-leaves">How do you close AI access when an employee leaves?</h2>
<p>Suspend or remove the member, and their very next call is refused. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call with no cache.</p>
<p>A SCIM deprovision suspends the member and never removes them. Removal is a separate step in Elaichi, and it runs a preflight. A shared connection can go to one colleague, or be deleted if the admin asks. Nothing transfers to the organization or a team. A private connection that nothing beyond the person depends on cannot be transferred and is deleted with them. A private connection that a shared toolbox depends on blocks removal until an administrator transfers it to a member. So the person who connects HR's private Rippling account should be someone who will stay.</p>
<p>Removal ends access through Elaichi, nothing more. The person's account inside each app still exists, and it is closed there or through the identity provider. <a href="/blog/offboarding-when-the-agent-holds-access/">The offboarding runbook</a> walks through a contractor case. Then check the audit log, where a removed member's past calls stay, labeled Former member.</p>
<h2 id="when-do-you-not-need-a-control-plane-for-this-rollout">When do you not need a control plane for this rollout?</h2>
<p>When one team uses one app and that app's own MCP server already does the job. Several vendors now host one, and it runs under the app's own permissions with no second vendor.</p>
<p>Notion is a fair example. Notion describes its server as "a remote MCP server hosted by Notion", where the client can read and update content the person can access. Workspace owners manage client access under Settings > Connections (<a href="https://developers.notion.com/docs/mcp">Notion's docs</a>, checked October 2026). For a product team living in Notion alone, that may be enough.</p>
<p>The case changes at the second app or the second team. Then you want one address across vendors, rules written once per role, and one audit trail. If no assistant can write to a company system yet, read <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting</a> first. Know one limit as well. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call.</p>
<p>As of October 2026, SSO, SCIM, group-to-role mapping and custom roles are on Gold, and the 14-day trial unlocks all of them. Gold lists at $15 per user per month in USD, and <a href="/pricing/">pricing</a> shows your local price and the trial terms. More governance posts sit under <a href="/blog/category/governance/">governance</a>, and team-by-team starting points are on the <a href="/use-cases/">use cases page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>As head of IT, how do I approve which apps employees can connect to Claude?</strong></dt><dd>In Elaichi, write an allow rule for each role that names the approved connectors. A connector the rule does not name is then refused when a member browses for it, connects it or calls it, from Claude, ChatGPT, Cursor or any other MCP client. Save the rule with its connectors in it, because an allow rule that names nothing denies everything. A member who needs an app that is not approved can file an access request, and an administrator approves or denies it.</dd><dt><strong>What IT admin controls exist for MCP connectors across Claude, ChatGPT and Cursor?</strong></dt><dd>Each client's admin console decides how an MCP server reaches that client's users. Elaichi decides what is behind the server. Point all three clients at the one Elaichi endpoint, and the same roles, restrictions and audit log apply whichever client makes the call. A restriction can name a whole connector or single tools, and it targets a role or one user.</dd><dt><strong>How does a platform team centrally manage MCP servers for the whole company?</strong></dt><dd>With Elaichi, a platform team runs no MCP servers. Elaichi authors most connectors and governs vendors' own MCP servers for the rest, every client uses one organization-wide endpoint, and the team manages connections, sharing, roles and restrictions in one console. Connector credentials sit in a separate credential service that owns token refresh, and a failed refresh shows the connection as needing sign-in instead of failing silently.</dd><dt><strong>How do I onboard a new hire so their AI assistant gets the right app access automatically?</strong></dt><dd>In Elaichi, every onboarding path sets a role on day one. An emailed invite can preset both the role and the teams. Verified-domain auto-join and just-in-time SSO apply a configured default role, and SCIM applies the role mapped to the person's directory group. Anything shared with the whole organization reaches the new hire at once. A team share reaches them within about two minutes of being added to the team, and SCIM does not set team membership, so keep that step in the joiner checklist.</dd><dt><strong>How long does a role or restriction change take in Elaichi?</strong></dt><dd>A role or restriction change in Elaichi takes effect within about two minutes, on MCP, the console and the REST API alike. Removing or suspending a member is faster: the grant is re-read on every call, so the person's next call is refused. Revoking a share and disconnecting an account also take effect on the next call.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>What is an MCP control plane, and who needs one?</title>
      <link>https://elaichi.ai/blog/what-is-an-mcp-control-plane/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/what-is-an-mcp-control-plane/</guid>
      <description>An MCP control plane is one org-wide MCP endpoint that serves the tools, signs each person in and decides access on every call.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An MCP control plane is one organization-wide address that holds the connections, serves the tools and decides access on every call. A gateway fronts servers somebody else runs, and a registry only lists them. Elaichi is a governed MCP control plane: Claude, ChatGPT, Cursor and any other MCP client reach every connected app through https://api.elaichi.ai/mcp, with roles, restrictions, SSO, SCIM and an audit log on that one address.</aside>
<h2 id="why-are-companies-asking-for-an-mcp-control-plane">Why are companies asking for an MCP control plane?</h2>
<p>Because the number of AI setups grew faster than anyone could govern them. Support wants its help desk inside Claude. Finance wants the ledger inside ChatGPT. Engineering already works in Cursor. Many apps now ship an MCP server of their own, each AI client needs its own setup, and each person signs in to each pair. An MCP control plane is the category built to replace that grid with one address and one set of rules.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An MCP server is the service that offers those tools. An endpoint is the address a client is pointed at. Four AI clients and fifteen apps can mean sixty separate setups for one person, and sixty to undo on their last day.</p>
<p>The request that reaches IT usually sounds like this: one MCP endpoint for all our company apps, not dozens of separate servers, with SSO and a record of what the AI did. That request describes a control plane.</p>
<h2 id="what-is-an-mcp-control-plane">What is an MCP control plane?</h2>
<p>An MCP control plane is the one place a company decides which people, through which AI clients, may call which tools in which accounts. It is the one MCP address clients use. It holds the connections, serves the tools, and makes the access decision on every call.</p>
<p>The name comes from networking. In a router, the control plane builds the routing table that says what to do with incoming packets. The data plane, also called the forwarding plane, processes them (<a href="https://en.wikipedia.org/wiki/Control_plane">Wikipedia</a>). The MCP version keeps that split. The decisions about who may reach what live in one place. The calls themselves run against many SaaS accounts.</p>
<p>Elaichi is a governed MCP control plane. Every SaaS account a company uses is connected once. Claude, ChatGPT, Cursor and any other MCP client reach those accounts through one organization-wide endpoint, <code>https://api.elaichi.ai/mcp</code>. Governed means the roles, restrictions and audit log ship with that address, rather than being a project you add later.</p>
<p>Four properties separate a control plane from the products it gets confused with:</p>
<ol>
<li><strong>One address for the organization.</strong> The person's grant varies. The URL does not.</li>
<li><strong>The control plane serves the connectors.</strong> Nobody at your company runs an MCP server.</li>
<li><strong>Access is decided where the tool is served,</strong> on every call, not only at sign-in.</li>
<li><strong>One record per executed call,</strong> naming the person and the account that was actually reached.</li>
</ol>
<h2 id="mcp-control-plane-vs-mcp-gateway-vs-mcp-registry-what-is-the-difference">MCP control plane vs MCP gateway vs MCP registry: what is the difference?</h2>
<p>A registry lists MCP servers, a gateway sits in front of MCP servers, and a control plane is the MCP server. Self-hosted servers are the do-it-yourself baseline all three are measured against.</p>
<p>A registry answers "which servers exist". The official MCP Registry describes itself as a central store of metadata about publicly accessible MCP servers. It points to packages hosted elsewhere and leaves security scanning to package registries and the marketplaces built on top of it. It was marked as a preview when checked in October 2026 (<a href="https://modelcontextprotocol.io/registry/about">MCP Registry</a>). <a href="/blog/mcp-registry-vs-first-party-connectors/">Who fixes a registry server when it breaks</a> is the question that follows.</p>
<p>A gateway answers "how do I put one door in front of the servers I already have". The name covers several products with different mechanics, and <a href="/blog/what-is-an-mcp-gateway/">the four gateway shapes</a> are sorted separately. A control plane answers "how does the whole company reach its apps under one set of rules, without running servers".</p>
<table>
<thead>
<tr>
<th></th>
<th>Self-hosted servers</th>
<th>Registry</th>
<th>Gateway</th>
<th>Control plane</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who runs the servers</td>
<td>Your team</td>
<td>Each publisher, or you</td>
<td>The vendor or your team</td>
<td>Nobody at the company: the control plane vendor, or the app's vendor for its own MCP server</td>
</tr>
<tr>
<td>Who writes the connectors</td>
<td>Your team</td>
<td>Each publisher</td>
<td>Whoever runs the servers behind it</td>
<td>The control plane vendor</td>
</tr>
<tr>
<td>Addresses a client points at</td>
<td>One per server</td>
<td>None; it points to servers</td>
<td>One gateway, sometimes one per team</td>
<td>One for the organization</td>
</tr>
<tr>
<td>Where access is decided</td>
<td>Inside each server, if anywhere</td>
<td>Not its job</td>
<td>At the gateway, before forwarding</td>
<td>Where the tool is served, on each call</td>
</tr>
<tr>
<td>Who fixes a broken tool</td>
<td>Your on-call engineer</td>
<td>The publisher's queue</td>
<td>The server's owner</td>
<td>The control plane vendor</td>
</tr>
</tbody>
</table>
<p>Elaichi sits in the last column. It authors, maintains and serves most of its connectors from its own infrastructure, and governs vendors' own MCP servers for the rest. It is not a marketplace of third-party servers, not a gateway you deploy, and not an API gateway that added MCP as a feature. If your team already runs MCP servers, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">what running them yourself really costs</a> is worked through cost by cost.</p>
<h2 id="what-should-a-governed-mcp-control-plane-for-enterprises-include">What should a governed MCP control plane for enterprises include?</h2>
<p>At minimum: per-person sign-in, connectors the vendor maintains, layered access rules, an audit record per call, identity from your directory, and a clean offboarding path. Each item says how Elaichi does it, so a trial can check it.</p>
<ul>
<li><strong>Per-person OAuth with nothing to paste.</strong> OAuth is the sign-in standard that lets software act for a named person without holding their password. The MCP authorization spec builds on OAuth 2.1 for HTTP transports. It lets a client obtain a client ID through metadata documents, pre-registration or dynamic client registration (<a href="https://modelcontextprotocol.io/specification/latest/basic/authorization">MCP authorization spec</a>). The 2026-07-28 version of the spec marks dynamic client registration as deprecated and keeps it for backwards compatibility. Clients register themselves with Elaichi through dynamic client registration, with PKCE S256 required. There is no client ID, secret or header to enter.</li>
<li><strong>Connectors the control plane runs or governs.</strong> Elaichi serves 600+ connectors and authors most of them. Account credentials sit in a separate credential service, encrypted at rest, that owns token refresh.</li>
<li><strong>Three access layers kept apart.</strong> Role permissions, sharing on each resource, and restrictions on connectors and single tools.</li>
<li><strong>A record of each call that runs.</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and the entry names the account the call reached.</li>
<li><strong>Identity from your directory.</strong> SAML or OIDC single sign-on (SSO) and SCIM provisioning, with groups mapped to roles.</li>
<li><strong>An offboarding path.</strong> Suspension or removal cuts every live grant on the next call.</li>
<li><strong>Residency.</strong> Elaichi has three regions, EU, US and APAC, chosen when the organization is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. <a href="/blog/eu-data-residency-ai-agents/">EU data residency, leg by leg</a> lists what each region covers and what it does not.</li>
</ul>
<h2 id="how-does-one-mcp-endpoint-replace-dozens-of-separate-servers">How does one MCP endpoint replace dozens of separate servers?</h2>
<p>The address stays fixed and the grant changes per person. Every client points at <code>https://api.elaichi.ai/mcp</code>, and each member signs in once per client. That person's grant, role and shares decide what their calls can reach.</p>
<p>The mechanism is standard MCP. The endpoint is <code>POST /mcp</code>, speaking Streamable HTTP and JSON-RPC 2.0, stateless, behind OAuth. A client that calls it without a token gets a 401 with a challenge that starts sign-in. The person signs in, confirms the organization, and lands on a consent screen with four boxes: read data, create and change data, run connected tools, and delete data. Delete is never ticked in advance. With "Run your connected tools" ticked, the person picks <strong>All my tools</strong> or <strong>Only the ones I pick</strong>, up to 50 toolboxes. A toolbox is a saved set of tools and the accounts behind them.</p>
<figure class="mermaid-container"><pre class="mermaid">flowchart LR
  A["Claude"] --> E["One endpoint: api.elaichi.ai/mcp"]
  B["ChatGPT"] --> E
  C["Cursor"] --> E
  E --> G{"Grant still valid?"}
  G -- "no" --> X["401: sign in again"]
  G -- "yes" --> R{"Role, sharing and restrictions allow this tool?"}
  R -- "no" --> W["Call refused"]
  R -- "yes" --> K["Connector Elaichi authors"]
  K --> S["The connected SaaS account"]
  K --> L["Audit log entry"]</pre></figure>
<p>From then on, every call takes the same path. The grant is re-read on each call. The role must hold <code>tool:execute</code>. Sharing decides which accounts the person can reach. One resolver (the code that decides allow or deny) then applies restrictions. Only then does the connector reach the account.</p>
<p>A big catalog does not become a long tool list. In Elaichi, connected tools are never listed one by one, however few there are. The model finds a connected tool with <code>search_tools</code> and runs it with <code>execute_tool</code>, which passes the same checks as a direct call. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. <a href="/blog/one-endpoint-vs-per-team-endpoint/">One address against one per team</a> works through what this saves at 200 people.</p>
<h2 id="can-a-centralized-mcp-server-for-the-whole-company-use-sso-and-scim">Can a centralized MCP server for the whole company use SSO and SCIM?</h2>
<p>Yes, and it should. Elaichi has SAML and OIDC single sign-on built in-house, plus SCIM v2 for users and groups, with group-to-role mapping. SSO means people sign in through your identity provider. SCIM means the directory pushes joiners, leavers and groups to Elaichi.</p>
<p>SCIM is a standard HTTP protocol for managing identities across separate systems, such as a company directory and a cloud service (<a href="https://www.rfc-editor.org/rfc/rfc7644.html">RFC 7644</a>). It moves people and groups. It does not decide what an AI client may do once a person is in. In Elaichi, that decision belongs to the role the group maps to, plus sharing and restrictions.</p>
<p>Two details matter during rollout:</p>
<ul>
<li><strong>SSO can be enforced.</strong> Domains are verified with a DNS TXT record. If a person's email domain belongs to an organization that enforces SSO, other sign-in methods are refused with "Your organization requires signing in with SSO".</li>
<li><strong>A SCIM deprovision suspends; it never removes.</strong> Suspension revokes every live grant, and the next call is refused. Removing the member, with its offboarding preflight, is a separate step an admin takes in Elaichi.</li>
</ul>
<p><a href="/blog/identity-provider-scim-vs-mcp-grants/">Where SCIM stops and MCP grants begin</a> covers the boundary in detail.</p>
<h2 id="which-control-plane-fits-a-company-using-claude-chatgpt-and-cursor">Which control plane fits a company using Claude, ChatGPT and Cursor?</h2>
<p>One that serves all three from the same address, with each member's own grant. Elaichi gives Claude, ChatGPT and Cursor one URL. An admin adds it once where the client allows, and each member then connects and signs in.</p>
<p>Each client has its own admin step. On Claude Team or Enterprise, an owner adds the address as a custom connector for the organization, and members connect it. In Cursor, team admins can share an MCP server with the team, and each developer can also add the URL to <code>mcp.json</code>. In ChatGPT, an admin on a Business plan creates the app in workspace settings and publishes it to members. Full MCP support with write actions is a beta on Business, Enterprise and Edu plans, and OpenAI says the details may change (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI help center</a>, read October 2026). The steps differ, but the address and the rules behind it do not.</p>
<p>Each member still connects once per client. What an admin avoids is a per-person URL, a pasted token, a per-team endpoint or a separate fork for each client. A fourth MCP client follows the same shape. The setup guides walk through <a href="/blog/connect-elaichi-to-claude/">connecting Claude</a>, <a href="/blog/connect-elaichi-to-chatgpt/">connecting ChatGPT</a> and <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">rolling Elaichi out to a Cursor team</a>.</p>
<h2 id="how-does-the-access-decision-work-on-each-call">How does the access decision work on each call?</h2>
<p>Three layers decide every call, and Elaichi keeps them separate. Roles say what a person may do. Sharing says which resources they may touch. Restrictions say which connectors and which individual tools a target may reach.</p>
<p><strong>Roles.</strong> Elaichi groups 58 permissions into roles, and each member holds exactly one. The built-in chain runs Guest, Member, Team Admin, People Admin, Org Admin and Org Owner, each holding everything below it. Billing Admin and Auditor sit off the chain. Guest, Billing Admin and Auditor lack <code>tool:execute</code>, so the endpoint lists no tools for them.</p>
<p><strong>Sharing.</strong> A grant of view, use or edit on a resource goes to a user, a team or the whole organization. A member sees only what they own or what was shared with them. Org owners and admins are no exception.</p>
<p><strong>Restrictions.</strong> In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, block rules beat allow rules. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p>Timing differs by change. A role or restriction change takes about two minutes. Revoking a grant, removing or suspending a member, revoking a share, or disconnecting an account takes effect on the next call. If an incident needs access cut at once, suspend the person rather than editing a rule.</p>
<h2 id="what-does-the-audit-log-record-for-each-call-that-runs">What does the audit log record for each call that runs?</h2>
<p>One entry per executed call, naming who called, what ran and which account it reached. An audit log is the append-only history of those calls, and in Elaichi it is the same record shape for every connector.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection recorded is the account the call actually reached, taken from the execution, not from the intent. Each entry also names the surface and the client a call came through, so a reviewer can tell a Claude call from a Cursor call. The trail records the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p>The audit history is scoped to each organization. A compliance reviewer can read the trail from the Auditor seat, which is free. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an AI audit log must hold</a> sets out what a reviewer should expect.</p>
<h2 id="how-do-you-compare-the-best-mcp-control-plane-platforms-in-2026">How do you compare the best MCP control plane platforms in 2026?</h2>
<p>Compare mechanics, not feature lists. Ask each vendor five questions and get a number or a name for each answer.</p>
<ol>
<li><strong>How many addresses does a rollout create?</strong> One for the company, one per team, or one per member. Elaichi has one.</li>
<li><strong>Who writes the connector for your most important app?</strong> And who fixes it when that app's API changes. Elaichi writes most of its connectors itself. For a native MCP connector, the app's own vendor writes the tools.</li>
<li><strong>Where is access decided?</strong> Only at sign-in, at a gateway in front of the server, or where the tool is served. Elaichi checks against one resolver, everywhere a member can reach a tool.</li>
<li><strong>How long does a change take?</strong> In Elaichi a role or restriction change takes about two minutes. Revoking a grant applies on the next call.</li>
<li><strong>What does one audit entry hold?</strong> Elaichi's names the person, the tool, the outcome and the account reached.</li>
</ol>
<p>Sort each vendor by these answers before reading its feature grid. A vendor whose setup asks you to run or register servers is a gateway. One that runs the connectors itself, serves one address and decides access on each call is a control plane. <a href="/blog/best-mcp-gateways/">A dated, vendor-by-vendor shortlist</a> applies the same questions to named products.</p>
<h2 id="what-does-elaichi-cost">What does Elaichi cost?</h2>
<p>Gold has a USD list price of $15 per user a month, or $120 per user a year. Elaichi has two plans, Gold and Black, and Black is launching soon. Visitors in some countries see a regional price, so <a href="/pricing/">the pricing page</a> shows what you would pay.</p>
<p>Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Suspended members are not billed, and neither are the Guest, Billing Admin and Auditor roles. If a trial ends without checkout, the workspace pauses, and nothing is deleted.</p>
<p>At list price, 50 seats cost $6,000 a year on annual billing, or $9,000 billed monthly. Black adds customer-managed keys and audit export to your own Datadog, and neither is part of Gold. <a href="/blog/mcp-gateway-pricing/">How vendors meter MCP access</a> compares per-seat and per-call pricing.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Gold is the plan on sale. The pricing page lists what it includes, shows your regional price, and sets out the trial terms.</p><a href="/pricing/" class="cta-button">See pricing</a></aside>
<h2 id="what-does-an-mcp-control-plane-not-do">What does an MCP control plane not do?</h2>
<p>It is not built to front a fleet of MCP servers you already run, it does not see prompts, and it does not run inside your network. Each limit has a workaround or a better-fitting product.</p>
<p>Elaichi is the server for the connectors it authors. An internal MCP server your platform team built keeps its own address and sits beside Elaichi in the client, unless it is reachable over public HTTPS and added on Gold, or on Black once it launches, as a remote MCP connector. If the internal system is an HTTP API, a custom connector written from JSON config brings it under the same resolver and audit trail.</p>
<p>No MCP server sees the user's prompt, because the protocol does not carry it. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds on the endpoint is per-operation role permissions, OAuth scope limits, output redaction, a forbidden classification no scope can reach, and an audit row for each call that reaches execution.</p>
<p>Elaichi is hosted, so a requirement to deploy inside your own network points to self-hosted servers or a self-hosted gateway. A control plane is also a bet on one vendor's connector roadmap.</p>
<h2 id="when-is-an-mcp-control-plane-more-than-you-need">When is an MCP control plane more than you need?</h2>
<p>When one person uses one AI client against one account. The client's own connector signs that person in, the app logs what was touched, and there is nothing to reconcile.</p>
<p>The same holds for a small engineering team calling two internal services from one client. A gateway in front of the servers it already runs fits that team better.</p>
<p>The case changes with the second of anything. A second AI client, a second account of the same app, a second team with different access, or a leaver whose access lives in more than one place. That is when one address, one rule set and one record start to pay for themselves. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When an MCP gateway is premature</a> lists the signals, and <a href="/blog/elaichi-vs-native-ai-connectors/">native client connectors set against one endpoint</a> covers the stage in between.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>See which apps Elaichi already serves through one endpoint, and which tools each connector exposes.</p><a href="/connectors/" class="cta-button">Browse the connectors</a></aside>
<p>For more on the protocol underneath, browse <a href="/blog/category/how-mcp-works/">how MCP works</a>. The <a href="/use-cases/">team use cases</a> show where rollouts usually start.</p>
<h2>FAQ</h2><dl><dt><strong>What is an MCP control plane?</strong></dt><dd>An MCP control plane is a single organization-wide MCP server that holds a company's connected app accounts, serves their tools to AI clients, and decides on every call whether the person calling may use that tool. It differs from an MCP gateway, which forwards calls to MCP servers that somebody else runs. Elaichi is a governed MCP control plane: every app account is connected once, and AI clients reach it through one address, https://api.elaichi.ai/mcp, with roles, restrictions and an audit log.</dd><dt><strong>What is the difference between an MCP control plane, an MCP gateway and an MCP registry?</strong></dt><dd>A registry lists MCP servers so clients and marketplaces can find them, and the official MCP Registry stores metadata that points to servers kept elsewhere. A gateway sits in front of MCP servers that a vendor or your own team runs, and adds one place for sign-in, policy and logging. A control plane serves the connectors, authoring most of them itself, holds the connections, and makes the access decision where the tool is served. With a control plane such as Elaichi, nobody at your company runs an MCP server.</dd><dt><strong>Can one MCP endpoint serve Claude, ChatGPT and Cursor for a whole company?</strong></dt><dd>Yes. Elaichi serves every organization from one address, https://api.elaichi.ai/mcp, and Claude, ChatGPT and Cursor all point at it. An admin adds the address once where the client allows it, and each member then connects and signs in with their own OAuth grant. No toolbox gets its own URL and no token sits in a client config, so adding a fourth MCP client follows the same steps.</dd><dt><strong>Does Elaichi support SSO and SCIM?</strong></dt><dd>Yes. Elaichi has SAML and OIDC single sign-on built in-house, plus SCIM v2 for users and groups with group-to-role mapping. Domains are verified through a DNS TXT record. A SCIM deprovision suspends the member rather than removing them, and suspension revokes every live OAuth grant, so that person's next call to the MCP endpoint is refused. Removing the member is a separate step an admin takes in Elaichi.</dd><dt><strong>How much does Elaichi cost?</strong></dt><dd>Elaichi has two plans, Gold and Black. Gold has a USD list price of $15 per user a month, or $120 per user a year, and visitors in some countries see a regional price on the pricing page. Black is launching soon. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Guest, Billing Admin and Auditor seats are not billed, and neither are suspended members.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Connect Elaichi to Claude</title>
      <link>https://elaichi.ai/blog/connect-elaichi-to-claude/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-elaichi-to-claude/</guid>
      <description>To connect Elaichi to Claude, add one URL as a custom connector and sign in with OAuth. On Team and Enterprise, an Owner adds it once for everyone.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to Claude, add Elaichi's one organization-wide MCP endpoint, https://api.elaichi.ai/mcp, as a custom connector and sign in with OAuth. On Team and Enterprise, an Owner adds it once under Organization settings and each member connects it under Customize. Pro and Max users add it themselves, and Free allows one custom connector. After sign-in, the member's role, what is shared with them and any restrictions decide which tools Claude can call.</aside>
<h2 id="how-do-i-connect-elaichi-to-claude">How do I connect Elaichi to Claude?</h2>
<p>Add one URL, <code>https://api.elaichi.ai/mcp</code>, as a custom connector, then sign in with OAuth. To connect Elaichi to Claude on Team or Enterprise, an Owner adds the connector once and each member connects it. On Pro and Max you do both yourself. There is no API key to paste and no server to run.</p>
<p>A company's Claude rollout usually starts with one team asking for one app. The second request is a different app, and the third comes from someone who should only read. Adding each app's own connector means one setup per app, each with its own permissions model. One Elaichi connector covers every app the company connects, with one set of rules.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps, and the <a href="https://modelcontextprotocol.io/specification/2026-07-28">specification</a> is public. Elaichi serves every connected SaaS account through one organization-wide endpoint, <code>POST /mcp</code>, behind OAuth.</p>
<h2 id="which-claude-plans-allow-a-custom-connector">Which Claude plans allow a custom connector?</h2>
<p>All five. Anthropic's help center lists custom connectors on Free, Pro, Max, Team and Enterprise, in Claude on the web, Claude Desktop and Cowork, and limits Free to one custom connector (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's guide to custom connectors</a>, checked October 2026).</p>
<p>Who adds it differs by plan. On Team and Enterprise, an Owner or Primary Owner adds custom connectors for the whole organization. Enterprise also lets a custom role that manages the organization's libraries add one (<a href="https://claude.com/docs/connectors/custom/add-unlisted">Anthropic's connector docs</a>). Everyone else asks an Owner.</p>
<h2 id="how-does-a-team-or-enterprise-owner-add-the-connector">How does a Team or Enterprise Owner add the connector?</h2>
<p>Once, for everyone, in the organization's settings. As of October 2026 the path is:</p>
<ol>
<li>Open <strong>Organization settings</strong>, then <strong>Connectors</strong>.</li>
<li>Select <strong>Add</strong>, hover over <strong>Custom</strong>, and choose <strong>Web</strong>.</li>
<li>Paste <code>https://api.elaichi.ai/mcp</code> as the server URL.</li>
<li>Leave <strong>Advanced settings</strong> empty, and select <strong>Add</strong>.</li>
</ol>
<p>Then each member opens <strong>Customize</strong>, then <strong>Connectors</strong>, finds the Elaichi connector, which usually carries a Custom label, and selects <strong>Connect</strong>. That sign-in is theirs alone. Nobody shares a credential, and what each member can reach is decided by their own role in Elaichi.</p>
<h2 id="how-do-you-add-it-on-pro-max-or-free">How do you add it on Pro, Max or Free?</h2>
<p>From your own settings, in one pass. Open <strong>Customize</strong>, then <strong>Connectors</strong>, select the <strong>+</strong> button, then <strong>Add custom connector</strong>. Paste the URL, leave the advanced settings empty, and select <strong>Add</strong>. Anthropic gives these steps for Pro and Max, and Free plans can add one custom connector.</p>
<p>The advanced settings take an OAuth client ID and secret, and Elaichi needs neither. Anthropic's authentication docs say Claude uses a client ID metadata document only when the server advertises one, and otherwise falls back to dynamic client registration (<a href="https://claude.com/docs/connectors/building/authentication">how Claude authenticates connectors</a>). Elaichi advertises no metadata document and supports registration under <a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>, so Claude registers itself.</p>
<h2 id="which-address-do-you-paste-exactly">Which address do you paste, exactly?</h2>
<p><code>https://api.elaichi.ai/mcp</code>, with no trailing slash, on the <code>api</code> host. That address answers an unsigned request with the challenge that starts sign-in. Two near misses do not.</p>
<ul>
<li>With a trailing slash, <code>https://api.elaichi.ai/mcp/</code> returns 404.</li>
<li>On the app host, <code>https://app.elaichi.ai/mcp</code> returns 405.</li>
</ul>
<p>Neither carries the challenge, so Claude never reaches Elaichi's sign-in, and the connector looks broken for no visible reason. If sign-in never opens, check the URL first. <a href="/blog/mcp-oauth-errors/">Fixing OAuth errors when adding an MCP connector</a> covers what to do when the sign-in itself fails.</p>
<h2 id="what-will-elaichis-consent-screen-ask-you">What will Elaichi's consent screen ask you?</h2>
<p>Which organization, and what the connector may do. If you belong to one organization, it is chosen for you. If you belong to several, nothing is preselected, and the one you pick is the only one Claude will see. Changing it later means connecting again.</p>
<p>The permissions arrive as up to four checkboxes:</p>
<ul>
<li><strong>Read your organization's data</strong></li>
<li><strong>Create and change data</strong></li>
<li><strong>Run your connected tools</strong></li>
<li><strong>Delete data and remove access</strong></li>
</ul>
<p>Everything Claude requested starts ticked except delete, which never does. Untick anything the person should not have. With <strong>Run your connected tools</strong> ticked, a second step asks which toolboxes Claude may use: <strong>All my tools</strong>, the default, or only the ones you pick.</p>
<h2 id="how-do-claudes-tool-permissions-apply-to-elaichi">How do Claude's tool permissions apply to Elaichi?</h2>
<p>They apply to Elaichi's two discovery tools, not to each app's tools. In Elaichi, connected tools are never listed one by one, however few there are. Claude finds a tool with <code>search_tools</code> and runs it with <code>execute_tool</code>.</p>
<p>Claude lets you set each connector's tools to Always allow, Needs approval or Blocked, and its chat prompt offers Allow once or Always allow (<a href="https://claude.com/docs/connectors/getting-started">Anthropic's getting-started guide</a>). Because every connected tool runs through <code>execute_tool</code>, a permission on it covers every app at once. Leave it on Needs approval if you want a prompt before each call, and put the per-tool decisions in Elaichi's restrictions, which can tell a Jira read from a Jira delete.</p>
<h2 id="where-does-claude-connect-from">Where does Claude connect from?</h2>
<p>From Anthropic's servers, not the user's machine. The help center says Claude reaches a custom connector "from Anthropic's cloud infrastructure, rather than from your local device", on every Claude client. Elaichi's endpoint is public, so there is nothing to allowlist on your network for it.</p>
<p>The SaaS accounts are reached by Elaichi, not by Claude. A member connects each account once, from a catalog of 600+ connectors. Elaichi writes most of them, and the rest are the app vendors' own MCP servers. A separate credential service holds each account's secrets, encrypted at rest, and marks a connection <code>needs_reauth</code> when a refresh fails.</p>
<h2 id="does-a-member-have-to-switch-elaichi-on-in-each-chat">Does a member have to switch Elaichi on in each chat?</h2>
<p>There is a switch per conversation. Under the chat's <strong>+</strong> button, then <strong>Connectors</strong>, each connector has a toggle that decides whether Claude may use it in that conversation. Turning it off does not disconnect anything: Claude stays signed in, and the toggle can come back on in any chat.</p>
<p>If Elaichi's tools seem to vanish in one conversation, check that toggle before anything else. If they are missing everywhere, <a href="/blog/mcp-tools-not-showing/">MCP tools not showing up? Start here</a> walks the checks in order.</p>
<h2 id="what-limits-what-claude-can-do-through-elaichi">What limits what Claude can do through Elaichi?</h2>
<p>The member's role, what has been shared with them, and restrictions, checked on every call. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</p>
<p>Frozen arguments pin a value the model must not choose, such as the workspace a team writes to. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A role or restriction change takes about two minutes to apply, so test a new rule after that window, not straight away.</p>
<p>Elaichi keeps an audit trail of connected-tool calls. It writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account the call reached, and <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a> lists the fields.</p>
<h2 id="how-do-you-take-claude-access-away-from-someone">How do you take Claude access away from someone?</h2>
<p>Remove or suspend them in Elaichi, and their next request from Claude fails. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A person can also disconnect Claude under <strong>Settings</strong>, then <strong>Connected apps</strong>, in Elaichi, which ends that one grant.</p>
<p>Disconnecting inside Claude signs Claude out of the connector, and the row then offers Connect again. To be sure the access is gone, end it on Elaichi's side. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding AI access, contractors included</a> covers the rest of a departure.</p>
<h2 id="when-is-claudes-own-connector-for-an-app-enough">When is Claude's own connector for an app enough?</h2>
<p>When one team needs one app and that app's own connector does what you need. Claude's connector directory lists connectors from many vendors. If a team needs only one of them, with that vendor's permissions and nothing across apps, use it. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals that change the answer.</p>
<p>Elaichi's Gold plan is $15 per user per month in USD, and your region's price is on the <a href="/pricing/">pricing page</a>. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<p>The same address serves the company's other clients: <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a> and <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">the Cursor setup</a> use it unchanged. To choose a first team, start from the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Which Claude plans can connect to Elaichi?</strong></dt><dd>Free, Pro, Max, Team and Enterprise can all add a custom connector, in Claude on the web, Claude Desktop and Cowork. Free is limited to one custom connector. On Team and Enterprise, an Owner or Primary Owner adds it for the organization, and members then connect it themselves.</dd><dt><strong>Do I need an OAuth client ID to connect Elaichi to Claude?</strong></dt><dd>No. Leave the advanced settings empty. Elaichi supports dynamic client registration and publishes no client ID metadata document, so Claude registers itself and each person signs in with their own identity.</dd><dt><strong>Why does Claude list only a few Elaichi tools?</strong></dt><dd>In Elaichi, connected tools are never listed one by one, however few there are. Claude finds a connected tool with search_tools and runs it with execute_tool, so a short list in the connector's settings is the expected view.</dd><dt><strong>How do I stop someone using Elaichi from Claude?</strong></dt><dd>Remove or suspend them in Elaichi. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so their next request from Claude fails. A person can also disconnect the app under Settings, then Connected apps, which ends that grant.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Thu, 01 Oct 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Fix OAuth errors when adding an MCP connector</title>
      <link>https://elaichi.ai/blog/mcp-oauth-errors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-oauth-errors/</guid>
      <description>Most OAuth errors when adding an MCP connector come from the URL, the account or a missing checkbox. What each Elaichi error means, and who fixes it.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Most OAuth errors when adding Elaichi to Claude, ChatGPT or Cursor have one of four causes: the wrong address, the wrong account or organization, an expired consent request, or a permission left unticked. Paste exactly https://api.elaichi.ai/mcp, sign in as the right person, and reconnect when a tool says a checkbox is missing. A role, a restriction or an inactive plan is for an admin to fix.</aside>
<h2 id="what-causes-most-oauth-errors-when-you-add-an-mcp-connector">What causes most OAuth errors when you add an MCP connector?</h2>
<p>Four things: the address, the account, an expired request, or a missing permission. OAuth errors when adding an MCP connector look alike in every client, because the client only reports that sign-in failed. Elaichi's side says which step failed, and almost every fix is on the screen in front of you.</p>
<p>OAuth is the standard that lets Claude, ChatGPT or Cursor act for you without holding your password. The client registers itself, opens Elaichi's sign-in in your browser, and asks for a grant: a record of what it may do, for whom. <a href="https://www.rfc-editor.org/rfc/rfc6749">OAuth 2.0</a> defines the flow, and its error names, such as <code>invalid_grant</code>, are the ones Elaichi returns.</p>
<h2 id="what-if-sign-in-never-opens">What if sign-in never opens?</h2>
<p>Check the address before anything else. Elaichi's endpoint is <code>https://api.elaichi.ai/mcp</code>, exactly. An unsigned request to it returns 401 with a pointer to Elaichi's sign-in details, and that 401 is what starts sign-in. Two near misses return no pointer:</p>
<ul>
<li><code>https://api.elaichi.ai/mcp/</code>, with a trailing slash, returns 404.</li>
<li><code>https://app.elaichi.ai/mcp</code>, on the app host, returns 405.</li>
</ul>
<p>Anthropic's docs say Claude needs that 401 to start sign-in (<a href="https://claude.com/docs/connectors/building/authentication">how Claude authenticates connectors</a>). Its troubleshooting page names the two errors you see when it is missing or sign-in stalls: "Couldn't reach the MCP server" and "Authorization with the MCP server failed" (<a href="https://claude.com/docs/connectors/building/troubleshooting">troubleshooting a connector</a>). ChatGPT and Cursor word it differently, but the fix is the same address.</p>
<h2 id="what-does-your-organization-requires-signing-in-with-sso-mean">What does "Your organization requires signing in with SSO" mean?</h2>
<p>Your company makes everyone sign in through its identity provider. When your email's domain belongs to an Elaichi organization that enforces SSO (single sign-on), Google, Microsoft, GitHub and email-code sign-in are refused with that message. The login screen then starts the SSO sign-in for you, and you land back on the same connection request.</p>
<p>Nothing is broken, and nothing needs an admin. Sign in the way your company asks, and continue.</p>
<h2 id="why-does-the-consent-screen-say-the-request-is-no-longer-valid">Why does the consent screen say the request is no longer valid?</h2>
<p>Because it expired or was already used. A connection request lasts 30 minutes and works once. Leaving the tab open over lunch, or double-clicking Allow, ends it. The screen says the request is no longer valid and offers a way back to Elaichi.</p>
<p>Start the connection again from the client: Claude's Connect, ChatGPT's app, or Cursor's server entry. That opens a fresh request. The 30 minutes are long enough to build a toolbox in another tab and come back, if the step that picks toolboxes sends you off to make one.</p>
<h2 id="what-if-you-are-signed-in-to-the-wrong-account-or-organization">What if you are signed in to the wrong account or organization?</h2>
<p>Use <strong>Not you?</strong> for the account, and connect again for the organization. The consent screen shows the signed-in email at the top. <strong>Not you?</strong> signs you out and returns you to the same request after you sign in as someone else.</p>
<p>The organization is chosen once per connection. With one membership it is chosen for you. With several, nothing is preselected, and the client will see only the organization you pick. Picking the wrong one means disconnecting and connecting again, and a second organization means a second connection.</p>
<p>If your account belongs to no organization yet, Continue and Allow stay disabled. The screen asks you to join or create one, then start the connection again.</p>
<h2 id="why-are-continue-and-allow-greyed-out">Why are Continue and Allow greyed out?</h2>
<p>Usually because nothing can be granted yet. Four cases disable them:</p>
<ul>
<li><strong>No organization.</strong> The account has nothing to give access to.</li>
<li><strong>No organization picked.</strong> With several memberships, Continue waits until you choose one.</li>
<li><strong>No active plan.</strong> The screen says the organization requires an active Gold or Black subscription. An Owner or a Billing Admin fixes that.</li>
<li><strong>Nothing ticked.</strong> Untick every checkbox and the screen asks you to allow at least one thing or deny the request.</li>
</ul>
<h2 id="what-does-a-not-authorized-tool-error-mean-after-connecting">What does a "Not authorized" tool error mean after connecting?</h2>
<p>The connection is missing a permission. The consent screen offers up to four: <strong>Read your organization's data</strong>, <strong>Create and change data</strong>, <strong>Run your connected tools</strong>, and <strong>Delete data and remove access</strong>. Everything the client requested starts ticked except delete, which never does. A client that asks for nothing gets read only.</p>
<p>When a tool needs a box that was not ticked, Elaichi answers the call with an error naming the checkbox and telling you to reconnect. It does not reject your login, because nothing is wrong with it. That answer arrives as a normal response, and Anthropic's docs say Claude ignores a sign-in challenge on such a response, so Claude will not ask on its own. Disconnect, reconnect, and tick the box. This works only if the client requested that permission in the first place.</p>
<h2 id="why-did-a-working-connection-stop-with-invalidtoken-or-invalidgrant">Why did a working connection stop with invalid_token or invalid_grant?</h2>
<p>Because the grant behind it was revoked, or its refresh token lapsed. An access token lasts one hour, and the client refreshes it quietly. A refresh token lasts 30 days and is replaced on every use. A client unused for more than 30 days therefore has to reconnect, and the grant itself never expires while it is used.</p>
<p>Other things end a grant too. You disconnect the app under <strong>Settings</strong>, then <strong>Connected apps</strong>, the client revokes it, an admin removes or suspends you, or an old refresh token is used twice. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the next request returns <code>invalid_token</code>. Elaichi deliberately makes unknown, expired and revoked tokens look the same, so the fix is the same: reconnect.</p>
<h2 id="what-does-a-429-mean">What does a 429 mean?</h2>
<p>Too many requests in a minute. Elaichi accepts 30 OAuth requests a minute, counted per client for most of the flow and per network address for registration, and 120 MCP requests a minute per token. Over either limit you get 429 with a <code>Retry-After</code> of 60 seconds. Wait a minute and try again.</p>
<h2 id="which-errors-can-you-fix-yourself-and-which-need-an-admin">Which errors can you fix yourself, and which need an admin?</h2>
<table>
<thead>
<tr>
<th>What you see</th>
<th>Who fixes it</th>
<th>How</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sign-in never opens</td>
<td>You</td>
<td>Paste exactly <code>https://api.elaichi.ai/mcp</code></td>
</tr>
<tr>
<td>SSO required</td>
<td>You</td>
<td>Sign in through your company's SSO</td>
</tr>
<tr>
<td>Request no longer valid</td>
<td>You</td>
<td>Start again from the client</td>
</tr>
<tr>
<td>Wrong account or organization</td>
<td>You</td>
<td><strong>Not you?</strong>, or connect again</td>
</tr>
<tr>
<td>"Not authorized" naming a checkbox</td>
<td>You</td>
<td>Reconnect and tick it</td>
</tr>
<tr>
<td><code>invalid_token</code> or <code>invalid_grant</code></td>
<td>You</td>
<td>Reconnect</td>
</tr>
<tr>
<td>429</td>
<td>You</td>
<td>Wait 60 seconds</td>
</tr>
<tr>
<td>No organization, or no longer a member</td>
<td>An admin</td>
<td>An invite or a membership</td>
</tr>
<tr>
<td>No active Gold or Black plan</td>
<td>An Owner or Billing Admin</td>
<td>Billing</td>
</tr>
<tr>
<td>Empty tool list, or one app missing</td>
<td>It depends</td>
<td>Not an OAuth error; see the checklist below</td>
</tr>
</tbody>
</table>
<p>An empty tool list after a clean sign-in is not an OAuth error at all. <a href="/blog/mcp-tools-not-showing/">MCP tools not showing up? Start here</a> walks those checks in order.</p>
<h2 id="what-should-a-custom-mcp-client-send">What should a custom MCP client send?</h2>
<p>The standard flow, with PKCE (Proof Key for Code Exchange) on every request. Register at the endpoint the discovery document names, under <a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>. Then send a <code>code_challenge</code> with <code>code_challenge_method=S256</code>, as <a href="https://www.rfc-editor.org/rfc/rfc7636">RFC 7636</a> defines. Elaichi does not assume S256 when the method is missing, and it refuses <code>plain</code>.</p>
<p>Three more rules catch hand-built clients:</p>
<ul>
<li><strong>The redirect URI must match.</strong> It must be exactly one you registered. The only allowance is a loopback address changing its port.</li>
<li><strong>The resource must be Elaichi's.</strong> If you send one, it must be on <code>https://api.elaichi.ai</code>, or the request fails with <code>invalid_target</code>.</li>
<li><strong>Scopes come from a fixed list.</strong> Ask only for <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code>, <code>mcp:tools</code>, <code>openid</code> and <code>email</code>. Anything else, such as <code>offline_access</code>, returns <code>invalid_scope</code>.</li>
</ul>
<p>The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization specification</a> describes the discovery steps a compliant client follows.</p>
<h2 id="what-does-sign-in-not-decide">What does sign-in not decide?</h2>
<p>Which tools the person can call. A clean sign-in proves who they are and what the connection may attempt. Their role, what is shared with them and restrictions decide the rest. Restrictions decide which connectors and which individual tools a target may reach, and a role or restriction change takes about two minutes to apply.</p>
<p>To set the connector up from the start, follow <a href="/blog/connect-elaichi-to-claude/">the Claude setup</a>, <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a> or <a href="/blog/cursor-mcp-one-endpoint-vs-per-developer/">the Cursor setup</a>. Elaichi's Gold plan is $15 per user per month in USD, with your region's price on the <a href="/pricing/">pricing page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Why does sign-in never open when I add the Elaichi connector?</strong></dt><dd>The address is usually wrong. https://api.elaichi.ai/mcp answers an unsigned request with the 401 challenge that starts sign-in. With a trailing slash it returns 404, and on the app host it returns 405, and neither carries the challenge.</dd><dt><strong>How long does an Elaichi sign-in last?</strong></dt><dd>An access token lasts one hour, and the client refreshes it. A refresh token lasts 30 days and is replaced on every use, and the grant itself never expires. A client left unused for more than 30 days has to reconnect.</dd><dt><strong>Why does a tool say I am not authorized after I connected?</strong></dt><dd>The connection is missing a permission, such as running connected tools or deleting. The message names the checkbox. Reconnect in the client and tick it on Elaichi's consent screen. Your login is fine.</dd><dt><strong>Which Elaichi sign-in problems need an admin?</strong></dt><dd>Having no organization, no longer being a member, a role without the tool:execute permission, a restriction, or an organization without an active Gold or Black plan. The person connecting cannot fix those.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Thu, 01 Oct 2026 00:00:00 GMT</pubDate>
      <category>setup</category>
    </item>
    <item>
      <title>MCP tools not showing up? Start here</title>
      <link>https://elaichi.ai/blog/mcp-tools-not-showing/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-tools-not-showing/</guid>
      <description>MCP tools not showing in Claude, ChatGPT or Cursor? With Elaichi, connected tools are never listed by design. Check these five things, in order.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> With Elaichi, MCP tools not showing in the client's list is normal: connected tools are never listed one by one, however few there are, and the client finds them with search_tools. If a search still finds nothing, check five things in order: the app is connected, its connection is active, no restriction blocks it, the connection may run tools, and the search names the app. An empty list means the person's role lacks tool:execute, which only an admin can change.</aside>
<h2 id="why-are-my-mcp-tools-not-showing">Why are my MCP tools not showing?</h2>
<p>Usually because they are not supposed to show. With Elaichi, MCP tools not showing in the client's tool list is the design. In Elaichi, connected tools are never listed one by one, however few there are. Claude, ChatGPT or Cursor sees two tools, <code>search_tools</code> and <code>execute_tool</code>, and uses them to find and run every connected tool.</p>
<p>Hundreds of tool definitions crowd a model's context, and a long list makes the wrong pick likelier. So Elaichi lists only what the model needs to find a tool, and ranks each search against what the person can reach. <a href="/blog/context-window-problem-mcp-tools/">The MCP context window problem, and a fix</a> explains the trade-off.</p>
<p>So start with what the list should contain. If it matches, the connection works, and a missing tool is one of the five checks below.</p>
<h2 id="what-should-an-elaichi-tool-list-contain">What should an Elaichi tool list contain?</h2>
<p>Three kinds of entry, and the connected tools are never among them:</p>
<ul>
<li><strong>Elaichi's own operations</strong>, whose names start with <code>elaichi__</code>, listed individually when the person's role and the connection's permissions allow them.</li>
<li><strong><code>search_tools</code> and <code>execute_tool</code></strong>, present while at least one connected tool is reachable.</li>
<li><strong>Nothing per app.</strong> A Jira or Zendesk tool never appears in the list itself.</li>
</ul>
<p>If <code>search_tools</code> and <code>execute_tool</code> are both missing, no connected tool is reachable yet, and the first two checks below are the likely reason.</p>
<h2 id="is-the-app-connected-at-all">Is the app connected at all?</h2>
<p>Check under <strong>Connections</strong> in Elaichi. If the app is not there, nothing can find its tools, and the fix is to connect it from the <a href="/connectors/">connector catalog</a>.</p>
<p>Search makes this case visible. A search naming an app the person never connected returns no results, with a line naming up to six apps the connection does reach. That empty answer is deliberate: a tool from the wrong app would be worse than none, because the model would call it.</p>
<h2 id="is-the-connection-active">Is the connection active?</h2>
<p>A connection that is not active contributes no tools at all. It is missing from the results, not present and failing. In the console a broken connection shows <strong>Needs sign-in</strong>, and one nobody finished shows <strong>Awaiting sign-in</strong>.</p>
<p>Open the connection under <strong>Connections</strong> and select <strong>Reconnect</strong>, or <strong>Finish sign-in</strong> for one that never completed. Then complete the app's own login. Reconnecting rebinds the same connection to the same account, so its shares and toolbox entries survive.</p>
<p>Who may do it is narrow. The owner, someone with edit access, or an admin over a shared connection can reconnect. Only the owner can finish a connection that never completed, because finishing it binds a new identity.</p>
<h2 id="could-a-restriction-withhold-the-tool">Could a restriction withhold the tool?</h2>
<p>Yes. A restricted tool is withheld from the tool list and cannot be called. If the assistant searches for it, it sees only the name, flagged restricted, with no description or schema. Restrictions decide which connectors and which individual tools a target may reach. A connector restricted whole shows as one row for the connector.</p>
<p>The console marks restricted tools too. Anyone who can view the connector sees each tool flagged restricted, so confirming one needs no restriction permission. Only an admin can change the rule. Watch for one trap when allow rules are involved: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>A restriction change takes about two minutes. Test it after that window.</p>
<h2 id="does-the-connection-have-permission-to-run-tools">Does the connection have permission to run tools?</h2>
<p>It needs one checkbox on Elaichi's consent screen: <strong>Run your connected tools</strong>. Without it, the connection can use Elaichi's own operations but no connected app. A tool call answers with an error naming that checkbox and asking you to reconnect and tick it.</p>
<p>Two narrower cases look the same from the client:</p>
<ul>
<li><strong>Delete tools hide without the delete permission.</strong> A tool that deletes is left out of search entirely unless <strong>Delete data and remove access</strong> was ticked.</li>
<li><strong>A connection limited to chosen toolboxes</strong> reaches only their tools. If none of those toolboxes can be used any more, it reaches nothing, never everything. Edit the choice under <strong>Settings</strong>, then <strong>Connected apps</strong>, in Elaichi.</li>
</ul>
<p><a href="/blog/mcp-oauth-errors/">Fixing OAuth errors when adding an MCP connector</a> covers reconnecting and the consent screen in detail.</p>
<h2 id="did-the-search-name-the-tool">Did the search name the tool?</h2>
<p>Search matches words, not meaning, so phrase the request the way the tool is named. Ask for "list Jira issues" rather than "what is the team working on". The model searches with <code>search_tools</code> and calls the result through <code>execute_tool</code>.</p>
<p>A search returns nothing rather than a weak match from another app. That floor keeps the model from running a Notion tool when you asked about Cal.com. <a href="/blog/search-tools-ranking-floor-idf/">How MCP tool search picks one tool from hundreds</a> explains the ranking.</p>
<h2 id="why-is-the-whole-list-empty">Why is the whole list empty?</h2>
<p>The person's role lacks <code>tool:execute</code>. Without that permission the list is empty at every level of access the connection holds, and every call answers with an error naming the permission and saying that reconnecting will not help. Guest, Auditor and Billing Admin lack it, while Member and above hold it.</p>
<p>That fix belongs to an admin, who changes the role. A Billing Admin or an Auditor who signs in to look at Elaichi from Claude will always see an empty list, and that is correct.</p>
<p>An organization can also switch off Elaichi's own operations. They then disappear from every list, while connected tools keep working.</p>
<h2 id="why-did-the-tools-not-appear-after-a-change">Why did the tools not appear after a change?</h2>
<p>Because the client is holding an old list. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> lets a server declare whether it will send a notification when its list of tools changes. Elaichi declares that it will not, so a client keeps whatever list it last read.</p>
<p>Most changes do not need a fresh list, because connected tools are found by search, not by the list. The exception is the first app. <code>search_tools</code> and <code>execute_tool</code> appear only once a connected tool is reachable, so a client that read its list before then does not have them. Start a new conversation, or disconnect and reconnect, to make it read the list again.</p>
<p>In Claude, also check the conversation's own switch. Each chat has a toggle per connector under the <strong>+</strong> button, then <strong>Connectors</strong>, and a connector switched off there sends nothing (<a href="https://claude.com/docs/connectors/getting-started">Anthropic's getting-started guide</a>). Cursor offers a similar per-server switch under Customize (<a href="https://cursor.com/docs/mcp">Cursor's MCP docs</a>).</p>
<h2 id="who-fixes-which-cause">Who fixes which cause?</h2>
<table>
<thead>
<tr>
<th>Cause</th>
<th>Who fixes it</th>
</tr>
</thead>
<tbody>
<tr>
<td>App not connected</td>
<td>Anyone who may connect apps</td>
</tr>
<tr>
<td>Connection needs sign-in</td>
<td>Its owner, an edit grantee, or an admin</td>
</tr>
<tr>
<td>Connection never finished</td>
<td>Its owner</td>
</tr>
<tr>
<td>A restriction</td>
<td>An admin</td>
</tr>
<tr>
<td>No permission to run tools</td>
<td>The person, by reconnecting</td>
</tr>
<tr>
<td>Role lacks <code>tool:execute</code></td>
<td>An admin</td>
</tr>
<tr>
<td>Old tool list in the client</td>
<td>The person, with a new conversation</td>
</tr>
</tbody>
</table>
<p>Once tools appear, <a href="/blog/connect-elaichi-to-claude/">the Claude setup</a> and <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a> cover what to set before a team relies on it.</p>
<h2>FAQ</h2><dl><dt><strong>Why does my MCP client show only search_tools and execute_tool?</strong></dt><dd>Because that is how Elaichi works. In Elaichi, connected tools are never listed one by one, however few there are. The client looks a tool up with search_tools and runs it with execute_tool, so those two in the list mean the connection is working.</dd><dt><strong>Why is my Elaichi tool list completely empty?</strong></dt><dd>Your role probably lacks the tool:execute permission. Without it the list is empty whatever the connection allows, and every call says so. Guest, Auditor and Billing Admin lack it. An admin has to change the role.</dd><dt><strong>Does Elaichi tell my client when the tool list changes?</strong></dt><dd>No. Elaichi declares that it sends no list-changed notifications, so a client keeps whatever list it last read. Start a new conversation or reconnect if a newly connected app's tools do not appear.</dd><dt><strong>How long does a restriction change take to show up?</strong></dt><dd>Role and restriction changes take about two minutes, on every surface. Grant revocation, member removal and suspension take effect on the next call.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Thu, 01 Oct 2026 00:00:00 GMT</pubDate>
      <category>setup</category>
    </item>
    <item>
      <title>Elaichi vs Composio: who writes your connectors?</title>
      <link>https://elaichi.ai/blog/elaichi-vs-composio/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/elaichi-vs-composio/</guid>
      <description>Elaichi vs Composio: Elaichi writes most of its connectors and serves them on one company-wide MCP endpoint. Composio covers more apps, one endpoint per team.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi and Composio split on who writes the connectors and on how many MCP addresses a company hands out. Elaichi authors, maintains and serves 600+ connectors through one organization-wide MCP endpoint behind OAuth, priced per user. Composio documents 1000+ apps reached through seven meta-tools, a gateway that gives each team its own endpoint, and billing by tool call. Composio suits a builder putting tools inside a product; Elaichi suits a company giving its own staff governed access.</aside>
<h2 id="elaichi-vs-composio-what-is-the-difference">Elaichi vs Composio: what is the difference?</h2>
<p>Elaichi vs Composio comes down to who writes your connectors and how many MCP addresses your company hands out. Elaichi writes, maintains and serves its own connectors. Every AI client reaches them through one organization-wide endpoint, and each member signs in with their own grant. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>Take twenty people who want Claude or ChatGPT to read the CRM, file tickets in Jira and pull invoices from Xero. Several products answer that request, and these two answer it with different designs.</p>
<p>Composio's docs describe Composio Connect as an MCP server at <code>connect.composio.dev/mcp</code> that gives an agent access to "1000+ apps". It does so through seven meta-tools rather than one listed tool per app action. Each app is approved through an OAuth link in the browser (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026).</p>
<p>Its MCP Gateway page describes the shape Composio offers a company: "one gateway, every server", where "each team gets its own MCP endpoint carrying only the tools it is permitted to use". That page counts "1,500+ apps available" (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked October 2026). These are two coherent designs for two different buyers, and neither is a strict upgrade of the other.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Elaichi</th>
<th>Composio</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who writes the connectors?</td>
<td>Elaichi serves 600+ connectors, authoring and maintaining most of them</td>
<td>"1000+ apps" through Composio Connect (<a href="https://docs.composio.dev/docs/composio-connect">docs</a>, checked October 2026); ask who maintains each one</td>
</tr>
<tr>
<td>How many addresses?</td>
<td>One organization-wide <code>POST /mcp</code> behind OAuth</td>
<td>Each team gets its own MCP endpoint (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked October 2026)</td>
</tr>
<tr>
<td>How does the model reach app tools?</td>
<td>Two meta-tools, <code>search_tools</code> and <code>execute_tool</code>; each tool maps to one operation and can be restricted on its own</td>
<td>Seven meta-tools on Composio Connect (<a href="https://docs.composio.dev/docs/composio-connect">docs</a>, checked October 2026)</td>
</tr>
<tr>
<td>Permissions</td>
<td>One role per member, sharing grants, per-tool restrictions</td>
<td>Set "per user and per role, down to the individual action" (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026)</td>
</tr>
<tr>
<td>Audit record</td>
<td>Keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account reached</td>
<td>Every tool call logged with user, team, tool, action and outcome, denied calls included (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>)</td>
</tr>
<tr>
<td>SSO and SCIM</td>
<td>Built in-house; the <a href="/pricing/">pricing page</a> lists both on Gold</td>
<td>Listed under the custom Enterprise tier (<a href="https://composio.dev/pricing">composio.dev/pricing</a>, checked October 2026)</td>
</tr>
<tr>
<td>Billing unit</td>
<td>Per user: Gold lists at $15 per user per month in USD (<a href="/pricing/">pricing</a>)</td>
<td>Per tool call: Hobby is free with 3 team members, Pro is $29 a month (<a href="https://composio.dev/pricing">composio.dev/pricing</a>)</td>
</tr>
<tr>
<td>Built for</td>
<td>A company giving its own staff governed access</td>
<td>Developers building agents, and people who want an assistant to act in their apps (<a href="https://composio.dev">composio.dev</a>, checked October 2026)</td>
</tr>
</tbody>
</table>
<h2 id="who-writes-the-connectors-you-depend-on">Who writes the connectors you depend on?</h2>
<p>Elaichi writes most of them. Elaichi serves 600+ connectors, authors and maintains most of them on its own infrastructure, and your company runs no MCP servers of its own. When an app changes its API and one of those tools starts failing, there is one party to chase, and it is the party you pay. A native MCP connector is the exception: the app's vendor builds and runs its tools, and reports go to that vendor's support contact.</p>
<p>Breadth and authorship pull against each other. A catalog one vendor writes grows only as fast as that vendor writes connectors. Composio's Connect docs count "1000+ apps", well beyond the Elaichi catalog (<a href="https://docs.composio.dev/docs/composio-connect">docs.composio.dev</a>, checked October 2026). That is a real gap in raw coverage, not a rounding error. If your teams depend on a long-tail app that Composio lists and Elaichi does not, that alone can decide the comparison. Check the five apps your teams actually name against the <a href="/connectors/">connector catalog</a> before the argument turns abstract.</p>
<p>Who writes and maintains each of Composio's app tools is a question to put to Composio. Its gateway page describes "one gateway, every server" (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked October 2026). Ask which tools behind it Composio maintains, and which come from servers your team or somebody else runs.</p>
<p>If an app is missing from the Elaichi catalog, custom connectors are authored from JSON config. A connector can be forked from a public one, and a fork can pull upstream changes through a review surface. That surface separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default, so someone has to look at them. The <code>connector:create</code> permission is flagged high trust, because a custom connector can be pointed at any destination.</p>
<h2 id="one-organization-wide-address-or-one-endpoint-per-team">One organization-wide address, or one endpoint per team?</h2>
<p>Elaichi has one address: <code>POST /mcp</code>, standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. The MCP specification defines Streamable HTTP as a transport in which each message is an HTTP POST to a single MCP endpoint (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports">MCP transports</a>). There are no per-toolbox URLs and no embedded tokens. There is no MCP server to create, list or revoke per person. The address is fixed, and the grant is what varies.</p>
<p>That shape decides what offboarding looks like, and offboarding runs at <a href="/blog/offboarding-when-the-agent-holds-access/">two different speeds</a>. Revocation is a database write, not a hunt through client configs for URLs. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A role change or a restriction change takes about two minutes to settle, through a short cache plus edge propagation rather than a config push to every client.</p>
<p>The same design has a cost. One address means one shared boundary. Isolation between teams on Elaichi is enforced by roles and restrictions inside the application, not by which URL a client happens to hold. Elaichi has no per-team endpoint. If your compliance model calls for a separate address per business unit, Elaichi does not offer one.</p>
<p>Composio's gateway page describes the per-team shape: "each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked October 2026). Per-team endpoints fit an organization where the team is the real unit of access. The cost is more addresses to track as the company grows. Ask any per-endpoint vendor how many addresses exist after a year, and who keeps client configuration in step with them. Ask whether a team's endpoint is its own boundary or a path on one shared gateway. And ask what an admin does at 5pm on a Friday when a laptop goes missing.</p>
<h2 id="how-do-claude-chatgpt-and-cursor-connect-to-elaichi">How do Claude, ChatGPT and Cursor connect to Elaichi?</h2>
<p>Every client takes the same URL. An admin adds it once where the client allows that, and each member then connects and signs in with their own grant. Nobody is issued a personal URL or token, though each member still connects once.</p>
<p>In Claude Team and Enterprise, an owner adds the connector under Organization settings > Connectors, and members connect it under Customize > Connectors. On Pro and Max, each person adds it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166">Anthropic's custom connector guide</a>). In Cursor, the admin MCP allowlist is Enterprise only. Cursor's docs say that adding a server to it "does not push it to users' machines", so each developer still adds the server in their own Cursor (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor's enterprise docs</a>). ChatGPT has its own steps, covered in <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>. Any other client that speaks MCP over Streamable HTTP uses the same address. The Elaichi Agent is not one of them. It works inside the app and comes with the Black plan.</p>
<p>The test to run on any candidate is the number of steps a member performs before their first successful tool call. Setup repeated per person is the cost that shows up in month three rather than week one. It arrives when the fifth new hire asks how to connect Claude and nobody has written it down.</p>
<h2 id="how-does-each-one-govern-what-the-model-can-call">How does each one govern what the model can call?</h2>
<p>Both products have governance, so compare its shape rather than its presence. Elaichi splits access into three layers. Permissions are 58 action strings grouped into roles, with exactly one role per member, enforced by a unique index. Sharing is a separate grant of view, use or edit to a person, a team or the whole organization. Nobody sees a resource unless they own it or it was shared with them. Restrictions decide which connectors and which individual tools a target may reach.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Blocks always beat allows. One trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. A block catches a tool by its name or by the operation behind it, while an allow counts the operation only. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a>.</p>
<p>Composio's enterprise page states that permissions are "set administratively, per user and per role, down to the individual action". It says "every tool call is logged with the user, team, tool, action and outcome, denied calls included". Single sign-on is available over SAML and OIDC (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026). On paper, that is a comparable depth of control.</p>
<p>Elaichi and Composio Connect both keep app tools out of the model's first look. In Elaichi, connected tools are never listed one by one, however few there are. The model looks a tool up through <code>search_tools</code> and calls it through <code>execute_tool</code>. A tool a restriction withholds is left out of the tool list and cannot be called. Search names it, flagged restricted, with no schema. Composio Connect reaches its apps through seven meta-tools (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026). Ask Composio whether a restricted action disappears from what the model can discover, or is refused only when called. The answer decides how visible the boundary is to the model doing the planning.</p>
<p>On the Elaichi side, the audit trail keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The account it names is the one the call actually reached. Each entry also records the surface, <code>mcp</code>, and the OAuth client, with Claude, ChatGPT and Cursor marked verified. The call is recorded under the person who signed in, so the client is logged at the point of action rather than guessed later. The trail records the one path argument that names the object, as the target id, and nothing else about the arguments, which trades some forensic detail for not storing sensitive payloads. A compliance reviewer can hold a free read-only Auditor seat, so audit access does not compete with billable headcount.</p>
<p>One limit on the Elaichi side, stated plainly. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. It cannot, because an MCP server never sees a user prompt. What holds on the endpoint instead is a permission check per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution.</p>
<h2 id="what-does-each-one-cost-once-you-need-sso-and-scim">What does each one cost once you need SSO and SCIM?</h2>
<p>Elaichi has two plans, Gold and Black. Gold lists at $15 per user per month in USD, or $120 per user per year, and the <a href="/pricing/">pricing page</a> shows the price for your region. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Billable seats are active memberships. Suspended members and the free-seat roles (Guest, Billing Admin and Auditor) are not counted. SAML and OIDC SSO are built in-house, with SCIM v2 for users and groups and group-to-role mapping, and the pricing page lists all three on Gold.</p>
<p>Composio's pricing page bills on tool calls. It lists Hobby as free with 3 team members and Pro at $29 a month. SSO, SCIM and customer-managed keys sit under a custom Enterprise tier (<a href="https://composio.dev/pricing">composio.dev/pricing</a>, checked October 2026).</p>
<p>The two bills move with different things. Take a 20-person team on Elaichi Gold: at the USD list price, that is 20 seats at $15, or $300 a month, however many tool calls anyone makes. A plan billed per tool call moves with usage instead, so the number that matters there is your team's monthly call volume. Light, occasional lookups and an agent that runs all day produce very different counts from the same twenty people. Run your own count against both pricing pages before assuming either one is cheaper.</p>
<h2 id="when-is-composio-the-better-choice">When is Composio the better choice?</h2>
<p>When the people holding the sessions are your customers rather than your employees. Composio's homepage addresses developers building agents and people who want an AI assistant to act in their apps. Its docs describe an SDK with per-user sessions and managed auth (<a href="https://composio.dev">composio.dev</a>, <a href="https://docs.composio.dev">docs.composio.dev</a>, checked October 2026). That is the right shape for a product team putting tool access inside something it sells, where a seat does not map to an employee at all.</p>
<p>Elaichi assumes a workforce. Roles, billable seats, the offboarding preflight and SCIM all describe employees and contractors, not your end users. Bending Elaichi onto a consumer product would mean paying per seat for accounts whose churn you do not control. Three other cases point toward Composio:</p>
<ul>
<li><strong>A team already building on the Composio SDK.</strong> Switching is real engineering work, not a preference.</li>
<li><strong>An app you depend on that Composio lists and the Elaichi catalog lacks.</strong> That blocks you until someone builds a custom connector.</li>
<li><strong>An organization that wants a separate endpoint per team.</strong> Composio's <a href="https://composio.dev/mcp-gateway">gateway page</a> describes that shape, and Elaichi does not offer it.</li>
</ul>
<h2 id="when-should-you-buy-neither">When should you buy neither?</h2>
<p>Three people, one connected app, read-only access, and an owner who can see every call: buy nothing. The case for waiting, and the signals that the wait is over, are in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the piece on not needing a gateway yet</a>. If you already run MCP servers in your own infrastructure, the comparison is a different one, and its cost side is set out in <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">self-hosted servers against a managed control plane</a>.</p>
<h2 id="how-do-you-test-both-in-two-weeks">How do you test both in two weeks?</h2>
<p>Run both against the same narrow task instead of reading feature grids, this comparison included. Pick one team, one app and one job that team does weekly. Then measure setup, revocation and the audit record directly.</p>
<ol>
<li>Name the five apps the team needs and check each against both catalogs: the <a href="/connectors/">connector catalog</a> for Elaichi, and the toolkits list in <a href="https://docs.composio.dev">Composio's docs</a> for Composio.</li>
<li>Add the endpoint to one AI client, as an admin where the client allows it, and count the steps a member performs before their first successful tool call.</li>
<li>Block one destructive tool for one role and time how long the block takes to reach a live client session, not just the admin panel.</li>
<li>Remove a test member and check what happens to their access and to any shared connection. Note whether access ends on the next call, at the next token refresh, or not until someone notices.</li>
<li>Export a week of tool-call records. Check whether each one names the actual account reached, not just "Salesforce", and note whether refused calls appear beside successful ones. Elaichi writes no row for a call refused before execution.</li>
</ol>
<p>For a worked example of step three in a real team, read <a href="/blog/sales-team-chatgpt-salesforce-accounts/">how a sales team gets governed Salesforce access through ChatGPT</a>. The address-model argument in a different setting is in <a href="/blog/zapier-mcp-alternative/">the per-member server comparison</a>. Team-by-team starting points are on the <a href="/use-cases/">use cases page</a>, and more head-to-heads sit under <a href="/blog/category/comparisons/">comparisons</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is the difference between Elaichi and Composio?</strong></dt><dd>Elaichi authors and maintains its own connectors and serves them through one organization-wide MCP endpoint, POST /mcp, behind OAuth. Composio's docs describe Composio Connect reaching 1000+ apps through seven meta-tools, and its MCP Gateway page says each team gets its own MCP endpoint carrying only the tools it is permitted to use (https://docs.composio.dev/docs/composio-connect and https://composio.dev/mcp-gateway, checked October 2026). The practical choice is who writes the connectors and how many MCP addresses your organization hands out.</dd><dt><strong>Does Composio have role-based permissions, audit logs and SSO?</strong></dt><dd>Yes. Composio's enterprise page states that permissions are set administratively, per user and per role, down to the individual action; that every tool call is logged with the user, team, tool, action and outcome, denied calls included; and that single sign-on is available over SAML and OIDC (https://composio.dev/enterprise, checked October 2026). Compare it with Elaichi on the address model and on who writes the connectors, not on whether governance exists.</dd><dt><strong>How much does Elaichi cost, and is SSO included?</strong></dt><dd>Elaichi has two plans, Gold and Black. Gold lists at $15 per user per month in USD, or $120 per user per year, and the pricing page at https://elaichi.ai/pricing/ shows the price for your region. That page lists SAML or OIDC SSO, SCIM provisioning and group-to-role mapping on Gold, and Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Billable seats are active memberships; suspended members and the Guest, Billing Admin and Auditor roles are not counted.</dd><dt><strong>How quickly does a permission change take effect in Elaichi?</strong></dt><dd>It depends on the change. Grant revocation, member removal and suspension take effect on the next call, because the grant's revocation state is re-read from the organization store on every call, and removing or suspending a member revokes every live grant in the same transaction as the membership change. Role and restriction changes pass through a 60-second cache and then edge propagation, so they take effect within about two minutes on the MCP endpoint, the console and the REST API alike.</dd><dt><strong>When is Composio a better choice than Elaichi?</strong></dt><dd>When the people using the tools are your customers rather than your employees. Composio's homepage addresses developers building agents and people who want an AI assistant to act in their apps, and its docs describe an SDK with per-user sessions and managed auth (https://composio.dev and https://docs.composio.dev, checked October 2026). A team already building on that SDK, or one that needs an app Composio lists and the Elaichi catalog lacks, has a plain reason to choose it.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>Claude and ChatGPT connectors vs one MCP endpoint</title>
      <link>https://elaichi.ai/blog/elaichi-vs-native-ai-connectors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/elaichi-vs-native-ai-connectors/</guid>
      <description>Claude and ChatGPT connectors fit one client and a few apps. Once a second client repeats the setup, one governed MCP endpoint costs less to run.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi is one organization-wide MCP endpoint that Claude, ChatGPT and Cursor all point at, so accounts, roles and the audit trail are set up once. A client's own connectors are set up inside that client, person by person. With one client and a few apps, native is less to own. From the second client on, setup, audit and offboarding repeat, and one endpoint stops that.</aside>
<h2 id="claude-and-chatgpt-connectors-or-one-endpoint-what-are-you-choosing">Claude and ChatGPT connectors or one endpoint: what are you choosing?</h2>
<p>Claude and ChatGPT connectors are the right call while one AI client and a few apps cover the work. Once a second client repeats the same setup, one organization-wide MCP endpoint costs less to run and is easier to account for.</p>
<p>Support bought ChatGPT Enterprise in March. Engineering has run Cursor for a year. Legal now wants Claude. That is three clients, three connector setups and three sets of records to reconcile when something goes wrong.</p>
<p>The comparison is between two shapes, not two feature lists. A native connector system lives inside one AI client, set up there for that client's users. Elaichi is one organization-wide MCP endpoint that Claude, ChatGPT, Cursor and any other MCP client all point at. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps, and its <a href="https://modelcontextprotocol.io/specification/2025-06-18">specification</a> is public. An endpoint is the single address a client connects to. Elaichi's is <code>POST /mcp</code>: standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. OAuth here means each person signs in and receives their own grant, which can be revoked without touching anyone else's.</p>
<p>With one client, the two shapes are close to equivalent: one console, one setup, one place to look. The gap opens on the second client, because accounts, member lists, roles and records then exist once per client rather than once per company. That holds whether the organization-wide plane is Elaichi or another MCP gateway.</p>
<table>
<thead>
<tr>
<th>Concern</th>
<th>Each client's own connectors</th>
<th>One endpoint for every client (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Member setup</td>
<td>Each member attaches each app inside each client, with their own account</td>
<td>Each member connects the one URL once per client and signs in over OAuth</td>
</tr>
<tr>
<td>A second client</td>
<td>Accounts, member lists and rules are set up again in the new console</td>
<td>The new client points at the same URL; accounts, roles and restrictions already exist</td>
</tr>
<tr>
<td>Pinned arguments</td>
<td>Whatever that client's console offers; ask before relying on it</td>
<td>Frozen parameters, left out of the model's schema and merged over its arguments</td>
</tr>
<tr>
<td>Audit</td>
<td>Each client records only the calls made through it</td>
<td>One trail across every client, and each row names the account reached and the client the call came through</td>
</tr>
<tr>
<td>Leavers</td>
<td>One cleanup per client, and per app the person attached in it</td>
<td>Grants revoked on the next call; a preflight catches personal connections still in use</td>
</tr>
</tbody>
</table>
<h2 id="what-do-claudes-chatgpts-and-cursors-own-connectors-give-you">What do Claude's, ChatGPT's and Cursor's own connectors give you?</h2>
<p>Speed, and access defined one person at a time inside that client. A member picks an app and signs in with an account they control, and the grant from that sign-in sits against that person.</p>
<p>A finance manager attaches Claude to the billing system on a Tuesday. By Friday four colleagues have done the same, each with a personal account. Nothing is broken, and nothing is visible either. Where each person signs in to each app inside their own ChatGPT session, the shape is the same: the unit of control is the person. Ten people and six apps make sixty separate decisions per client, none of them written down together. Two people can attach different accounts of the same app, and nobody notices until a record lands in the wrong workspace.</p>
<p>Each client takes a custom connector, such as one organization-wide URL, in its own way. In Claude Team and Enterprise, an owner adds it under Organization settings > Connectors > Add > Custom > Web. Members then connect it under Customize > Connectors. On Claude Pro and Max, each person adds it under Customize > Connectors > "+" > Add custom connector (<a href="https://support.claude.com/en/articles/11175166">Claude's help center</a>, checked September 2026). In Cursor, the admin MCP allowlist is Enterprise only, and it does not put a server on anyone's machine. Admins publish the approved server through a team marketplace, and each developer still adds it in their own Cursor (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor docs</a>, checked September 2026). The ChatGPT steps are in <a href="/blog/connect-elaichi-to-chatgpt/">connecting ChatGPT to Elaichi</a>. In every client, each member still connects once.</p>
<p>Before settling on native, put four questions to each client's admin settings, and date each answer:</p>
<ol>
<li>Can you restrict a single tool, or only a whole connected app?</li>
<li>Can you list, in one place, which members attached which accounts?</li>
<li>Does the record of a tool call name the account reached, and whether an assistant made the call?</li>
<li>When someone leaves your identity provider, when exactly does their tool access stop?</li>
</ol>
<p>An answer that meets your requirement is a fine reason to stay native, once it is written down.</p>
<h2 id="what-do-chatgpt-enterprise-and-claude-enterprise-admins-control">What do ChatGPT Enterprise and Claude Enterprise admins control?</h2>
<p>Both consoles approve apps for the whole workspace, and Claude also sets permissions per tool. Neither console reaches the other vendor's client.</p>
<p>In Claude Team and Enterprise, directory connectors stay off until an Owner or Primary Owner adds them. Adding one connects nobody, since each member still signs in (<a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities">Anthropic's connector guide</a>, checked October 2026). On Team, a member sees a Request button on a directory connector, and an Owner enables or dismisses the request (<a href="https://claude.com/docs/connectors/directory">Claude's connector directory docs</a>, checked October 2026). Custom connectors, such as one organization-wide MCP URL, are added by Owners and Primary Owners. On Enterprise, a custom role with Libraries (Manage) can add one too (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic on custom connectors</a>, checked October 2026). Owners set tool permissions per connector, per group of tools or per tool: Always allow, Needs approval or Blocked. On Enterprise, the Compliance API, which the Primary Owner turns on, records members connecting and disconnecting a connector (<a href="https://platform.claude.com/docs/en/api/compliance/activities">Anthropic's Compliance API reference</a>, checked October 2026). Anthropic says those permissions do not govern connectors a member runs locally on their own machine (<a href="https://support.claude.com/en/articles/13930452-manage-custom-roles-on-enterprise-plans">Anthropic on custom roles</a>, checked October 2026).</p>
<p>In ChatGPT, apps now sit inside plugins, managed in the Admin Console under the workspace, then Plugins. That path was read in October 2026, and OpenAI keeps moving it (<a href="https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps">OpenAI on admin controls for plugins and apps</a>, checked October 2026). Each app is on or off for the whole workspace on Business, Enterprise and Edu. Different apps for different teams is Enterprise and Edu only, through custom roles assigned to groups. Roles add up, so any role granting an app grants it, and changes take up to 5 minutes (<a href="https://help.openai.com/en/articles/11750701-managing-feature-access-with-role-based-access-control-in-chatgpt">OpenAI on role-based access control</a>, checked October 2026). Per-app Actions switch read and write actions on separately. Plugin permissions decide when ChatGPT asks first: Always ask, Allow read actions, Allow low-risk actions, and, per app only, Allow all actions (<a href="https://help.openai.com/en/articles/20001495-managing-app-permissions-in-chatgpt">OpenAI on app permissions</a>, checked October 2026). Only Admins and Owners publish a custom MCP app (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI on developer mode and MCP apps</a>, checked October 2026). The Compliance Logs Platform is Enterprise and Edu only, and no tool-name field is documented in its app events (<a href="https://chatgpt.com/public/admin/api-reference">OpenAI's admin API reference</a>, checked October 2026).</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>ChatGPT Enterprise</th>
<th>Claude Enterprise</th>
<th>One governed MCP endpoint (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who approves an app</td>
<td>Admins and Owners, in the Admin Console</td>
<td>Owners and Primary Owners, plus a custom role with Libraries (Manage)</td>
<td>An admin connects the account and writes the restrictions</td>
</tr>
<tr>
<td>Different apps per team</td>
<td>Enterprise and Edu only, through custom roles on groups</td>
<td>Custom roles narrow tool permissions further, Enterprise only</td>
<td>Restrictions written per role, with access requests for exceptions</td>
</tr>
<tr>
<td>Control below the app</td>
<td>Per-app Actions, on or off</td>
<td>Per tool: Always allow, Needs approval or Blocked</td>
<td>Per connector or per single tool, plus frozen arguments</td>
</tr>
<tr>
<td>Read versus write</td>
<td>Read and write actions switched separately per app</td>
<td>Set per tool, by the Owner</td>
<td>An allow rule naming read tools, or blocks on the write tools</td>
</tr>
<tr>
<td>The record of a call</td>
<td>Compliance Logs Platform, Enterprise and Edu only, no documented tool-name field</td>
<td>Compliance API records connector connect and disconnect events, Enterprise only</td>
<td>One trail naming the person, the account reached and the OAuth client</td>
</tr>
<tr>
<td>A second AI client</td>
<td>Covers ChatGPT only</td>
<td>Covers Claude only</td>
<td>The same URL, the same roles, the same trail</td>
</tr>
</tbody>
</table>
<p>The two layers meet in one place. To ChatGPT, Elaichi is one custom app, and its tools are <code>search_tools</code>, <code>execute_tool</code> and Elaichi's own operations, because connected tools are never listed one by one, however few there are. So ChatGPT's per-action switches cannot tell one connected app or tool behind Elaichi from another. In Claude, a tool permission on <code>execute_tool</code> covers every connected tool at once. Do not set the Elaichi app to read actions only and expect a connected app to become read-only; it does not work that way. Approval per app and per tool for the apps behind Elaichi is written in Elaichi, as restrictions.</p>
<h2 id="what-does-a-second-ai-client-cost-in-repeated-configuration">What does a second AI client cost in repeated configuration?</h2>
<p>Three things set up once start repeating per client: the account authorization, the member list and the role model. Each copy then drifts on its own schedule.</p>
<p><strong>Authorization.</strong> Every place a SaaS account is connected is a place an authorization has to be created, consented to and renewed. Two clients reaching the same Salesforce org means two authorizations to keep alive, and two places a broken connection can go unnoticed. Elaichi holds the account once. Credentials sit outside Elaichi, in a separate credential service that keeps each account's secrets encrypted with AES-256-GCM and runs the token refresh itself. A failed refresh marks the connection <code>needs_reauth</code> instead of failing quietly mid-task. Elaichi also serves the 600+ connectors, most of them authored on its own infrastructure and the rest vendors' own MCP servers, so nobody at the company runs an MCP server.</p>
<p><strong>Provisioning.</strong> Each client carries its own member list, and each list drifts from the identity directory at its own rate. Someone offboarded in the HR system on Monday can still hold a live Cursor seat on Friday if nothing carries the change across. Elaichi runs SAML and OIDC single sign-on (SSO) built in-house, plus SCIM v2 for users and groups with group-to-role mapping. SCIM is the standard an identity provider such as Okta or Entra ID uses to push joiner, leaver and group changes to an app.</p>
<p><strong>Role model.</strong> Two clients rarely agree on what a role is, so "who can reach Stripe" gets a different answer in each console. In Elaichi a member holds one role and no more, which a unique database index enforces, so each role describes a whole persona. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. That default surprises careful admins, because connecting an account does not lock it down. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer a block beats an allow. One trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Why blocks and allows match different things is set out in <a href="/blog/block-matches-name-allow-matches-operation/">the rename problem for restrictions</a>.</p>
<p>A rough measure of the repeated work is clients times shared accounts: three clients and ten accounts make thirty setups, each on its own schedule.</p>
<h2 id="which-tool-arguments-can-an-admin-pin-so-no-model-chooses-them">Which tool arguments can an admin pin so no model chooses them?</h2>
<p>Any key in a tool's argument space, frozen on a toolbox entry. A toolbox is a saved set of tools that a member or team uses, and each entry pairs one tool with one connection. Frozen parameters act in two directions. Frozen keys are left out of the schema the model reads, so it cannot set them. It can see a note that they are frozen, and often the value. Frozen values are written over whatever the caller sends at execution, so a prompt that names the key cannot un-freeze it. Precedence runs from entry defaults, up through whatever the caller or model passes, to frozen values, which always win.</p>
<p>The clearest case is a payout tool that takes a source account, a payee, an amount and a currency. The analyst decides three of those. The controller settled the source account once, and a model should not re-decide it because a document in its context named another account. Freeze the source account on the entry and the model cannot pick another one. The choice was never in the schema it read. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. The same move fixes a CRM owner field, a reporting workspace or a sandbox environment. <a href="/blog/frozen-parameters-wire-transfer-receiver/">A worked payments example</a> goes through it step by step.</p>
<p>With a client's own connectors, the model reads the argument list the app advertises to whoever attached it. Whether an admin can fix a value first is a question for that client's documentation, dated when you read it.</p>
<h2 id="who-holds-the-full-record-when-three-clients-call-the-same-app">Who holds the full record when three clients call the same app?</h2>
<p>Nobody, when each client keeps its own log. A client can record only the calls made through it, so Claude's log holds Claude's calls, ChatGPT's holds ChatGPT's, and Cursor's holds Cursor's. Each has its own field names, timestamps and idea of what counts as an event. The app at the far end usually logs the person whose account was used. There, an assistant's write and a human's write can look identical.</p>
<p>When something changes that nobody expected, the question that follows is narrow: which Notion workspace an assistant wrote to on Thursday, and through whose connection. With three clients in play, answering it means pulling three exports and the app's own history, then matching them by eye. That reconciliation is the audit cost of a second client, and each later client adds to it.</p>
<p>Elaichi keeps one trail for every client, and each row records the account a call reached and the client the call came through. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> goes through those fields one at a time. A compliance reviewer reads it on the free, read-only Auditor seat.</p>
<h2 id="what-closes-when-somebody-leaves-and-how-fast">What closes when somebody leaves, and how fast?</h2>
<p>With one endpoint, a single removal closes access from every client. With each client's own connectors, a departure is one cleanup per client, and one more per app the person attached inside it. Disabling someone's identity-provider account ends their sign-in wherever a client relies on it. It does not, by itself, list which apps they attached in each client or which account each one used.</p>
<p>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the next call from Claude, ChatGPT or Cursor fails. Role and restriction edits are slower. They take effect within about two minutes, on MCP, in the console and over REST. In an incident, suspend the member instead of editing their rules.</p>
<p>Removing a member runs a preflight that lists every connection they own. A private connection that a shared toolbox relies on blocks the removal until an admin transfers it to one other active member or deletes it. A transfer never goes to a team, the organization or the admin running the removal. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. A shared connection a team still depends on is deleted only if the admin asks for that; otherwise transfer it to someone who is staying, which leaves every grant on it as it was. The full last-day sequence is in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding a member who holds MCP connections</a>.</p>
<h2 id="when-are-chatgpts-and-claudes-own-connectors-enough">When are ChatGPT's and Claude's own connectors enough?</h2>
<p>When the unit of control and the unit of risk are the same person. Per-user sign-in is not a defect. It is the right default for a product sold to individuals, where one person's assistant reaches one person's accounts. Four cases favor staying where you are.</p>
<p><strong>One client, a few accounts.</strong> A Claude-only legal team with one document system has nothing to coordinate across clients. Neither does a support team whose only client is ChatGPT and whose only connected account is the help desk. A control plane there is another system to run, another sign-in step and another vendor, for a problem that does not exist yet.</p>
<p><strong>Small, read-mostly and unregulated.</strong> Six people and two apps, with no contractors, no regulated records and no auditor asking for a log. At that size, per-user connectors cost nothing to run and nothing to explain.</p>
<p><strong>Coverage.</strong> If the resource you need exists only as a first-party connector inside one client, no control plane creates it for you. Check that client's connector list first, because it can settle the question either way.</p>
<p><strong>Cost.</strong> A client's own connectors are part of a product you already pay for, and Elaichi is a second bill. It has two paid plans, Gold and Black. Gold lists at $15 a user each month in USD, or $120 a user for a year, and the <a href="/pricing/">pricing page</a> shows the price for your region. Elaichi offers a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. That spend pays back once the setup repeats several times, usually at a second client with a second set of shared accounts.</p>
<p>The trigger to move is usually one of four events. A second AI client arrives, or contractors and agencies get access. One person's assistant gains write access to a system other teams depend on. Or someone outside the team asks for evidence. Until then, keep the connections few and named. The longer case for waiting is in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when a gateway is premature</a>.</p>
<h2 id="what-does-one-endpoint-across-clients-not-fix">What does one endpoint across clients not fix?</h2>
<p>Three limits hold whichever client is calling.</p>
<ul>
<li>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server receives tool calls, never the prompt behind them, so there is nothing to inspect on <code>POST /mcp</code>. What holds on the endpoint instead is a role check on each operation and a <code>forbidden</code> class that no OAuth scope unlocks. Output redaction, scope limits and the audit trail hold there too.</li>
<li>Deleting an organization tears down the workspace and deletes every connector credential. Three stores keep residue, and the deletion names them: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. That matters to anyone with right-to-erasure obligations, and it is never total erasure.</li>
<li>Models reach tools differently. In Elaichi, connected tools are never listed one by one, however few there are. The model looks a tool up with <code>search_tools</code> and calls it through <code>execute_tool</code>. The ranking behind that search has <a href="/blog/search-tools-ranking-floor-idf/">a relevance floor</a>, so a near-miss is not handed to the model.</li>
</ul>
<h2 id="how-do-you-roll-it-out-without-repeating-it-per-client">How do you roll it out without repeating it per client?</h2>
<p>Connect accounts once, decide access once, and point clients at the URL last, per the <a href="https://elaichi.ai/product/">product overview</a>. In that order, adding another client later is one more URL and no new policy work.</p>
<ol>
<li>Connect the accounts the team already uses, from the <a href="/connectors/">connector catalog</a>.</li>
<li>Give each member one role, mapped from an identity provider group where SCIM is set up.</li>
<li>Write restrictions against roles, and send exceptions through an access request that an admin approves.</li>
<li>Freeze the arguments no model should choose: destructive operations, financial fields, anything with compliance exposure.</li>
<li>Point Claude, ChatGPT and Cursor at the one endpoint, and have each member connect and sign in over OAuth.</li>
<li>After a week, filter the audit trail by actor and read which OAuth client each call came through. Then adjust restrictions to what the assistants actually tried.</li>
</ol>
<p>If the alternative on the table is a per-member server inside an automation account, read <a href="/blog/zapier-mcp-alternative/">one organization server, not one per member</a>. It includes a two-week trial plan. If it is servers your own team would run, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the real cost of running them</a> does the arithmetic. For team-by-team starting points, see the <a href="/use-cases/">twelve team pages</a> and the other <a href="/blog/category/comparisons/">side-by-side write-ups</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Claude, ChatGPT and Cursor use the same MCP endpoint?</strong></dt><dd>Yes. Elaichi serves one organization-wide MCP endpoint, `POST /mcp`, and every client points at it. Each member still connects once per client and signs in over OAuth. In Cursor, the admin MCP allowlist is Enterprise only, and each developer adds the approved server.</dd><dt><strong>When are a client's own AI connectors enough?</strong></dt><dd>When one client serves one team with a few apps, and nobody outside the team asks for evidence. The usual triggers to move are a second AI client, contractor access, or an assistant that can write to a shared system of record.</dd><dt><strong>Can an admin pin a tool argument so the model cannot change it?</strong></dt><dd>Yes, in Elaichi, with frozen parameters on a toolbox entry. Frozen keys are left out of the schema the model reads, and frozen values are written over the caller's arguments at execution, so a prompt cannot un-freeze them. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</dd><dt><strong>How quickly does AI tool access stop when someone leaves?</strong></dt><dd>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the next call from any client fails. Role and restriction edits are slower and take effect within about two minutes.</dd><dt><strong>Who can see what an AI assistant did across Claude, ChatGPT and Cursor?</strong></dt><dd>With each client's own connectors, each client records only its own calls. Elaichi keeps one audit trail across every client, and each row names the account reached and the client the call came through.</dd><dt><strong>Do ChatGPT Enterprise's app controls replace an MCP gateway?</strong></dt><dd>They approve apps for the whole workspace and, on Enterprise and Edu, per group through custom roles, with read and write actions switched per app. They do not reach Claude or Cursor. They also cannot tell apart the separate tools behind a gateway's `execute_tool`, so per-app and per-tool approval for those apps is written in Elaichi, as restrictions.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>Least privilege for AI agents without breakage</title>
      <link>https://elaichi.ai/blog/least-privilege-tool-calls-without-breaking-automation/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/least-privilege-tool-calls-without-breaking-automation/</guid>
      <description>Least privilege for AI agents starts from what your pilot actually called: narrow to that recorded set, then confirm the rule landed before you trust it.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Least privilege for AI agents works best measured, not guessed. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the tool, the account reached and the result, so the tool set a pilot actually used can be read off the trail. Narrow from that recorded set, not from job titles, and write the rule against a role or a single user. A restriction change takes effect within about two minutes, so write the rule, wait, then re-list tools and call one restricted tool and one allowed tool to confirm it landed.</aside>
<h2 id="what-does-a-pilot-tell-you-about-least-privilege-for-ai-agents">What does a pilot tell you about least privilege for AI agents?</h2>
<p>Least privilege for AI agents means each agent reaches only the tools its work needs, and a pilot has already recorded what that work needed. NIST's least-privilege control, AC-6, allows only the accesses that users, or processes acting for them, need to accomplish assigned tasks (<a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">NIST SP 800-53 Rev. 5</a>). An agent calling tools for someone is a process acting on that person's behalf. So narrowing is a measurement problem before it is a policy problem, and the audit log, the append-only record of what happened, holds the measurement.</p>
<p>A six-week pilot ends with traffic, not policy. Twenty or thirty people pointed Claude, ChatGPT or Cursor at Elaichi, connected the accounts they needed, and got on with work. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps (<a href="https://modelcontextprotocol.io/specification/2026-07-28">MCP specification</a>), and every call that reached execution left a row. Nobody wrote a rule, and in Elaichi the absence of a rule means allow-all.</p>
<p>Guesswork fails in a specific way. It over-permits the tools people discuss in meetings and under-permits the ones an automation quietly depends on. Asking users does not fix it either, because they describe the outcome they wanted, not the operations the model called to get there. That gap is what breaks a workflow at 3am, and it is why a narrowing pass gets reversed a week later.</p>
<p>A pilot also leaves leftovers. OWASP's entry on excessive agency describes one exactly: an extension trialled during development and dropped for a better one, but still available to the agent (<a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP LLM06:2025</a>). Its first mitigation is to limit the extensions an agent may call to the minimum necessary.</p>
<h2 id="which-audit-fields-show-what-the-pilot-actually-used">Which audit fields show what the pilot actually used?</h2>
<p>The tool, the account reached, the result and who acted. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), which is the raw material for a narrowing decision.</p>
<p>Alongside the tool and operation, a record holds the connection, the classification, the approval decision and the result. The connection is the account the call actually reached, read from the execution rather than from what was asked. So "which of our two Notion workspaces did the agent write to" has an answer in the row itself.</p>
<p>The actor is a stored field, <code>actor_kind</code>, rather than a guess made afterwards from a user agent. Its values include <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks only the Elaichi Agent. Calls from MCP clients are recorded under the person who signed in, with surface <code>mcp</code>. Audit events and application logs share one record shape, so a single query answers what happened instead of two systems being lined up by eye.</p>
<p>Two limits shape the analysis. The record keeps the one path argument that names the object, as the target id, and nothing else about the arguments, so you can see which object was acted on, not what was written to it. The trail is also eventually consistent, so a row from the last few seconds may not have appeared yet. Neither limit changes the tool inventory you can derive. Both change how you write the query.</p>
<p>Failed calls are as informative as successes. A tool somebody tried twice and abandoned was discovered, not needed. The trail is newest-first, cursor-paginated, and filterable by free text, category, actor, action kind and time, and it is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon, for teams that would rather group the rows in their own tooling. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog.</p>
<h2 id="how-do-you-turn-pilot-audit-rows-into-a-narrower-tool-list">How do you turn pilot audit rows into a narrower tool list?</h2>
<p>Work from the recorded set, then subtract, then verify. Elaichi serves one organization-wide MCP endpoint (a single network address that receives every client's calls), so the usage matrix is one query rather than one per team.</p>
<ol>
<li>Filter or export the pilot window, start to end. Include failures.</li>
<li>Group by tool, connection and actor. You now have who called what, in which account.</li>
<li>Separate the automation traffic. Rows with an <code>actor_kind</code> of <code>api_token</code>, or <code>ai_assistant</code> for the Elaichi Agent, behave differently from a person exploring. A synthetic tool runs a graph of steps, and every step goes through the same restriction check as any other call. The audit trail holds one row for the whole run, not one per step.</li>
<li>Mark each tool used, tried, or never seen. Never-seen tools are the safe part of the cut.</li>
<li>Decide where the rule goes, role or user.</li>
<li>Write the rule, wait, then verify with a real call.</li>
</ol>
<p>Keep the list of tools that were tried and failed with a permission-shaped error. Those are the calls a user will ask you about within a day of the change, and having the list in hand turns a surprise into a reply.</p>
<h2 id="should-the-rule-sit-on-a-role-or-on-one-person">Should the rule sit on a role or on one person?</h2>
<p>On the role, almost always. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Every Elaichi member holds exactly one role, enforced by a unique index. A role is therefore a complete persona rather than a bolt-on, and a rule written against it covers everyone who holds it. Reserve user targets for genuine exceptions, such as one contractor who needs less than the team.</p>
<p>Know the limit of a user target before you use one. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A user rule can take tools away from one person, but it cannot add a tool the role withholds. If one person needs an extra tool, they file an access request and an admin approves it in the console. The approval creates a grant for that person alone, and the role rules stay as they are.</p>
<h2 id="why-does-a-first-allow-list-so-often-deny-everything">Why does a first allow list so often deny everything?</h2>
<p>Because an empty allow rule is still a rule. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That empty allow list is the most common way a first narrowing pass takes a team offline.</p>
<p>Two rules decide what your written list actually means. Within each layer, allow rules union, block rules union, and blocks always beat allows. Across layers, a member is governed by their role's rules and the rules aimed at them, and a tool is reachable only when both admit it.</p>
<p>Enforcement runs against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A restricted tool never reaches the list a client is shown. Write the rule against a spare role first if you want to see its shape before a production team feels it.</p>
<h2 id="does-an-allow-rule-survive-a-tool-being-renamed">Does an allow rule survive a tool being renamed?</h2>
<p>Yes, because the rule binds the operation rather than the label. A block matches the advertised tool name or the operation recorded at write time. An allow matches that recorded operation only.</p>
<p>A rule is written against a connector and a tool, but the canonical resource and method are pinned against the catalog when the rule is saved. The advertised name of a tool can be changed by whoever edits that connector's documentation, so the name is a token the governed party controls. Governance binds the operation, never the label. The MCP specification is similarly wary of tool metadata: clients must treat tool annotations as untrusted unless they come from a trusted server (<a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP tools specification</a>). The reasoning behind the asymmetry is worked through in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a>.</p>
<h2 id="what-happens-to-a-run-that-is-halfway-through-when-a-rule-lands">What happens to a run that is halfway through when a rule lands?</h2>
<p>It can finish three steps and fail the fourth. A synthetic tool in Elaichi is a graph of steps with no cycles, each step calls a connection's tool, and every step is checked against restrictions on its own.</p>
<p>That is the failure mode to plan for. The half-finished state sits in the third-party system, not in Elaichi. A run that created a ticket, posted a comment, then could not attach the file leaves a ticket somebody has to finish by hand. The model cannot undo the calls it already made. The run's audit row names the step that failed, so the recovery path is visible. Recovery is still manual.</p>
<p>Three habits reduce it. Read the pilot rows for scheduled or token-driven traffic before you write anything, because those runs have nobody watching them. Cut never-seen tools first and tried-but-unused tools in a second pass. Land the change in a quiet window for the systems involved, not a quiet window for your own calendar.</p>
<h2 id="does-tool-search-get-around-a-restriction">Does tool search get around a restriction?</h2>
<p>No. In Elaichi, connected tools are never listed one by one, however few there are. A model finds a connected tool through <code>search_tools</code> and calls it through <code>execute_tool</code>, and both sit behind the same gates as everything else. The second is only a naming indirection: it unwraps to the same name and arguments and falls through the identical gates, so there is no separate execution path and no privilege in it.</p>
<p>Control-plane operations stay listed individually, and <code>search_tools</code> never returns one. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. OWASP calls the principle complete mediation: every request is checked against policy, rather than the model deciding what is allowed (<a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP LLM06:2025</a>). Narrowing makes discovery quieter as well as execution safer, and the ranking behind that search is covered in <a href="/blog/search-tools-ranking-floor-idf/">how tool search applies a relevance floor</a>.</p>
<h2 id="how-do-you-confirm-a-new-rule-actually-took-effect">How do you confirm a new rule actually took effect?</h2>
<p>Wait out the window, then make real calls. A restriction change takes effect within about two minutes, and role membership behaves the same way. Both resolve through a 60-second cache plus edge propagation, on every surface, so the MCP endpoint, the console and the REST API agree inside that window.</p>
<p>Test a minute after saving and you are reading the old state. The test passes, the configuration looks right, and the workflow changes behavior while you are doing something else. Grant revocation, member removal and member suspension hold from the next call instead, and so do revoking a share and disconnecting an account. The OAuth grant, which is the authorization a client holds after signing in, is re-read from the organization store on every single call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Everything else needs the wait.</p>
<p>Build the wait into the change:</p>
<ul>
<li>Write the rule and confirm the allow list is not empty.</li>
<li>Wait about two minutes by the clock.</li>
<li>Re-list tools in the client the affected people use. A restricted tool is gone from the list.</li>
<li>Call one restricted tool and one allowed tool.</li>
<li>Read the audit row for the allowed call. It names the account reached, so you confirm you narrowed the right connection and not its twin. The restricted tool is withheld before execution, so that call writes no row.</li>
</ul>
<p>A compliance reviewer can watch all of this without a billable seat. The read-only Auditor role is a free seat, and it lacks <code>tool:execute</code>, so an auditor cannot make the test calls by accident.</p>
<h2 id="can-you-lock-one-argument-instead-of-removing-the-tool">Can you lock one argument instead of removing the tool?</h2>
<p>Yes. Sometimes the tool is needed and one argument is the problem, and frozen parameters cover that case without cutting the tool. A frozen key disappears from the schema the model works from. The frozen value is merged over the caller's arguments at execution, so passing the key cannot un-freeze it. The order runs entry defaults first, then the caller's or model's arguments, then frozen parameters, which win. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</p>
<p>This changes the shape of a narrowing pass. A tool that only had to be pinned to one workspace, one pipeline or one folder does not belong on a block list. Keeping it available with a frozen argument is usually less disruptive than removing it and then handling the ticket. <a href="/blog/frozen-parameters-wire-transfer-receiver/">How a frozen parameter protects a wire-transfer receiver</a> works one example through.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Before a team relies on this, the security page sets out how Elaichi holds credentials, shares access and records each tool call that reaches execution.</p><a href="/security/" class="cta-button">Open the security overview</a></aside>
<h2 id="when-is-a-narrowing-pass-not-yet-needed">When is a narrowing pass not yet needed?</h2>
<p>When the pilot was small. If it was five people in one team with two connected apps, the audit-driven pass buys little. Read the rows, keep the current list, and revisit when a second team joins or the first automation ships. Restrictions are cheap to add later. The analysis pays off once the usage matrix is wide enough to contain surprises, and <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway yet</a> works through the earlier version of the same judgment.</p>
<p>Two cautions hold at every size. OAuth scopes sit on top of any tool list: <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>, and a tool classified <code>forbidden</code> is reachable under no scope. The <code>mcp:tools</code> scope does not replace the ladder, so a connected tool whose method is a delete needs <code>mcp:destructive</code> as well.</p>
<p>The second caution is the prompt-injection write gate. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees a user prompt, so the gate has nothing to inspect there. What does hold on the endpoint is RBAC per operation (role-based access control, with one role per member), the <code>forbidden</code> classification, output redaction, scope limits and an audit row for each call that reaches execution. A narrow tool list belongs in that set. It does not replace it.</p>
<p>For a worked single-team example, read <a href="/blog/sales-team-chatgpt-salesforce-accounts/">how a sales team gets governed Salesforce access</a>. More decisions of this shape sit under <a href="/blog/category/governance/">governance</a>, the tools you are narrowing come from the <a href="/connectors/">connector catalog</a>, and <a href="/use-cases/">team use cases</a> show which departments usually go first.</p>
<h2>FAQ</h2><dl><dt><strong>How do I find which MCP tools my team actually used during a pilot?</strong></dt><dd>Read the audit trail. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and each record holds the tool and operation, the connection the call reached, the classification, the approval decision and the result. Filter to the pilot window, then group by tool, connection and actor for a usage matrix you can subtract from. The rows keep the one path argument that names the object, as the target id, and nothing else about the arguments, so they show which tools ran and in which account, not what the payload held.</dd><dt><strong>How long does a restriction change take to apply?</strong></dt><dd>Within about two minutes. Restrictions and role membership resolve through a 60-second cache plus edge propagation on every surface: the MCP endpoint, the console and the REST API. Grant revocation, member removal and member suspension hold from the next call, and so do revoking a share and disconnecting an account, because the OAuth grant is re-read from the organization store on every call. Plan each narrowing change with that wait and a verification call after it.</dd><dt><strong>Does an allow rule that names no tools allow everything?</strong></dt><dd>No, it denies everything. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That makes it the strictest rule you can express. Within each layer, allow rules union, block rules union, and blocks always beat allows. Check the contents of an allow rule before saving it, because an empty one takes the target down to no tools at all.</dd><dt><strong>What happens to a multi-step run when one of its tools is restricted?</strong></dt><dd>The run fails at the restricted step and leaves the earlier steps done. A synthetic tool is a graph of steps with no cycles, and every step goes through the same restriction check as any other call, so steps are checked independently. Completed steps have already changed the third-party system. The run's one audit row names the step that failed, so recovery is visible but manual. Land restriction changes when scheduled or token-driven runs are not in flight.</dd><dt><strong>Can a restriction apply to everyone in the company at once?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. To narrow broadly, write the rule against the role the affected members hold, since every member holds exactly one role. Use a user target only to narrow one person. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Engineers using ChatGPT at work: block or scope it</title>
      <link>https://elaichi.ai/blog/shadow-ai-cto-engineers-already-have-chatgpt/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/shadow-ai-cto-engineers-already-have-chatgpt/</guid>
      <description>For engineers using ChatGPT at work, scope access rather than block it. A block moves the paste to a phone; scoped access removes the reason to paste.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Engineers using ChatGPT at work already paste logs into it, and a block moves that paste to a personal phone. The alternative is scoped access to the systems engineers query anyway, which Elaichi serves through one organization-wide MCP endpoint behind OAuth. Restrictions target a role or a user, and a change to one takes about two minutes to apply. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</aside>
<p>Engineers using ChatGPT at work are already pasting stack traces and log lines into it, so the choice in front of you is whether to block it or scope it. A block holds on the managed browser and the corporate sign-in, and fails on a phone, a personal account and the assistant inside the editor. Scoping means giving the assistant governed, audited access to the systems engineers already query, so the clipboard stops being the fast path. A block still has a place, as a short holding measure while that is built.</p>
<p>Start with the artifact. An engineer hits a nil dereference in the checkout service at 2am. They copy the stack trace out of the log viewer and paste it into an assistant, asking why the frames are ordered the way they are. The trace carries three things beyond the error. A production customer ID sits in a frame argument, an internal hostname in the connection string, and a query fragment names a table.</p>
<p>None of that was the question. All of it left with the question. The paste happened for a boring reason. Reading the log needed a VPN session and a saved search, and reading the explanation needed a tool that is not in the log viewer. A clipboard closed the gap.</p>
<h2 id="what-does-a-pasted-stack-trace-leak">What does a pasted stack trace leak?</h2>
<p>Whatever happened to sit on the frame, and nobody picked those fields. The engineer picked the question. The customer ID, the hostname and the table name came along because they were in the buffer.</p>
<p>Three properties make a paste worse than a deliberate disclosure. It is unreviewable: data loss tooling can flag a paste into a browser tab on a managed device, but not which record went or which environment it came from. It is unbounded: nobody trims a trace in the middle of an incident. It is unrepeatable: the next outage produces a different trace with different fields, so no rule can be written against its shape.</p>
<p>A governed tool call has the opposite properties. It is one record, with a named operation, a named account, and a tool schema you can inspect before you allow it.</p>
<h2 id="should-you-block-engineers-using-chatgpt-at-work">Should you block engineers using ChatGPT at work?</h2>
<p>For a short window, yes; as a permanent control, no. Blocking works on the managed browser and the corporate sign-in. It does not work on a phone, a personal account, or the assistant built into the editor, so a block changes where the paste happens rather than whether it happens.</p>
<p>The cost arrives later. Once engineers route around the block, you lose the record too. Cyberhaven, which sells data loss prevention software, says in its <a href="https://www.cyberhaven.com/blog/managing-shadow-ai-best-practices-for-enterprise-security">guide to detecting shadow AI</a> that 32.3% of the ChatGPT use it sees runs through personal accounts. A company workspace is the version you can govern. OpenAI's <a href="https://openai.com/enterprise-privacy/">enterprise privacy page</a> says business data from ChatGPT Business, Enterprise and Edu is not used for training by default, and neither is data ChatGPT reads from connected apps.</p>
<p>A block is still the right call for a short window. If you have no scoped path ready and a regulator is asking questions this month, block, then build. Treat the block as a countdown, not as a control.</p>
<h2 id="what-does-scoped-access-look-like">What does scoped access look like?</h2>
<p>One address, a sign-in per person, and no shared token anywhere in the setup. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi is a governed MCP control plane: every SaaS account the company uses is connected once, and its tools are served through one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth. OAuth is the sign-in that hands the client a per-person grant instead of a secret pasted into a config file. There is no separate address per team and no token embedded in a client config, as <a href="/blog/one-endpoint-vs-per-team-endpoint/">one endpoint versus one per team</a> explains.</p>
<p>Each client reaches that address its own way, as of October 2026:</p>
<ul>
<li><strong>Claude.</strong> On Team and Enterprise, an owner adds the address under Organization settings, Connectors, and each member then connects it under Customize, Connectors, per <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's setup steps</a>. On Pro and Max, each person adds it themselves.</li>
<li><strong>ChatGPT.</strong> <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">Full MCP with write actions is a beta</a> on Business, Enterprise and Edu, where an admin creates and publishes the app. Pro users can connect MCP servers with read and fetch permissions only, in developer mode. The <a href="/blog/connect-elaichi-to-chatgpt/">ChatGPT setup guide</a> walks through it.</li>
<li><strong>Cursor.</strong> Engineers add the address by URL in <code>.cursor/mcp.json</code> or <code>~/.cursor/mcp.json</code>, or install it from a team marketplace a Team admin has shared it to. <a href="https://cursor.com/docs/mcp">Cursor supports OAuth</a> for the sign-in. An Enterprise allowlist approves a server but does not install it on anyone's machine.</li>
</ul>
<p>Connector credentials do not live in Elaichi. A separate credential service holds per-account secrets, encrypted at rest, and owns refresh. A failed refresh marks the connection <code>needs_reauth</code> rather than failing quietly. Sign-in to Elaichi itself can run over your own SAML or OIDC, with SCIM v2 provisioning and group-to-role mapping.</p>
<p>Back to the nil dereference. The engineer asks the assistant for the error and the deploy before it. The assistant reads the issue and its events through the <a href="/connectors/sentry/">Sentry connector</a>, along with the release's deploys. The customer ID never touches the clipboard, because nobody had to move it.</p>
<h2 id="how-does-the-assistant-find-the-right-tool">How does the assistant find the right tool?</h2>
<p>By search. In Elaichi, connected tools are never listed one by one, however few there are. The model asks <code>search_tools</code> for a match and runs the result through <code>execute_tool</code>. Control-plane operations stay listed individually, and the search never returns one.</p>
<p><code>execute_tool</code> is only a naming indirection. It unwraps to the same name and arguments and passes the identical gates, so there is no privilege in it. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. The search is lexical, with a relevance floor that stops it answering a query about one app with a tool from another. <a href="/blog/search-tools-ranking-floor-idf/">Why tool search needs a relevance floor</a> has the example, and <a href="/blog/context-window-problem-mcp-tools/">the context-window case for keeping tools unlisted</a> has the reasoning.</p>
<h2 id="what-do-you-have-to-write-before-you-turn-it-on">What do you have to write before you turn it on?</h2>
<p>Restrictions. A restriction is a rule about which connectors and which individual tools a target may reach, and somebody has to sit down and write them. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Opening the endpoint before any rule exists gives a broad surface to a fast client, and that is the trade-off, stated plainly.</p>
<p>A blanket rule for engineers is therefore written on the engineering role. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, allow rules union, block rules union, and blocks always beat allows. Watch for one trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>A sensible first rule allows the Sentry and <a href="/connectors/jira/">Jira</a> reads and blocks <code>delete_a_sentry_organization_issue_by_id</code> and <code>sentry_organization_issues_bulk_delete</code>. Blocks can match a tool's name, but allows bind only to the operation behind it. The advertised name is a label that whoever edits the connector's documentation can change, so governance binds the operation, never the label. <a href="/blog/block-matches-name-allow-matches-operation/">The name-versus-operation post</a> has the detail.</p>
<p>Frozen arguments handle the case where the tool is fine and one argument is not. Freeze the environment or the Jira project key on an entry. The key drops out of the schema the model is shown, and the frozen value overrides whatever the caller passes at execution. Precedence runs entry defaults, then caller arguments, then frozen values.</p>
<h2 id="how-long-does-a-restriction-change-take-to-apply">How long does a restriction change take to apply?</h2>
<p>A restriction change takes about two minutes to take effect, and so does a role change, on MCP, the console and REST alike. A runbook that assumes otherwise will be wrong during the one incident that matters. <a href="/blog/offboarding-when-the-agent-holds-access/">Why there is a delay at all</a> is covered alongside the offboarding timings.</p>
<p>Five changes are effective on the next call instead: grant revocation, member removal, suspension, revoking a share and disconnecting an account. The OAuth grant, the per-person authorization the client holds, is re-read on every call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>The operational consequence is simple. If an engineer is mid-incident and reaching something they should not, suspend the member or revoke the grant. Do not edit a restriction and then watch the next call go through anyway.</p>
<h2 id="what-does-the-audit-log-show-afterward">What does the audit log show afterward?</h2>
<p>The one thing a paste can never show: which account the assistant actually reached. The audit log, the append-only record of what happened, holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Its connection field is the account the call reached, taken from the execution rather than the intent. Each entry also names the operation, the classification, whether the call was approved and its outcome, and it records the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p><code>actor_kind</code> is set at the point of action rather than inferred later from a user agent. Its values include <code>ai_assistant</code>, which marks the Elaichi Agent. A call from ChatGPT or Claude is recorded under the engineer who signed in, with surface <code>mcp</code> and the client named. Claude, ChatGPT and Cursor are marked verified.</p>
<p>The seat that reads all of this is free: Auditor is a read-only role with no license cost and no permission to run tools. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon. <a href="/blog/what-an-ai-audit-log-must-capture/">The audit-log field guide</a> covers the full record.</p>
<h2 id="what-happens-the-day-an-engineer-leaves">What happens the day an engineer leaves?</h2>
<p>Removal runs through a preflight, and it can refuse. The preflight lists every connection the departing engineer owns, private and shared alike. Only a private connection that a shared toolbox depends on can block the removal, until an admin transfers it to a member. A private connection that nothing beyond the engineer depends on cannot be transferred and is deleted with them. A connection never passes to the organization, to a team, or to the admin running the removal.</p>
<p>A shared connection a team still depends on is deleted only if you explicitly ask for that. Otherwise transfer it to a member who is staying, which leaves every grant on the connection exactly as it was. Delegated toolbox entries, entries on the saved set of tools a person or team works from, surface as a non-blocking warning, and re-pointing the entry at another connection is the fix rather than a credential decision.</p>
<p>Once the removal goes through, every live grant the person held is revoked with it, effective on the next call rather than about two minutes later.</p>
<h2 id="where-does-scoped-access-not-help">Where does scoped access not help?</h2>
<p>Scoped access reduces the reason to paste. It does not police the chat window, and claiming otherwise would be a lie by omission. An engineer who wants to paste a trace into a personal account on a personal phone can still do it. What changes is that the fast path now runs through a tool call, and the fast path is the one people take.</p>
<p>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What the endpoint offers instead is the frozen argument: a value such as the environment stays fixed whatever text reached the model.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>For a security review, the security page covers how credentials are held, how access is shared, and how each action is attributed to a person.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="when-should-a-cto-not-build-this-yet">When should a CTO not build this yet?</h2>
<p>If you have eight engineers, one internal system to query and no contractual obligation to show who touched what, writing restrictions is overhead you will never read again. Use the assistant, keep secrets out of the log lines, and revisit when the second team asks. The case for waiting is laid out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the post on not needing a gateway yet</a>.</p>
<p>If your real exposure is people who are not employees, start with the leaving path rather than the engineering path. <a href="/blog/offboarding-when-the-agent-holds-access/">Contractor offboarding and AI access</a> covers the day somebody stops working for you.</p>
<p>If engineering is the second team rather than the first, the <a href="/use-cases/">team playbooks</a> show the same shape applied to support, finance and legal. The <a href="/connectors/">connector catalog</a> lists what is already authored, and <a href="/blog/engineering-team-cursor-jira/">Cursor and Jira for an engineering team</a> is the closest playbook.</p>
<h2>FAQ</h2><dl><dt><strong>Should we block ChatGPT for engineers?</strong></dt><dd>Only as a short holding measure. A block works on the managed browser and the corporate sign-in, and fails on a phone, a personal account and the assistant built into the code editor. It moves the paste somewhere with no record rather than preventing it. The durable answer is a company workspace plus scoped, audited access to the systems engineers already query, so the clipboard stops being the fast path.</dd><dt><strong>How long does a restriction change take to take effect in Elaichi?</strong></dt><dd>It takes about two minutes, on MCP, the console and REST alike. Three changes are effective on the next call instead: grant revocation, member removal and suspension. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. During an incident, suspend the member rather than editing a rule.</dd><dt><strong>Does an MCP endpoint stop engineers pasting stack traces into an assistant?</strong></dt><dd>No. An MCP server never sees a user prompt, so it cannot inspect or block what somebody types into a chat window. Scoped access removes the reason to paste by letting the assistant fetch the error, the deploy and the ticket directly. What the endpoint enforces is role-based permissions per operation, OAuth scope limits, output redaction and a forbidden classification that no scope can reach. Elaichi also writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</dd><dt><strong>What does Elaichi record when an AI assistant calls a tool?</strong></dt><dd>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the operation and tool, the classification, whether the call was approved, its outcome and an error code, plus the account actually reached rather than the account intended. For arguments it records the one path argument that names the object, as the target id, and nothing else about the arguments. The actor_kind field is set at the point of action. Its value ai_assistant marks the Elaichi Agent. A call from ChatGPT or Claude is recorded under the person who signed in, with the client named.</dd><dt><strong>Who can a restriction target in Elaichi?</strong></dt><dd>A role or a user. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule meant for everyone is written against each role that members hold. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>SOC 2 evidence for AI agents: CC6 and CC7</title>
      <link>https://elaichi.ai/blog/soc2-evidence-ai-agents-cc-controls/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/soc2-evidence-ai-agents-cc-controls/</guid>
      <description>SOC 2 evidence for AI agents maps to CC6.1, CC6.2, CC6.3 and CC7.2: who can reach what, how access starts and ends, and a log of each executed tool call.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi produces SOC 2 evidence for AI agents under four criteria. CC6.1 comes from one OAuth-protected MCP endpoint and its restriction rules, CC6.2 from the onboarding paths, grant revocation and the offboarding preflight, CC6.3 from a member list with exactly one role each, and CC7.2 from an audit trail that records who made each call that reaches execution and through which client. It produces nothing for CC1 through CC5, physical access, your own change management or your vendors, and it is evidence, not a certification.</aside>
<h2 id="where-does-soc-2-evidence-for-ai-agents-come-from">Where does SOC 2 evidence for AI agents come from?</h2>
<p>SOC 2 evidence for AI agents comes from four records the endpoint already keeps. They show what each person's AI can reach (CC6.1), how access is granted and removed (CC6.2), which role each person holds (CC6.3), and each tool call that reaches execution (CC7.2). None of them is produced for the audit. Each is the operating record of the endpoint, which makes a sample cheap to pull and hard to argue with.</p>
<p>The criteria are the AICPA's <a href="https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022">Trust Services Criteria</a>, the control criteria used to evaluate and report on controls over security, availability, processing integrity, confidentiality and privacy. In a Type II audit, AI access lands in logical access, next to the user access review. The auditor tests a period, not a moment, and asks for a population, the authorization behind it, and a log nobody can edit. The complication is that the population was assembled by a support lead and a finance analyst, in three different AI clients, on their own logins.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected SaaS account through one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth. Each person signs in and receives their own grant, rather than pasting a shared token into a client. One address is what makes the population countable in the first place.</p>
<p>The alternative is not an absence of AI. It is AI that leaves no record: a customer list pasted into a browser client, or a script carrying a long-lived token. Neither produces anything a tester can sample, which is why the first finding is usually about visibility rather than permissions.</p>
<p>A control plane produces evidence. It does not produce a certification. Whether Elaichi itself holds SOC 2, ISO 27001 or HIPAA attestations is a question for the <a href="/security/">Trust Center</a>. Read the answer there rather than inferring it from a blog post.</p>
<h2 id="which-artifact-answers-each-criterion">Which artifact answers each criterion?</h2>
<p>Each criterion has an artifact the auditor will ask for, and each artifact is a record Elaichi keeps for its own operation. This table pairs them.</p>
<table>
<thead>
<tr>
<th>Control</th>
<th>Artifact the auditor asks for</th>
<th>Where it comes from in Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>CC6.1</td>
<td>The access path from an AI client to company data</td>
<td>One organization-wide MCP endpoint behind OAuth; no toolbox gets its own URL, and no link carries a token</td>
</tr>
<tr>
<td>CC6.1</td>
<td>The rules that narrow what each person's AI can reach</td>
<td>Restriction rules per role and per user, covering which connectors and which individual tools a target may reach</td>
</tr>
<tr>
<td>CC6.1</td>
<td>Where app credentials are held</td>
<td>A separate credential service, which owns refresh, holds them AES-256-GCM at rest; the credentials are not in Elaichi</td>
</tr>
<tr>
<td>CC6.2</td>
<td>How people are registered before access</td>
<td>Four onboarding paths: single-use invites with roles preset, verified-domain auto-join, SCIM provisioning and just-in-time SSO</td>
</tr>
<tr>
<td>CC6.2</td>
<td>Proof that access ends on removal</td>
<td>Grant revocation: removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call</td>
</tr>
<tr>
<td>CC6.2</td>
<td>What happened to a leaver's connections</td>
<td>The offboarding preflight, which refuses a removal until each private connection a shared toolbox depends on is transferred to a member</td>
</tr>
<tr>
<td>CC6.3</td>
<td>One authorization per person</td>
<td>The member list, with exactly one role per member and each member's seat class</td>
</tr>
<tr>
<td>CC6.3</td>
<td>Least privilege and segregation of duties</td>
<td>Role definitions: Org Admin lacks <code>billing:manage</code> and <code>org:delete</code>, and <code>org:delete</code> is Owner-only</td>
</tr>
<tr>
<td>CC7.2</td>
<td>Activity records to analyze for anomalies</td>
<td>The audit trail: one entry for each connected-tool call that reaches execution (a call refused earlier writes none), with <code>actor_kind</code> and the account actually reached</td>
</tr>
<tr>
<td>CC7.2</td>
<td>A reviewer who can read the record</td>
<td>The Auditor role: read-only, a free seat, and no <code>tool:execute</code></td>
</tr>
</tbody>
</table>
<p>Work them in the order an auditor tests: the population first, the authorization second, the record third.</p>
<h2 id="cc61-what-can-an-ai-client-reach-and-on-whose-credential">CC6.1: what can an AI client reach, and on whose credential?</h2>
<p>CC6.1 asks for logical access security software, infrastructure and architecture over protected information assets. For AI access, the artifact is the endpoint itself plus the rules that narrow it. Elaichi exposes one organization-wide MCP endpoint behind OAuth. No toolbox gets a URL of its own and no link carries an embedded token, so there is no second population of addresses to go hunting for.</p>
<p>The protocol supports that shape. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization specification</a> makes a protected MCP server an OAuth 2.1 resource server, and it requires authorization on every HTTP request from client to server.</p>
<p>What to pull:</p>
<ul>
<li>Scopes on the grant: <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>. A tool classified <code>forbidden</code> is reachable under no scope at all.</li>
<li>The permission gate. <code>tool:execute</code> gates the whole endpoint ahead of every scope. Without it, <code>tools/list</code> comes back empty and a call returns an in-band error naming the permission.</li>
<li>Restriction rules, enforced at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</li>
<li>Identity. SAML and OIDC SSO built in-house, SCIM v2 with group-to-role mapping, TOTP MFA with single-use recovery codes, passkeys, and API tokens hashed at rest and shown once.</li>
</ul>
<p>One detail closes a bypass, so testers like it. A block rule matches the tool name or the underlying operation, and an allow rule matches the operation only. Whoever edits a connector's documentation controls the advertised name, so governance binds the operation instead of the label. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow does not</a>.</p>
<h2 id="where-do-the-app-credentials-actually-sit">Where do the app credentials actually sit?</h2>
<p>Not in Elaichi. A separate credential service holds per-account secrets, encrypted with AES-256-GCM at rest, and it owns refresh. When a refresh fails, the connection is set to <code>needs_reauth</code> instead of breaking quietly, so a stale token shows up as a state instead of an intermittent error.</p>
<p>A connect URL is not a credential. It is a one-time session carrying no token, which is why it is safe to return over MCP. Read-back of an account's configuration returns public values plus <code>secret_paths</code>, the list of encrypted dot-paths, with none of their values.</p>
<p>An organization can also supply its own OAuth app per connector: a client ID, a client secret and scopes, with everything endpoint-shaped deliberately unrepresentable. That path is gated on <code>connector:manage</code> rather than <code>connection:manage</code>, so the people who can delete a connection do not silently gain the ability to repoint the organization's OAuth app.</p>
<p>Key custody sits on the next plan. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. Leave it out of a control description written for Gold.</p>
<h2 id="cc62-how-do-people-get-access-and-what-happens-when-they-leave">CC6.2: how do people get access, and what happens when they leave?</h2>
<p>CC6.2 asks that new internal and external users are registered and authorized before credentials are issued, and that their credentials are removed once access is no longer authorized. Removal is where the timing is exact. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's <code>revoked_at</code> value is then re-read from the organization store on every call. For removal, suspension and grant revocation, "effective on the next call" is accurate.</p>
<p>Registration has four paths, and an auditor will want to know which ones you use. They are emailed single-use invite links with roles and teams pre-assigned, verified-domain auto-join with a configurable default role, SCIM provisioning, and just-in-time SSO. SCIM is the provisioning protocol defined in <a href="https://www.rfc-editor.org/rfc/rfc7644">RFC 7644</a>, so users and groups can come straight from your identity provider. Verified domains are proved by a DNS TXT record.</p>
<p>The second half of a deprovisioning sample is usually the weak one, and the offboarding preflight covers it. A removal is refused while a private connection is still depended on by a shared toolbox. An admin has to transfer it to another member first. A transfer goes to one member, never to a team or the organization. A private connection that nothing beyond the person depends on cannot be transferred and is deleted with them. Delegated toolbox entries raise a non-blocking warning, and re-pinning is the fix.</p>
<p>Contractors are where removal goes wrong most often. <a href="/blog/offboarding-when-the-agent-holds-access/">Cutting contractor AI access on the day they leave</a> covers that case on its own.</p>
<h2 id="cc63-how-is-each-persons-access-authorized-and-limited">CC6.3: how is each person's access authorized and limited?</h2>
<p>CC6.3 asks that access is authorized, modified and removed based on roles and responsibilities, with least privilege and segregation of duties in mind. The artifact is a member list where every member holds exactly one role. Elaichi enforces that with a unique index, so roles do not pile up over a tenure and an access review has nothing to reconcile.</p>
<p>The system roles form a strict subset chain: Guest, Member, Team Admin, People Admin, Org Admin, Org Owner. Billing Admin and Auditor sit off the chain. Two instances of segregation of duties belong in the control description. Org Admin holds every permission except <code>billing:manage</code> and <code>org:delete</code>, and <code>org:delete</code> is Owner-only, so an attacker who lands an admin account cannot delete the workspace and the evidence together. The <code>connector:create</code> permission is flagged high trust, because a custom connector can be pointed at any destination.</p>
<p>Sharing is a separate layer, and it answers the request to show that a given person cannot see a given resource. A grant of view, use or edit goes to a user, a team or the whole organization. A member sees only what they own or what was explicitly shared with them. No organization-level permission silently widens a listing, owners and admins included.</p>
<p>Two facts belong in the narrative before a tester finds them:</p>
<ul>
<li>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. Note the trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</li>
<li>A role change or a restriction change takes effect within about two minutes, because it waits out a 60-second cache before spreading across the edge. Grant revocation, member removal and suspension are effective on the next call.</li>
</ul>
<h2 id="can-the-auditor-get-a-seat-without-paying-for-one">Can the auditor get a seat without paying for one?</h2>
<p>Yes. Elaichi has an Auditor role that is read-only and a free seat, alongside Guest and Billing Admin. Org Owner, Org Admin, People Admin, Team Admin and Member are the billable seats, so a compliance reviewer does not cost a license on either plan.</p>
<p>Put the reviewer inside the system rather than emailing exports. Exported files create a chain-of-custody argument you do not need, and they go stale the day after you send them.</p>
<p>Auditor lacks <code>tool:execute</code>, which gates the whole MCP endpoint. The reviewer reads the configuration state and the audit trail. The tools list comes back empty, and any call returns an in-band error naming the missing permission. Read access to the record does not come with the ability to act on a connected account.</p>
<h2 id="cc72-how-do-you-show-that-ai-activity-is-monitored">CC7.2: how do you show that AI activity is monitored?</h2>
<p>CC7.2 asks that system components are monitored for anomalies that point to malicious acts, natural disasters or errors, and that anomalies are analyzed to decide whether they are security events. The artifact is the audit log, meaning the append-only record of who did what. In Elaichi it holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The account it records is the one the call actually reached, taken from the execution rather than from the intent.</p>
<p><code>actor_kind</code> is a field, not an inference. Its values include <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks the Elaichi Agent. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named, and those three clients are marked verified. Both are recorded at the point of action, not guessed afterwards from a user agent string. That is the difference between a monitoring control a tester can sample and one you can only describe. The full field list, and why argument contents stay out of it, is in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<p>The protocol expects such a record. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification's tools page</a> asks servers to implement proper access controls, and asks clients to log tool usage for audit purposes. A trail kept at the endpoint does not depend on which client a person happened to use.</p>
<p>Properties that come up in fieldwork:</p>
<ul>
<li>Each organization's audit history is scoped in the type system rather than by a WHERE clause. A dropped clause leaks; a wrong scope returns nothing.</li>
<li>Staff impersonation is recorded and attributed to the staff member in your own audit log, rather than appearing as you.</li>
<li>The trail is append-only, newest-first, and filterable by free text, category, actor, action kind and time. A departed member renders as "Former member" rather than being dropped.</li>
<li>It is eventually consistent, so a row may take a moment to appear. Put that in the narrative, or a tester who makes a call and refreshes at once writes a finding.</li>
</ul>
<p>Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. A Splunk HEC or Microsoft Sentinel destination is accepted but does not deliver events, so do not build a control description around either one. The audit trail inside Elaichi is on Gold.</p>
<h2 id="which-criteria-does-a-governed-mcp-endpoint-not-touch">Which criteria does a governed MCP endpoint not touch?</h2>
<p>Most of them. A control plane is a logical access and monitoring control. It says nothing about CC1 through CC5: control environment, communication and information, risk assessment, monitoring activities and control activities. CC6.4 is physical access. CC8 is change management over your own infrastructure, data and software. CC9 is risk mitigation, including the vendor risk in CC9.2, and Elaichi is one of the vendors being managed.</p>
<p>It also stops at the boundary of the account it reaches. Native permissions inside your accounting system are still yours to configure, and the model itself is not audited by the endpoint in front of it.</p>
<p>Two limits are specific to this product and belong in the narrative rather than in a finding:</p>
<ul>
<li>Prompt injection. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on the endpoint is role-based access control per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution. If prompt injection sits on your risk register, this endpoint is not the mitigating control for it.</li>
<li>Data disposal. Deleting an organization deletes the credentials and tears down the workspace, but it leaves three stores behind: the audit history (each record ages out under the log server's 90-day retention, counted from when it was written), analytics events and the credential service's connector configuration rows. It returns that residue by name. Document the residue, and do not claim complete deletion.</li>
</ul>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Before a team relies on this, the security page sets out how Elaichi holds credentials, shares access and attributes each call that runs to a person.</p><a href="/security/" class="cta-button">Open the security overview</a></aside>
<h2 id="how-do-you-assemble-the-sample-pack">How do you assemble the sample pack?</h2>
<p>Work in the order the auditor tests, population first and detail second. Six steps, each producing one exhibit.</p>
<ol>
<li>Export the member listing with role and seat class: exactly one role per member, with Guest, Billing Admin and Auditor marked as free seats.</li>
<li>Export the resource grants, showing which users and teams hold view, use or edit on each shared connection and toolbox.</li>
<li>Export the restriction rules per role and per user, recording the operations they bind rather than the advertised tool names.</li>
<li>Pull the audit log for the whole period. Filter by actor and time, then trace a sample of tool calls back to a member, a role, a connection and an outcome.</li>
<li>Take three removals and pair each with its offboarding preflight resolution and the grant revocation in the same transaction.</li>
<li>Attach the Trust Center for anything about certification status, and state in your own control description that role and restriction changes take effect within about two minutes.</li>
</ol>
<p>If your AI footprint is one team and one client, the smaller answer may still be right. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The case for not buying a gateway yet</a> sets out when that holds. Past that, the population you will be asked to enumerate is the set of SaaS accounts people have already connected. The <a href="/connectors/">connector catalog</a> runs to 600+, the <a href="/use-cases/">team pages</a> show which of the twelve teams tends to connect what, and the rest of the <a href="/blog/category/governance/">governance writing</a> covers the rules underneath.</p>
<h2>FAQ</h2><dl><dt><strong>Does a governed MCP endpoint make a company SOC 2 compliant?</strong></dt><dd>No. A control plane produces evidence for specific Trust Services Criteria, mainly CC6.1, CC6.2, CC6.3 and CC7.2. A SOC 2 report is issued by an auditor after testing your controls over a period, and it covers far more than logical access to AI tools. Elaichi's own certification status is published in its Trust Center, at elaichi.ai/security/, rather than claimed in product copy.</dd><dt><strong>What evidence shows which client made a call?</strong></dt><dd>In Elaichi a call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface mcp and the OAuth client named. The actor_kind field has values that include user, system, staff, scim, api_token and ai_assistant, which marks the Elaichi Agent. All of it is recorded at the point of action, not inferred afterwards from a user agent string. Each record also names the account the call actually reached, taken from the execution rather than from the intent.</dd><dt><strong>How quickly does removing someone cut off their AI access?</strong></dt><dd>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the removed person's next call fails. Role and restriction changes are different. They take effect within about two minutes, after a 60-second cache and edge propagation. Write that figure into the control description.</dd><dt><strong>Which SOC 2 criteria does an MCP control plane not cover?</strong></dt><dd>CC1 through CC5, which cover the control environment, communication and information, risk assessment, monitoring activities and control activities. Also CC6.4 physical access, CC8 change management over your own systems, and CC9 risk mitigation, including vendor risk. Two product limits belong in the narrative as well. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. Deleting an organization also leaves residue in three stores, so no claim of complete deletion is available.</dd><dt><strong>Can an external auditor get read-only access without paying for a seat?</strong></dt><dd>Yes. Elaichi has an Auditor role that is read-only and a free seat, like Guest and Billing Admin. Auditor does not hold the tool:execute permission, which gates the whole MCP endpoint, so the seat can read the audit trail and the configuration without being able to call any connected tool. The tools list returns empty for that seat.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Xero in Claude, without letting it edit invoices</title>
      <link>https://elaichi.ai/blog/finance-team-claude-xero/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/finance-team-claude-xero/</guid>
      <description>Xero in Claude for a finance team: analysts read invoices and reports, no assistant can edit or void an invoice, and one named person drafts supplier bills.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Put Xero in Claude for a finance team through one organization-wide MCP endpoint, and make invoices read-only with an allow rule on the analyst role that names read operations only. Xero's catalog has two families of invoice tools plus bulk updates and voids, so a block list has to find all of them, while a list of reads closes them all at once. An access request that an admin approves can let one person draft supplier bills, with the invoice type frozen on a toolbox shared with them rather than the Xero connection. Every call that reaches execution writes an audit entry naming the Xero account actually reached, and a rule change takes about two minutes to apply.</aside>
<h2 id="what-does-xero-in-claude-look-like-for-a-finance-team">What does Xero in Claude look like for a finance team?</h2>
<p>An analyst exports aged receivables from Xero to a spreadsheet, pastes it into Claude, and asks which customers to chase this week. The answer is useful. The copy of the ledger now sits in a chat window, and nothing in Xero records that it left. Putting Xero in Claude properly closes that gap, with one condition the finance lead states first: the assistant may read invoices, and it may not change them.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves the Xero connector from its own infrastructure, as it does most of its 600+ connectors, so nobody in finance or IT runs an MCP server. The <a href="/connectors/xero/">Xero connector</a> is one of the <a href="/connectors/category/accounting/">accounting connectors</a> in the catalog, with 250 tools. Most of this playbook is about which of those 250 a finance team should reach, and the answer is far fewer than all of them.</p>
<p>The shape most finance teams land on is narrow. Analysts read invoices, payments, contacts and reports. At most one person can draft a supplier bill. Nobody's assistant can edit, void or bulk-update an invoice. Every call that reaches execution lands in an audit trail that names the Xero account the call reached.</p>
<h2 id="why-does-do-not-edit-invoices-need-an-allow-rule-not-a-block">Why does "do not edit invoices" need an allow rule, not a block?</h2>
<p>Because Xero has more than one way to change an invoice. A block list has to find every one of them. An allow rule only has to name what analysts should do.</p>
<p>Look at what the catalog's Xero connector exposes. There are two families of invoice tools. One is <code>create_a_xero_invoice</code> and <code>update_a_xero_invoice_by_id</code>. The other is <code>create_a_xero_invoices_invoice</code> and <code>update_a_xero_invoices_invoice_by_id</code>. Next to them sit <code>xero_invoices_bulk_update</code>, which updates many invoices in one request, and the repeating-invoice templates. A block on one update tool leaves the other family open.</p>
<p>The names mislead in a second way. The tool called <code>delete_a_xero_invoice_by_id</code> does not delete anything. Its own description says it voids the invoice, setting its status to <code>VOIDED</code>. Xero's <a href="https://github.com/XeroAPI/Xero-OpenAPI/blob/master/xero_accounting.yaml">accounting API specification</a> lists <code>VOIDED</code> as one of six invoice statuses, beside <code>DRAFT</code> and <code>PAID</code>. A void is a real change to the ledger, and an assistant should not reach it by accident.</p>
<p>So the analyst rule is an allow rule against the analyst role, naming read operations only. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Once an allow rule exists for a target, everything it does not name is denied. That covers both invoice families, the bulk update, the void, payments, contact edits, and any tool added to the connector next quarter.</p>
<p>The reach is wider than Xero. Once the analyst role holds an allow rule, every connector that no allow rule on that role names is denied for the role, not only the other Xero tools. Allow rules on the same role add up, so give the role an allow rule for each other app it uses, where naming a whole connector is fine, or the team loses those apps.</p>
<h2 id="which-xero-tools-should-a-finance-analyst-reach">Which Xero tools should a finance analyst reach?</h2>
<p>The reads that answer the questions finance actually asks. A workable first list:</p>
<ul>
<li>Invoices and bills: <code>list_all_xero_invoices</code>, <code>get_single_xero_invoice_by_id</code> and <code>xero_invoices_download</code> for the PDF.</li>
<li>Payments and contacts: <code>list_all_xero_payments</code>, <code>list_all_xero_contacts</code>.</li>
<li>The ledger: <code>list_all_xero_accounts</code>, <code>list_all_xero_bank_transactions</code>, <code>list_all_xero_journals_journals</code>.</li>
<li>Reports: <code>list_all_xero_reports_aged_receivables_by_contacts</code>, <code>list_all_xero_reports_aged_payables_by_contacts</code>, <code>list_all_xero_reports_profit_and_loses</code>, <code>list_all_xero_balance_sheet</code> and <code>list_all_xero_reports_trial_balances</code>.</li>
</ul>
<p>Write the rule against the role, not against people, so a new analyst inherits it on day one. Then check the rule before you save it. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. An empty allow list takes the whole team offline, which is the safe failure, but still a failure.</p>
<p>One mechanic decides how the names behave. A rule is written against a connector and a tool, and the canonical operation is pinned against the catalog when you save it. A block matches the tool name or the pinned operation. An allow matches the pinned operation only, because a tool's advertised name can be changed by whoever edits the connector's documentation. <a href="/blog/block-matches-name-allow-matches-operation/">Why a block matches the name and an allow matches the operation</a> works through the reasoning.</p>
<p>Keep the Xero side narrow as well. A restriction decides what Elaichi will advertise and run. The account you connect still decides what Xero will accept, so connect with a Xero user whose own role fits the job.</p>
<h2 id="how-do-you-let-one-person-draft-supplier-bills">How do you let one person draft supplier bills?</h2>
<p>With an access request for the one create tool, and a frozen argument on the toolbox entry they use.</p>
<p>The request comes first. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. So a rule aimed at the clerk cannot add the create tool. Instead, the accounts payable clerk files an access request for <code>create_a_xero_invoices_invoice</code>. An admin approves it in the console, under Governance, then Access requests. No AI client and no Elaichi Agent can approve it, and nobody approves their own request. Approval creates an access grant for that one person. The grant lifts exactly that tool out of the clerk's role rules. Every other role rule keeps applying, so the clerk keeps the same reads, and nobody else changes. No rule is written and the role is not edited.</p>
<p>Then the frozen argument. That create tool requires a <code>Type</code>. Xero's specification allows both <code>ACCPAY</code>, its code for a purchase bill, and <code>ACCREC</code>, its code for a sales invoice. On the clerk's toolbox entry for the tool, freeze <code>Type</code> to <code>ACCPAY</code>. Frozen keys are stripped from the schema the model sees, so it is never offered the field. Frozen values are merged over the caller's arguments at execution, so passing <code>ACCREC</code> anyway changes nothing. The precedence runs entry defaults, then the caller's or model's arguments, then frozen parameters.</p>
<p>One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. If the clerk also holds <code>use</code> on the Xero connection, directly or through a finance team share, the clerk's Claude reaches the create tool unfrozen and can raise a sales invoice. A block on the create tool would not close that gap, because restrictions apply to toolbox entries too and would withhold the frozen entry as well. Leave the Xero connection unshared. Give the clerk a toolbox with the reads and the frozen create entry, and give the analysts a toolbox of the reads.</p>
<p>A freeze rewrites a call rather than refusing it. If someone asks the clerk's assistant for a sales invoice, the call goes through as a bill, and a person deletes the stray draft in Xero. That is the trade: an odd draft is possible, and a sales invoice raised by an assistant is not.</p>
<p>The result is narrow on purpose. The clerk's assistant can draft a supplier bill and cannot raise a sales invoice. Nobody's assistant can update, bulk-update or void an existing invoice, because the role's allow rule does not name them and no grant lifts them.</p>
<h2 id="what-can-each-finance-role-do">What can each finance role do?</h2>
<p>Three roles cover most finance teams. The table is the whole design on one screen.</p>
<table>
<thead>
<tr>
<th>Person</th>
<th>Xero reads</th>
<th>Draft a supplier bill</th>
<th>Edit, void or bulk-update an invoice</th>
<th>Seat</th>
</tr>
</thead>
<tbody>
<tr>
<td>Analyst, by role allow rule</td>
<td>The named reads</td>
<td>No</td>
<td>No</td>
<td>Paid</td>
</tr>
<tr>
<td>Accounts payable clerk, by access grant</td>
<td>The same reads, kept</td>
<td>Yes, through a toolbox with <code>Type</code> frozen to <code>ACCPAY</code></td>
<td>No</td>
<td>Paid</td>
</tr>
<tr>
<td>Compliance reviewer, on the Auditor seat</td>
<td>None: the seat has no <code>tool:execute</code></td>
<td>No</td>
<td>No</td>
<td>Free</td>
</tr>
</tbody>
</table>
<p>OAuth scopes add one more ceiling. A scope is the limit attached to the client's sign-in. Reads need <code>mcp:read</code>, a create needs <code>mcp:write</code>, and a destructive call needs <code>mcp:destructive</code>. A tool classified as forbidden is reachable under no scope at all.</p>
<h2 id="which-xero-organization-did-the-assistant-reach">Which Xero organization did the assistant reach?</h2>
<p>Xero lets one sign-in authorize several organizations. Before rollout, run <code>list_all_xero_connections</code>. It lists every organization the sign-in granted, by name, because Xero's <a href="https://github.com/XeroAPI/Xero-OpenAPI/blob/master/xero-identity.yaml">identity API</a> returns one connection per organization the user authorized. If the sign-in reaches an entity the team should not touch, narrow the authorization in Xero before anyone points Claude at it.</p>
<p>After rollout, the audit entry answers the question. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none) (<a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must capture</a> covers the rest of the record). The Xero organization on an entry comes from the execution, not the request, so it is the one the call actually reached.</p>
<p>A compliance reviewer does not need a paid seat to read it. Auditor is a free, read-only role in Elaichi, and it lacks <code>tool:execute</code>, so the reviewer can read the trail and cannot run a Xero tool.</p>
<h2 id="how-does-claude-reach-xero-through-elaichi">How does Claude reach Xero through Elaichi?</h2>
<p>Through one organization-wide endpoint, <code>POST /mcp</code>, behind OAuth. In Claude Team and Enterprise, an owner adds it under Organization settings, Connectors, Add, Custom, Web, and members then connect it under Customize, Connectors. On Pro and Max, each person adds it under Customize, Connectors, the plus button, then Add custom connector (<a href="https://support.claude.com/en/articles/11175166">Anthropic's guide</a>). Each analyst signs in as themselves, so the grant is per person and the address is the same for everyone.</p>
<p>An MCP client discovers a server's tools with a <code>tools/list</code> request (<a href="https://modelcontextprotocol.io/specification/2025-06-18/server/tools">MCP specification</a>). In Elaichi, connected tools are never listed one by one, however few there are. Claude searches for a Xero tool before calling it, as <a href="/blog/context-window-problem-mcp-tools/">the post on tool lists and context</a> explains. A tool withheld by a restriction cannot be called. If an analyst's Claude searches for an invoice update tool, it sees only the name, flagged restricted, with no schema. ChatGPT and Cursor point at the same address, which <a href="/blog/elaichi-vs-native-ai-connectors/">the native connector comparison</a> covers.</p>
<p>The Xero credential does not live in Elaichi. A separate credential service holds it, encrypted at rest, and owns refresh. A failed refresh marks the connection <code>needs_reauth</code> instead of failing silently, so a lapsed Xero sign-in shows up as a connection to fix. It does not show up as a mysterious empty answer.</p>
<h2 id="how-do-you-test-it-before-month-end-close">How do you test it before month-end close?</h2>
<p>Run four checks with real accounts before the team relies on it. Each one takes a few minutes, and together they prove the design rather than the intent.</p>
<ol>
<li>Sign in as an analyst and ask Claude to void a test invoice. Claude should be unable to run any tool that can do it, because the void tool is restricted for that role and search shows only its name.</li>
<li>Ask the same analyst's Claude for an aged receivables summary. It should work, and the audit entry should name the Xero account reached and the analyst as the actor, with Claude as the client.</li>
<li>As the clerk, after the access request is approved, draft a supplier bill from a vendor's total and check in Xero that it arrived as a bill. Then ask for a sales invoice. It should arrive as a bill as well, which you delete.</li>
<li>Suspend the test analyst and ask again. The next call should fail, with no wait.</li>
</ol>
<h2 id="when-does-a-rule-change-take-effect">When does a rule change take effect?</h2>
<p>A role or restriction change takes about two minutes to apply, on the MCP endpoint, the console and the REST API alike. Plan rule changes around that window, not around a page refresh.</p>
<p>Some changes take effect on the next call instead: grant revocation, member removal and suspension, and revoking a share or disconnecting an account. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. If an analyst leaves during month-end close, remove or suspend them, and their Claude session stops on its next call. Do not edit the role and wait. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding a member with MCP connections</a> sets out why the two speeds differ and what a removal checks first.</p>
<h2 id="why-not-run-xeros-own-mcp-server-instead">Why not run Xero's own MCP server instead?</h2>
<p>You can, and for one analyst on one Xero organization it may be all you need. Xero publishes the server, and it is open source (<a href="https://github.com/XeroAPI/xero-mcp-server">XeroAPI/xero-mcp-server</a>, read October 2026). It is also run by you. Each client installs it with <code>npx</code> in its own configuration, and it authenticates with a Xero custom connection or a bearer token. It is not a hosted endpoint.</p>
<p>Where it wins is plain. It is Xero's own code, so there is no second vendor, and it runs under Xero's own permission model. You can read every line before you install it.</p>
<p>What Elaichi adds starts with hosting. Nothing is installed on an analyst's machine, and a separate credential service holds the Xero credential and owns its refresh. One address serves Xero and the team's other apps to Claude, ChatGPT and Cursor. The analyst role's Xero rule sits beside its rules for every other app, and the clerk's toolbox keeps <code>Type</code> frozen to <code>ACCPAY</code>. One audit trail covers every connected app, and removing or suspending a person ends their access to all of them on their next call. The README does not describe per-role rules or an audit trail, so if you need those from Xero's server itself, ask Xero.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Every Xero tool a rule can name is on the Xero connector page, along with each client's setup.</p><a href="/connectors/xero/" class="cta-button">Browse the Xero tools</a></aside>
<h2 id="when-is-a-spreadsheet-export-still-the-right-answer">When is a spreadsheet export still the right answer?</h2>
<p>When one person in finance uses Claude occasionally against one Xero organization. A narrow Xero user and a manual export have a smaller blast radius than any access layer you can stand up this week, and nobody has to maintain an allow list. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The case for waiting</a> lists the signals that end the wait.</p>
<p>The costs of doing it are real. The allow list needs a look when the Xero connector gains tools, although new tools stay denied until you add them. Rule changes lag by about two minutes. Seat rules and the price for your region are on the <a href="/pricing/">pricing page</a>.</p>
<p>The case for doing it arrives with the second analyst, a second Xero organization, or the first auditor who asks which ledger an assistant touched. The sales version of this sequence is the playbook on <a href="/blog/sales-team-chatgpt-salesforce-accounts/">ChatGPT access to Salesforce accounts</a>. Other teams are on the <a href="/use-cases/">use cases page</a>, and every app you can connect is in the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Claude edit a Xero invoice if the finance role is read-only?</strong></dt><dd>Not through Elaichi. An allow rule on the analyst role that names only read operations leaves every other Xero tool unreachable, including both invoice update tools, the bulk update and the void. Xero still decides what the connected account may do, so keep that account's own permissions narrow too.</dd><dt><strong>Why not just block the invoice update tool?</strong></dt><dd>Because there is more than one. The Xero catalog has two families of invoice tools, update_a_xero_invoice_by_id and update_a_xero_invoices_invoice_by_id, plus xero_invoices_bulk_update and a tool named delete_a_xero_invoice_by_id that voids the invoice. A block list has to name each one. An allow rule naming only reads closes all of them at once, and covers tools added to the connector later.</dd><dt><strong>Which Xero organization did Claude read from?</strong></dt><dd>The audit entry answers it. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each one records the Xero organization the call reached, taken from the execution rather than the request. One Xero sign-in can authorize several organizations, so check list_all_xero_connections before rollout and connect only what the team should reach.</dd><dt><strong>How long does a restriction change take in Elaichi?</strong></dt><dd>It takes about two minutes, on the MCP endpoint, the console and the REST API alike. Grant revocation, member removal and suspension are faster: each is effective on the next call, as are revoking a share and disconnecting an account.</dd><dt><strong>Why not use Xero's own MCP server?</strong></dt><dd>Xero publishes an open-source MCP server, but you run it yourself. Each client installs it with npx in its own configuration, it authenticates with a Xero custom connection or a bearer token, and it is not a hosted endpoint. It needs no second vendor. Elaichi hosts the connector and adds what spans apps: one address for every AI client, role rules written once, frozen arguments such as an invoice type, one audit trail, and one removal that ends a person's access to every connected app.</dd><dt><strong>Does a compliance reviewer need a paid seat to read the trail?</strong></dt><dd>No. Auditor is a free, read-only seat in Elaichi. It lacks the tool:execute permission that gates the MCP endpoint, so a reviewer can read the audit trail and cannot run any Xero tool.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Lunar MCPX alternative: count your servers first</title>
      <link>https://elaichi.ai/blog/lunar-mcpx-alternative-governed-access/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/lunar-mcpx-alternative-governed-access/</guid>
      <description>With no MCP servers to front, the Lunar MCPX alternative is a hosted server like Elaichi. With several, a gateway like MCPX still fits.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Lunar.dev describes MCPX as a self-hosted gateway that sits between agents and the MCP servers, APIs and LLM providers they use, and Boomi has completed its acquisition of Lunar.dev. If your estate already has servers in it, that shape fits. If it has none, Elaichi is the Lunar MCPX alternative that removes the servers: one organization-wide MCP endpoint behind OAuth, with connectors Elaichi authors or governs. Self-hosting still wins where policy puts the tool plane inside your own network.</aside>
<h2 id="do-you-already-run-mcp-servers">Do you already run MCP servers?</h2>
<p>Count them first, because the count decides the answer. With none, the Lunar MCPX alternative to look at is a hosted MCP server such as Elaichi, which serves your SaaS accounts with no servers of your own to run. With several, a gateway is the right shape, and MCPX belongs on the shortlist. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>The gateway case looks like this. An engineer stands up an MCP server for the internal ticketing API. A data team ships a second one over the warehouse. A year later there are nine, each with a token file, a deploy story and its own opinion about who may call what. That estate has a gateway-shaped problem, and a gateway is the right purchase.</p>
<p>A company with zero MCP servers reads the same gateway pages and reaches the wrong answer. Support, finance and legal are not waiting for a proxy. They are waiting for Salesforce, Xero and Jira to show up inside ChatGPT with limits attached. Buying a gateway in that state means first finding or building the servers it is supposed to govern.</p>
<h2 id="what-is-lunardevs-mcpx-built-for">What is Lunar.dev's MCPX built for?</h2>
<p>MCPX is built for an estate that already has servers in it. <a href="https://www.lunar.dev/">Lunar.dev</a> presents MCPX as an "Enterprise MCP Gateway" that sits between agents and the MCP servers, APIs and LLM providers they use (checked October 2026). The same page says MCPX is fully self-hosted, running inside your own infrastructure, and an open-source version is on <a href="https://github.com/TheLunarCompany/lunar">GitHub</a>.</p>
<p>Read the shape of that description. A gateway is a middle. It assumes two ends: agents on one side, servers and APIs on the other. Its value comes from consolidating control over servers and APIs your agents already use. If those exist, that value arrives on day one. You keep the server code, the network path and the release cycle, and you gain one place to watch the traffic.</p>
<p>The same description implies the standing work. A middle is only as current as its ends. Nine servers still need nine upgrades when a vendor changes an API, and nine owners on call when one of them stops refreshing a token. That is a fair price for an estate that wanted those servers. It is a strange price for an estate that never asked for them.</p>
<p>Tyk and Zuplo sell a related shape from an API management starting point (both checked October 2026). <a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk's MCP Gateway</a> proxies and governs remote MCP servers. <a href="https://zuplo.com/mcp-gateway">Zuplo's MCP Gateway</a> federates MCP servers behind one OAuth-protected gateway.</p>
<h2 id="what-does-the-boomi-acquisition-change">What does the Boomi acquisition change?</h2>
<p>It changes who owns the roadmap, not the shape of the product. Boomi announced a letter of intent to acquire Lunar.dev on May 13, 2026 (<a href="https://boomi.com/resources/resources-library/lunar-dev-boomi/">Boomi press release</a>). It has since completed the acquisition (<a href="https://boomi.com/blog/lunar-dev-boomi-acquisition/">Boomi blog</a>, checked October 2026).</p>
<p>Treat that as a set of questions to put in writing, not as a verdict. Ask about standalone pricing now that the gateway sits inside a larger platform. Ask about the release cadence of the open-source version. Ask whether support terms survive without a wider platform contract. Ask which buyer the roadmap now follows. An acquisition is not a reason to rule a product out. An unanswered roadmap question is a reason to keep the first commitment short.</p>
<h2 id="what-does-a-lunar-mcpx-alternative-look-like-with-no-servers-to-front">What does a Lunar MCPX alternative look like with no servers to front?</h2>
<table>
<thead>
<tr>
<th>Axis</th>
<th>Lunar MCPX</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Where it runs</td>
<td>Self-hosted, inside your own infrastructure, which some auditors require</td>
<td>Hosted service; every SaaS account served through one org-wide <code>POST /mcp</code> endpoint behind OAuth</td>
</tr>
<tr>
<td>What it serves</td>
<td>The MCP servers, APIs and LLM providers your agents already use</td>
<td>600+ connectors, most authored by Elaichi and the rest vendors' own MCP servers it governs</td>
</tr>
<tr>
<td>Who maintains the tools</td>
<td>Whoever runs each server behind the gateway</td>
<td>Elaichi; custom work through JSON config, or forks with a review step for upstream changes</td>
</tr>
<tr>
<td>Per-tool rules</td>
<td>Ask how rules are written and where each one is enforced</td>
<td>Block or allow rules on a role or a user, checked wherever a member can reach a connector or tool, including the outbound URL</td>
</tr>
<tr>
<td>A leaver's access</td>
<td>Ask how it is cut at the gateway and at each server</td>
<td>Grant re-read on every call; a preflight for personal connections</td>
</tr>
<tr>
<td>Audit</td>
<td>Ask what the gateway records and what each server records</td>
<td>One record shape across audit and application logs; each entry names the account reached</td>
</tr>
<tr>
<td>Cost model</td>
<td>Engineer time to run it; open-source version on GitHub; commercial terms to confirm after the Boomi deal</td>
<td>Gold lists at $15 per user per month in USD; free read-only Auditor seat</td>
</tr>
</tbody>
</table>
<p>For a company with no servers, the server is the cost, so the useful Lunar MCPX alternative deletes that line rather than governing it. A gateway routes traffic to servers that already exist. Elaichi serves the tools itself.</p>
<p>Elaichi is a governed MCP control plane. Every SaaS account the company uses is connected once, and the tools those accounts expose are served through one organization-wide endpoint: <code>POST /mcp</code>, standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. No toolbox gets its own URL, and no token rides inside a link. An admin adds that address once where each AI client allows it, and each person then connects and signs in as themselves. <a href="/blog/connect-elaichi-to-chatgpt/">Connecting ChatGPT</a> shows one client's flow end to end. Elaichi authors, maintains and serves most of the connectors from its own infrastructure, and the catalog runs to 600+. The rest are vendors' own MCP servers that Elaichi staff publish one by one, not an open registry, and there is nothing for your team to deploy.</p>
<h2 id="who-decides-what-a-tool-call-may-touch">Who decides what a tool call may touch?</h2>
<p>Three layers decide it, and they stay separate. Permissions group 58 action strings into roles, and a member holds exactly one role, so every role is a complete persona. Sharing is a grant of view, use or edit on a resource to a user, a team or the whole org. Nobody sees a resource they neither own nor were given, org owners included.</p>
<p>Restrictions are the third layer: which connectors and which individual tools a target may reach. One limit on them is deliberate: restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Blocks always beat allows inside each layer. A block can match a tool's name or the operation underneath it, while an allow matches the operation alone. The reason is in <a href="/blog/block-matches-name-allow-matches-operation/">the writeup on names versus operations</a>. Every rule is checked at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<h2 id="who-holds-the-credentials-in-each-shape">Who holds the credentials in each shape?</h2>
<p>With a gateway in front of servers you run, your team holds them. Each server carries its own secret and its own refresh path, and rotation is a job with your name on it.</p>
<p>Connector credentials never sit in Elaichi. Secrets for each account live in a separate credential service that encrypts them at rest and handles refresh. A refresh that fails flags the connection <code>needs_reauth</code>, so the break shows up where someone will see it. A connect URL is a one-time session that carries no token, which is why it is safe to return over MCP. Read-back of an account's configuration returns public values plus the list of dot-paths that were encrypted, carrying none of their values. An org can supply its own OAuth app per connector. That setting is gated on <code>connector:manage</code>, not <code>connection:manage</code>, so deleting a connection and repointing the org's OAuth app stay separate powers.</p>
<h2 id="when-is-self-hosting-still-the-requirement">When is self-hosting still the requirement?</h2>
<p>Self-hosting wins whenever your policy puts the tool plane inside your own network. An air-gapped segment, an internal system with no internet-reachable API, or a control that requires inspection of every outbound packet all point at a self-hosted gateway. Elaichi runs as a service, so in those estates it is not the answer and MCPX is a reasonable place to look.</p>
<p>Elaichi does carry controls that regulated buyers ask about. An organization picks its region at creation. Elaichi has three regions, EU, US and APAC. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. None of that is the same sentence as "inside our VPC", so check which sentence your auditor actually wrote.</p>
<h2 id="what-do-you-give-up-when-the-servers-disappear">What do you give up when the servers disappear?</h2>
<p>Three things, stated plainly. First, you no longer own the connector code. Elaichi authors it. You can fork a public connector, edit its JSON config, and pull upstream changes. A review surface separates new tools, safe updates, config diffs, conflicts and upstream removals. But the base is not yours.</p>
<p>Second, prompt injection. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on the endpoint: role-based permissions per operation, the <code>forbidden</code> classification that no OAuth scope reaches, output redaction, scope limits and an audit row for each call that reaches execution.</p>
<p>Third, cost shape. Gold lists at $15 per user per month, or $120 per user per year, in USD, and <a href="/pricing/">pricing</a> shows the price where you are. Black is the other plan. There is a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. If a trial ends without checkout, the workspace pauses rather than losing anything. A self-hosted gateway converts that line into engineering time, which is cheaper at some headcounts and much more expensive at others. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The self-hosted versus managed arithmetic</a> works it through.</p>
<p>One more disclosure while you cost it: deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name. It never claims a clean wipe.</p>
<h2 id="how-does-each-shape-show-which-account-an-agent-wrote-to">How does each shape show which account an agent wrote to?</h2>
<p>Elaichi answers from its own audit trail, with no correlation work. The trail holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection on each entry is the account the call reached, taken from the execution itself. Audit events and application logs share one record shape, so a single query answers what happened. The <code>actor_kind</code> field is recorded at the point of action rather than guessed from a user agent, and its values include <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from an MCP client is recorded under the person who signed in, with the OAuth client named. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. The read-only Auditor seat is free, so a compliance reviewer does not consume a license.</p>
<p>Two error strings exist per failed call. The one returned to the caller derives from the third party's response body. The one written to the audit trail never does, because audit records are org-visible and fan out to whatever SIEM you configured.</p>
<p>With a gateway in front of servers you run, the answer depends on what the gateway records and on what each server behind it records. Settle that inventory question on a quiet afternoon rather than during an incident.</p>
<h2 id="what-happens-on-the-day-somebody-leaves">What happens on the day somebody leaves?</h2>
<p>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A grant is the OAuth authorization a client holds for that person. Its revocation status is re-read on every single call, so removal is effective on the next call. Role and restriction changes are different. They resolve through a short cache and take effect within about two minutes, on the MCP endpoint, the console and the REST surface alike.</p>
<p>Offboarding runs a preflight that lists every connection the departing member owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until you transfer it to an active member, never to the organization, to a team, or to the admin running the removal. A private connection nothing else depends on cannot be transferred and is deleted with the member. A shared connection a team still depends on is left untouched unless you delete it, so transfer it to someone who is staying, which leaves every grant on it as it was. For the contractor version of this problem, <a href="/blog/offboarding-when-the-agent-holds-access/">the offboarding walkthrough</a> covers what to do before any of this is in place.</p>
<h2 id="how-do-you-sort-your-own-estate-in-an-afternoon">How do you sort your own estate in an afternoon?</h2>
<p>Start with the count, then price both shapes against it. The steps below take a couple of hours and settle the question better than any feature grid.</p>
<ol>
<li>List every MCP server running in your company today, with an owner name against each.</li>
<li>List the AI clients your people already use, and check how each one lets an admin add a single URL for members to connect to.</li>
<li>Read your own policy for the sentence about where third-party processing may happen.</li>
<li>Price the gateway path as engineer-weeks per quarter, and the hosted path as billable seats.</li>
<li>Trial whichever shape the first four answers favor, scoped to one team and one connected app.</li>
</ol>
<p>If the count in step one is zero and step three does not require your own network, you are buying a hosted MCP server. If it is nine, you are buying a gateway, and the acquisition questions belong in that conversation. If both answers feel premature, <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting</a> is a real one. For the wider field, see <a href="/blog/what-is-an-mcp-gateway/">what an MCP gateway is, shape by shape</a>. When you want to see what a single endpoint would serve, browse the <a href="/connectors/">connector catalog</a> or the <a href="/use-cases/">team use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Is Lunar's MCPX self-hosted?</strong></dt><dd>Yes. Lunar.dev describes MCPX as a self-hosted Enterprise MCP Gateway that sits between agents and the MCP servers, APIs and LLM providers they use, with an open-source version on GitHub (lunar.dev, checked October 2026). It is built to front servers and APIs your agents already use, so it pays off when those exist in your estate.</dd><dt><strong>Did Boomi acquire Lunar.dev?</strong></dt><dd>Yes. Boomi announced a letter of intent to acquire Lunar.dev on May 13, 2026, and has since completed the acquisition, per Boomi's own announcements (boomi.com, checked October 2026). For a buyer evaluating MCPX, the useful follow-ups are standalone pricing, the release cadence of the open-source version, and support terms outside a wider platform contract.</dd><dt><strong>What is a Lunar MCPX alternative for a company that runs no MCP servers?</strong></dt><dd>Elaichi, a governed MCP control plane. Instead of proxying servers you deployed, Elaichi serves every connected SaaS account through one organization-wide endpoint at POST /mcp, standard MCP over Streamable HTTP and JSON-RPC 2.0, behind OAuth. There are no per-toolbox URLs and no embedded tokens, and Elaichi authors most connectors and governs vendors' own MCP servers for the rest, so the company never runs an MCP server.</dd><dt><strong>When is a self-hosted MCP gateway still the right choice?</strong></dt><dd>When policy requires the tool plane to run inside your own network. Air-gapped segments, internal systems with no internet-reachable API, and controls that require inspection of every outbound packet all point at self-hosting. Elaichi runs as a service with three regions, EU, US and APAC. For EU and US, the data store and the execution of org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. Neither is a substitute for running the software in your own VPC.</dd><dt><strong>How quickly does a permission change take effect in Elaichi?</strong></dt><dd>Role and restriction changes take effect within about two minutes, because they resolve through a short cache on every surface. Grant revocation is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Revocation status is re-read on every call, so it is effective on the next call.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>Should marketing get HubSpot inside ChatGPT?</title>
      <link>https://elaichi.ai/blog/marketing-team-chatgpt-hubspot-campaigns/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/marketing-team-chatgpt-hubspot-campaigns/</guid>
      <description>Yes: marketing can have HubSpot inside ChatGPT to read contacts and campaigns and draft work, with email sends and deletes restricted and the portal pinned.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Yes, with limits. Through Elaichi, marketing can use HubSpot inside ChatGPT to read contacts, lists and campaign results and to draft notes, tasks and logged emails. One block rule takes away every tool that sends email, another takes away the deletes, and a toolbox pinned to the production portal, shared in place of the connection, keeps writes out of the wrong one. A restriction change takes about two minutes to apply.</aside>
<h2 id="should-marketing-get-hubspot-inside-chatgpt">Should marketing get HubSpot inside ChatGPT?</h2>
<p>Yes, with three limits. Marketing can have HubSpot inside ChatGPT to read contacts, lists and campaign results, and to draft notes, tasks and logged emails. The limits are a block rule on every tool that sends email and a second block on the deletes. The portal is pinned, so no write lands in the wrong HubSpot account.</p>
<p>The request usually starts small. A campaign manager wants to ask which contacts opened the last nurture email, and read the answer from HubSpot rather than from an exported CSV. IT agrees with the goal. What stalls the rollout is the rest of the account, because the login that reads a campaign report can also send email and archive contacts.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi is a governed MCP control plane. It serves HubSpot and the rest of a 600+ catalog through one organization-wide endpoint, so each limit below is a setting, not code. The <a href="/connectors/hubspot/">HubSpot connector page</a> lists every HubSpot tool, and the <a href="/connectors/category/crm/">CRM connectors</a> sit beside it.</p>
<h2 id="what-can-marketing-do-in-hubspot-from-chatgpt">What can marketing do in HubSpot from ChatGPT?</h2>
<p>Read and draft. The reads a campaign manager reaches for are <code>list_all_hubspot_contacts_search</code>, <code>list_all_hubspot_contact_lists</code>, <code>list_all_hubspot_email_campaigns</code>, <code>list_all_hubspot_marketing_emails</code> and <code>list_all_hubspot_email_events</code>. Drafting means writes no customer sees: <code>create_a_hubspot_note</code>, <code>create_a_hubspot_task</code> and <code>create_a_hubspot_email</code>. That last tool records an email on a contact's timeline and sends nothing. HubSpot's <a href="https://developers.hubspot.com/docs/api-reference/legacy/crm/activities/emails/guide">email engagement guide</a> describes the API behind it as the way to "log and manage emails on CRM records".</p>
<p>Marketing reaches those tools through a toolbox, a curated set of tools shared with the team, rather than through the HubSpot connection itself. That is what lets a pinned portal hold. Nobody outside marketing sees the toolbox: in Elaichi, a member's list holds what they own and what someone explicitly shared with them, nothing more. The credentials stay out of Elaichi: a separate credential service holds them, encrypted at rest, and owns the token refresh.</p>
<p>Writes need the right ChatGPT plan. OpenAI says full MCP support, "including modify/write actions, is rolling out in beta to ChatGPT Business, Enterprise, and Edu plans" (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI help center</a>, checked October 2026). On those plans an admin creates the app and publishes it to the workspace. The same page says "Pro users can connect MCPs with read/fetch permissions in developer mode". A marketer on Pro can read campaigns but cannot draft anything into HubSpot. The steps are in <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>.</p>
<p>Through Elaichi, connected tools are never listed one by one, however few there are, so ChatGPT finds each HubSpot tool by searching for it (<a href="/blog/context-window-problem-mcp-tools/">why connected tools sit behind search</a>).</p>
<h2 id="why-does-sending-email-need-a-block-rule-of-its-own">Why does sending email need a block rule of its own?</h2>
<p>Because no other setting stops it. The OAuth scopes are coarse. A send is a write, not a delete, so withholding <code>mcp:destructive</code> leaves it reachable, and withholding the write scope would take drafting away with it. ChatGPT "may ask for confirmation" before a write, in OpenAI's words, but a prompt the client may or may not show is not a control you hold.</p>
<p>Four catalog tools put an email or a message in front of customers:</p>
<ul>
<li><code>create_a_hubspot_email_single_send</code> sends one templated email per call. HubSpot's <a href="https://developers.hubspot.com/docs/api-reference/legacy/marketing/transactional-emails/guide">single-send guide</a> says the API "sends template emails created in the HubSpot email tool". A model asked to email everyone who opened the webinar invite can call it once per contact, which is a bulk send made one call at a time.</li>
<li><code>create_a_hubspot_workflow</code> and <code>update_a_hubspot_workflow_by_id</code> create and edit automation. A workflow's Send email action sends "marketing emails that have been saved for automation" to the contacts it enrolls (<a href="https://knowledge.hubspot.com/workflows/choose-your-workflow-actions">HubSpot knowledge base</a>). A model that can edit a workflow can schedule a send to a whole list.</li>
<li><code>create_a_hubspot_message</code> posts a new message into a HubSpot Conversations thread, which is a live conversation with a customer.</li>
</ul>
<p>Leave all four out of marketing's toolbox, and put them in one block rule on the role marketing members hold as well. A block holds on every path, a toolbox entry included, so the tools stay out even after someone adds one to a toolbox or shares the connection directly. Blocks also always beat allow rules, so the rule survives someone widening the reads next quarter. A block matches the tool's name as well as the operation Elaichi pinned when the rule was saved. Renaming a tool in a forked connector does not get around it.</p>
<h2 id="which-hubspot-deletes-should-marketing-lose">Which HubSpot deletes should marketing lose?</h2>
<p>All of them. The single delete, <code>delete_a_hubspot_contact_by_id</code>, archives one contact. The batch tool, <code>hubspot_contacts_batch_delete</code>, archives contacts "in a single request", so one wrong list of IDs archives every contact on it. The workflow delete, <code>delete_a_hubspot_workflow_by_id</code>, is worse: its catalog description says it "permanently removes the flow and cannot be undone".</p>
<p>Deletes have a second guard. A connected tool whose method is a delete needs the <code>mcp:destructive</code> scope on top of any rule, so a grant without that scope cannot run one. Write the block anyway. A scope belongs to one person's grant, while a rule covers everyone on the role, including the next person you add.</p>
<p>Write the deletes as blocks rather than as a short allowlist of reads. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That is the quickest way to ship a rollout in which nothing works, and <a href="/blog/block-matches-name-allow-matches-operation/">why blocks and allows match differently</a> covers the rest of the rule.</p>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. So a rule aimed at the head of demand generation cannot hand the sends and the deletes back. If she needs one restricted tool, she files an access request and an admin approves it in the console. The grant lifts that one tool for her, and every other block keeps applying.</p>
<h2 id="how-do-you-keep-writes-out-of-the-wrong-hubspot-portal">How do you keep writes out of the wrong HubSpot portal?</h2>
<p>Pin the portal into a toolbox, and share the toolbox instead of the connections. A company with a sandbox portal beside production, or one portal per region, connects HubSpot more than once. A member who holds <code>use</code> on both connections sees each HubSpot tool with a required <code>connection</code> argument, and the model picks its value from the account labels in the tool's schema. That is a guess the model should not be making for a contact update.</p>
<p>Take the guess away. The person who connected the portals leaves both connections unshared. They pin the production portal into a toolbox entry for each tool marketing needs, then share the toolbox with the marketing team at <code>use</code>. Marketing then runs those tools only through the entries, which reach production and nothing else, and cannot open or reshare the connection behind them. Frozen values on an entry lock any other argument. A frozen key is removed from the schema the model is offered. A frozen value is merged over whatever the caller sends, so passing the key anyway changes nothing. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking a tool argument</a> shows the mechanism on a payment tool.</p>
<p>One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. Anyone who also holds <code>use</code> on a portal's connection, directly or through a team share, reaches its tools unfrozen. Do not try to close that path with a block rule, because a block withholds the tool everywhere, the pinned entry included. Close it by not sharing the connection.</p>
<p>Afterward, the audit trail settles where a write went: Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), each recording the portal the call actually reached. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the rest of each entry.</p>
<h2 id="which-role-should-marketing-members-hold">Which role should marketing members hold?</h2>
<p>One role, carrying <code>tool:execute</code>. Every member holds exactly one role, so the marketing role is a complete persona rather than an add-on. The <code>tool:execute</code> permission gates the whole MCP endpoint ahead of every scope. Without it, <code>tools/list</code> comes back empty and a call returns an error naming the missing permission. Guest, Auditor and Billing Admin do not carry it.</p>
<p>Keep <code>connector:create</code> out of the role. A custom connector can dial any destination, which is why Elaichi flags that permission as high trust. A marketer who can write one can route around every HubSpot rule in this post.</p>
<p>A compliance reviewer who only reads the trail needs no marketing role at all. The Auditor role is read-only and free, so oversight costs no license (<a href="/pricing/">pricing</a>).</p>
<h2 id="why-not-use-hubspots-own-mcp-server">Why not use HubSpot's own MCP server?</h2>
<p>If HubSpot is the only app marketing needs in ChatGPT, HubSpot's own server is the simpler choice. HubSpot's remote MCP server is generally available (<a href="https://developers.hubspot.com/changelog/remote-hubspot-mcp-server-is-now-generally-available">HubSpot developer changelog</a>, checked October 2026). The changelog says any MCP-compatible tool "can now read from and write to your CRM through natural conversation, with your existing HubSpot permissions respected throughout". It runs over "a secure, HubSpot-hosted connection authenticated via OAuth 2.1 with PKCE" at <code>https://mcp.hubspot.com</code>, through an MCP auth app the account creates. HubSpot's own permission model decides what each marketer can touch, and there is no second vendor to review. If marketing also needs finance and support data, <a href="/blog/connect-ai-to-crm/">connecting AI to your CRM</a> covers the shared setup.</p>
<p>Elaichi earns its place when HubSpot is one app among several:</p>
<ul>
<li><strong>One address.</strong> ChatGPT, Claude and Cursor reach HubSpot and every other connected app through the same organization endpoint.</li>
<li><strong>One set of rules per role.</strong> The send block and the delete block sit on the marketing role beside its rules for every other app, written once.</li>
<li><strong>Frozen arguments.</strong> On a shared toolbox entry, a pinned value is one the model cannot override, and a short one shows in the tool description.</li>
<li><strong>One audit trail.</strong> Calls to HubSpot and to every other app that reach execution land in one record, each naming the account it reached.</li>
<li><strong>One place to cut access.</strong> In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Removing a marketer ends their access through Elaichi to every connected app on the next call. Their HubSpot user is a separate step, in HubSpot or your identity provider.</li>
</ul>
<p>HubSpot's changelog does not describe rules that reach other apps, which is no criticism: it is HubSpot's server for HubSpot's data.</p>
<h2 id="when-does-marketing-not-need-any-of-this">When does marketing not need any of this?</h2>
<p>When one marketer uses one assistant against one portal, with a HubSpot login that cannot send or delete. HubSpot's own permissions, or its own MCP server, cover that, and a control plane would be overhead. Revisit when a second client, a second portal or an auditor arrives, the triggers set out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway yet</a>.</p>
<p>One limit holds either way. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds instead is the configuration: a model steered by a pasted campaign brief still cannot reach a restricted send or the other portal.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>To check a tool's exact name before you write a rule, the HubSpot connector page lists them all.</p><a href="/connectors/hubspot/" class="cta-button">Open the HubSpot connector</a></aside>
<h2 id="what-order-should-the-rollout-follow">What order should the rollout follow?</h2>
<p>Blocks before invites, so marketing never has a day with more access than you meant.</p>
<ol>
<li>Connect the HubSpot portals once, and leave the connections unshared.</li>
<li>Pin production into a toolbox entry for each tool marketing needs, and share the toolbox with the marketing team at <code>use</code>.</li>
<li>Put marketing members on one role with <code>tool:execute</code> and without <code>connector:create</code>.</li>
<li>Write the send block: <code>create_a_hubspot_email_single_send</code>, <code>create_a_hubspot_message</code>, <code>create_a_hubspot_workflow</code> and <code>update_a_hubspot_workflow_by_id</code>.</li>
<li>Write the delete block: <code>delete_a_hubspot_contact_by_id</code>, <code>hubspot_contacts_batch_delete</code> and <code>delete_a_hubspot_workflow_by_id</code>.</li>
<li>Test with one member. Each restriction edit takes about two minutes to land everywhere, and <a href="/blog/offboarding-when-the-agent-holds-access/">why a removal lands faster</a> explains the other speed.</li>
<li>Have a ChatGPT workspace admin publish the app, then invite the team.</li>
</ol>
<p>The same shape runs the <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Salesforce rollout for a sales team</a>, and the <a href="/blog/category/team-playbooks/">team playbooks</a> apply it to other apps. What the other eleven teams ask for first is on the <a href="/use-cases/">use cases page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can marketing use HubSpot inside ChatGPT without being able to send email?</strong></dt><dd>Yes. In Elaichi, write one block rule on the marketing role naming the tools that send: create_a_hubspot_email_single_send, which sends a templated email per call, create_a_hubspot_message, and the two workflow tools, because a HubSpot workflow can send saved marketing emails to every contact it enrolls. Withholding the mcp:destructive OAuth scope does not cover a send, because a send is a write, not a delete.</dd><dt><strong>Can you stop ChatGPT from deleting HubSpot contacts?</strong></dt><dd>Yes. Block delete_a_hubspot_contact_by_id and hubspot_contacts_batch_delete on the marketing role, and add delete_a_hubspot_workflow_by_id, which the catalog describes as permanent. A block holds on every path, toolbox entries included. Deletes also need the mcp:destructive OAuth scope, so a grant without it cannot run one, but the rule covers everyone on the role at once.</dd><dt><strong>How do you keep ChatGPT writing to the right HubSpot portal?</strong></dt><dd>Share a toolbox instead of the connections. The person who connected the portals leaves both connections unshared, pins production into a toolbox entry for each tool marketing needs, and shares the toolbox with marketing at use. Marketing then reaches production and nothing else. Anyone who also holds use on a portal's connection reaches its tools without the pin, so do not share the connection itself. The audit trail records the portal each call actually reached.</dd><dt><strong>Why not use HubSpot's own MCP server instead?</strong></dt><dd>If HubSpot is the only app marketing needs, HubSpot's remote MCP server is simpler. It is generally available, connects over OAuth 2.1 with PKCE, and respects your existing HubSpot permissions, with no second vendor. Elaichi adds one address for every app and client, the same role rules across apps, frozen arguments on a shared toolbox, and one audit trail across apps. Removing someone in Elaichi also ends their access through it to every connected app on the next call, though their HubSpot user is a separate step.</dd><dt><strong>Which ChatGPT plans can write to HubSpot through an MCP app?</strong></dt><dd>As of October 2026, OpenAI describes full MCP support, write actions included, as a beta on ChatGPT Business, Enterprise and Edu, where an admin creates the app and publishes it to the workspace. Pro users can connect MCP apps with read and fetch permissions only, in developer mode, so a marketer on Pro can read campaigns but cannot draft into HubSpot.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Why blocks match tool names but allows don&apos;t</title>
      <link>https://elaichi.ai/blog/block-matches-name-allow-matches-operation/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/block-matches-name-allow-matches-operation/</guid>
      <description>In Elaichi, blocks match tool names or the operation behind them, while allows match the operation only, so a renamed tool can never widen a role&apos;s reach.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, a block rule stops a call when either the tool's name or the operation behind it matches, and an allow rule counts the operation only. Elaichi looks that operation up in its catalog when the rule is saved. Whoever edits a connector can rename a tool, so a rename must never widen what a role can reach. The name check on blocks is a safety net, because it can only deny more.</aside>
<h2 id="why-do-blocks-match-tool-names-but-allows-do-not">Why do blocks match tool names but allows do not?</h2>
<p>In Elaichi, blocks match tool names or the operation behind them, and allows match the operation only. The split comes down to who controls each one. You control the operation, because Elaichi looks it up in its catalog when you save the rule. Whoever maintains the connector controls the name, and a rename must never widen what a role can reach.</p>
<p>Here is the case the design is built for. You restrict a tool called <code>delete_contact</code> for the Member role. Six weeks later, someone with edit rights on that connector renames it <code>archive_contact</code>. The call underneath has not changed: the same kind of record, the same action, the same records gone. Only the label moved, and your block still holds because the operation still matches.</p>
<p>A few terms first. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A connector is Elaichi's ready-made link to one app, such as HubSpot. Restrictions decide which connectors and which individual tools a target may reach. An operation is what a tool actually does: the kind of record it touches and the action it takes, such as deleting a contact.</p>
<p>The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification's page on tools</a> identifies each tool by a name and describes it with metadata the server supplies. It tells servers to implement proper access controls and leaves the design of those controls to them. So any system that layers role-based access control over MCP has to settle one question. That question is what a rule should match when one action appears under two names at different times. Elaichi's answer is the asymmetry above, and it holds just as well for a permission layer you build yourself.</p>
<h2 id="what-does-elaichi-record-when-you-save-a-rule">What does Elaichi record when you save a rule?</h2>
<p>It records the tool you clicked and the operation behind it, side by side. You write a rule in the terms the console shows: pick a connector, pick a tool, choose allow or block, and choose a target. On save, Elaichi looks the tool up in its catalog and stores the operation with the rule. For <code>delete_contact</code>, that is the delete action on the contacts record type.</p>
<p>The lookup happens once, at save time, rather than each time a call is checked. That timing is deliberate. A rule worked out again on every call would mean whatever the connector says today. Your decision would become a question put to editable documentation. Recording the operation at save time keeps the rule a record of what the administrator meant on the day they wrote it.</p>
<p>Two more facts decide which rules apply to a given call. First, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Second, a member sits under two layers at once: the rules on their role and the rules aimed at them. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A call passes only when both layers admit it. Inside each layer, allow rules add up, block rules add up, and a block always beats an allow. With no rule at all, nothing is restricted.</p>
<h2 id="which-part-of-a-tool-does-each-rule-check">Which part of a tool does each rule check?</h2>
<p>A block checks the name and the operation, and either match is enough. An allow checks the operation and ignores the name. Once Elaichi has gathered the rules that apply to a call, that is the only difference between the two rule types:</p>
<table>
<thead>
<tr>
<th>Rule type</th>
<th>Checks the displayed tool name?</th>
<th>Checks the operation recorded at save time?</th>
<th>With no rule of this type in the layer</th>
<th>Against the other rule type</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Block</strong></td>
<td>Yes</td>
<td>Yes (either match is enough)</td>
<td>Nothing is restricted by this check</td>
<td>Always wins over an allow</td>
</tr>
<tr>
<td><strong>Allow</strong></td>
<td>No</td>
<td>Yes, and only this</td>
<td>The layer allows everything</td>
<td>Loses to any matching block</td>
</tr>
</tbody>
</table>
<p>Three consequences follow:</p>
<ul>
<li>A <strong>block</strong> denies the call if the displayed name matches or if the recorded operation matches.</li>
<li>An <strong>allow</strong> passes the call only if the recorded operation matches. The displayed name plays no part.</li>
<li>Blocks have the last word. A call that passes the allowlist but matches a block is denied.</li>
</ul>
<p>One principle covers all three. Anything a block matches on can only make the system stricter, so a block may lean on an editable string. Anything an allow matches on grants reach, so an allow may not.</p>
<h2 id="why-cant-an-allow-rule-trust-the-tool-name">Why can't an allow rule trust the tool name?</h2>
<p>Because the name belongs to whoever maintains the connector, who is often not the person who wrote the restriction. A tool's displayed name lives in the connector's configuration. Your organization can author connectors from JSON config, and it can fork a public connector and edit the copy. The permission behind that work, <code>connector:create</code>, is flagged high trust in Elaichi, because a custom connector can call any destination you give it.</p>
<p>So a name is a label someone attaches, not a fixed property of an operation. The MCP specification takes a similar line on the hints a tool gives about its own behavior. Clients must treat <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">those tool annotations as untrusted</a> unless they come from a trusted server. In a governance model, a string the governed side can change must never be the thing that grants reach.</p>
<p>Picture the two ways this could fail.</p>
<p>If an allow matched on the name, an editor could give an unwanted operation a name your allowlist already covers. The call would then pass. A documentation edit would widen the allowlist silently, with no rule change and no approval.</p>
<p>If a block matched on the operation only, a rename would not beat it, since the operation is what counts. Matching the name as well adds a second net: the block also stops any tool that carries the name you blocked, whatever sits behind it. Neither check can grant anything. The worst a wrong match on a block can do is deny a call, and an administrator fixes that by adjusting the rule.</p>
<p>That is the whole argument. Governance binds the operation. The name check on blocks is a safety net, and a safety net is only ever allowed to catch.</p>
<h2 id="what-happens-if-an-allow-rule-names-nothing">What happens if an allow rule names nothing?</h2>
<p>It denies everything for that target. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That makes it the strictest rule you can write, not a harmless placeholder.</p>
<p>To record "no restrictions decided yet," save no rule at all, because with no rule the default is allow-all. If a role suddenly reaches nothing, check for an empty allow rule first.</p>
<p>The strictness is the point of an allowlist. NIST SP 800-53 states least privilege in control <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AC-6</a>: allow only the access needed for assigned tasks. The control covers users and the processes acting on their behalf. An AI client calling tools for a member is one of those processes. An allowlist is how you write least privilege down for a role, and it only works if a rename cannot widen it.</p>
<h2 id="where-does-elaichi-check-a-restriction">Where does Elaichi check a restriction?</h2>
<p>Elaichi checks every rule with the same resolver, the code that decides allow or deny. It runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. Of those, four checks decide most cases, and each answers a different question:</p>
<ol>
<li><strong>Browse.</strong> Can this role see that the connector exists in the catalog?</li>
<li><strong>Connect.</strong> Can this role set up a connection to it?</li>
<li><strong>Advertise.</strong> Is this tool in the list an AI client receives?</li>
<li><strong>Execute.</strong> Does the actual call, with its actual arguments, pass the same allow and block logic?</li>
</ol>
<p>The final check runs after every variable in the outbound web address has been filled in.</p>
<p>The advertise check changes what a model can even attempt. Elaichi withholds a restricted tool from the tool list for a member of that role over MCP, and the tool cannot be called. Search names it, flagged restricted, with no schema. The model cannot pick the tool, guess at it or call it.</p>
<p>The execute check covers any call that arrives anyway. Wrapping a call in <code>execute_tool</code> changes nothing. Elaichi unwraps it to the original tool and arguments, and the call meets every check a direct call would. There is no second path with weaker matching. OWASP's guidance on <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">excessive agency in LLM applications</a> names this principle complete mediation. Authorization is enforced in the downstream system on every request, rather than left to the model to decide.</p>
<p>A saved change does not land at once. A restriction change first waits out a 60-second cache, then spreads across the edge network. It takes effect within about two minutes on MCP, the console and the REST API alike. Grant revocation is faster, and so are removing and suspending a member. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, so the next call is refused.</p>
<h2 id="do-restrictions-apply-to-forked-connectors">Do restrictions apply to forked connectors?</h2>
<p>Blocks do. A block on a public connector also catches forks of it. A forked connector's identity includes its declared lineage, the chain of parents it says it came from, followed to the root. That inheritance applies to blocks only. It fails closed if the chain is cut off or loops, so a lineage that cannot be followed counts as restricted. An administrator does not need to track down every fork to keep a block in force.</p>
<p>Elaichi does not treat the host a connector calls as part of its identity. Two connectors that call the same domain are not the same connector, and a connector that changes host is not a new one. Identity comes from the catalog entry and its declared parents, not from where the network traffic ends up.</p>
<h2 id="what-do-frozen-parameters-add-to-restrictions">What do frozen parameters add to restrictions?</h2>
<p>Restrictions decide whether a tool is reachable at all. Frozen parameters decide what a reachable tool may be called with. Each one fixes an argument's value, so an allowed tool can only run with that value.</p>
<p>A frozen parameter is set on one toolbox entry, and a toolbox is a named set of tools shared with people. Elaichi leaves a frozen field out of the schema the model receives, so the model is never asked to fill it. A short frozen value shows in the tool description, but the model cannot change it. At execution, Elaichi writes the frozen value over whatever the caller sent, so sending the field anyway changes nothing. Entry defaults lose to caller arguments, and both lose to frozen values.</p>
<p>Freezing a workspace ID narrows what an allowed tool can touch. It does not replace a block on a tool nobody should reach. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking the payee on a payment tool</a> walks through the mechanic in full.</p>
<h2 id="how-do-you-write-a-rule-that-survives-a-rename">How do you write a rule that survives a rename?</h2>
<p>Write blocks against the destructive operations you mean, at the role level, and keep them. Use allows sparingly, because the first one you save switches that target to deny by default. Re-check an allowlist after a connector is forked or pulls upstream changes. Tools that arrive upstream are new operations, and the allowlist keeps them out until somebody adds them.</p>
<p>Then confirm the rule did what you expected. A call a restriction refuses before execution writes no row, so a block shows up as a missing tool and no entry, not as a log line. The audit log holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). It records the one path argument that names the object, as the target id, and nothing else about the arguments. A call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. Claude, ChatGPT and Cursor are marked verified. So "which client made this call" is answered from the record, not from a user agent string.</p>
<h2 id="when-can-you-skip-rules-like-these">When can you skip rules like these?</h2>
<p>You can skip all of this if your organization has one connected account, three people, and everyone is equally trusted with it. With no rules, the default is allow-all. That is a defensible position while the blast radius is one workspace you can inspect by hand.</p>
<p>The difference between name and operation starts to matter in three cases:</p>
<ul>
<li>Connectors are forked or written in-house.</li>
<li>The people who edit a connector are not the people who set policy.</li>
<li>Roles differ enough that one of them should not see a tool exists.</li>
</ul>
<p>It also matters once access stops being arranged person by person. <a href="/blog/zapier-mcp-alternative/">Replacing per-member MCP servers with one endpoint</a> covers that shift.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>For a security review, the security page covers how credentials are held, how access is shared, and how each action is attributed to a person.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="where-do-block-and-allow-rules-sit-in-the-rest-of-elaichi">Where do block and allow rules sit in the rest of Elaichi?</h2>
<p>Inside restrictions, which sit on top of roles, behind one MCP endpoint. For when to restrict one tool rather than a whole connector, see <a href="/blog/per-tool-vs-per-app-restrictions/">six cases for per-tool rules</a>. The <a href="/product/">product overview</a> shows how roles, restrictions and the endpoint fit together, and the <a href="/security/">security page</a> covers residency, audit tenancy and key management. Elaichi has 600+ connectors, each with its own page, such as <a href="/connectors/airtable/">Airtable</a> or <a href="/connectors/asana/">Asana</a>, and <a href="/use-cases/">use cases by team</a> show what each group typically needs to reach.</p>
<h2>FAQ</h2><dl><dt><strong>Why does a block rule in Elaichi also match the tool name?</strong></dt><dd>Because a block can only deny, so a second way to match costs nothing in safety. A block in Elaichi catches a call when the tool's displayed name matches or when the operation Elaichi recorded at save time matches. If someone renames a restricted tool, the operation still matches. If a tool carries the name you blocked, the name match catches it whatever sits behind it. The worst result of a wrong match is a tool withheld when it should not be, which an administrator fixes by adjusting the rule.</dd><dt><strong>Why can't an allow rule in Elaichi match on the tool name?</strong></dt><dd>Because an allow rule grants reach, and reach must never depend on a string the governed side can change. A tool's displayed name lives in the connector's configuration, and whoever edits the connector can rename it. If allows matched names, giving an unwanted operation a name already on the allowlist would let it through with no rule change and no approval. So an allow matches only the operation Elaichi recorded from its catalog when the rule was saved.</dd><dt><strong>What happens if I save an allow rule that names no tools?</strong></dt><dd>It denies everything for that target. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. To record that no restrictions are decided yet, save no rule at all. With no rule, the default is allow-all.</dd><dt><strong>How quickly does a restriction change take effect in Elaichi?</strong></dt><dd>Within about two minutes. Restrictions and role membership are read through a 60-second cache and then spread across the edge network, on the MCP endpoint, the console and the REST API alike. Only OAuth grant revocation, member removal and suspension take effect on the next call, because Elaichi re-reads the grant on every call.</dd><dt><strong>Can one rule cover everybody at once?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. You write policy against roles and against individual users. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Connect Elaichi to ChatGPT</title>
      <link>https://elaichi.ai/blog/connect-elaichi-to-chatgpt/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/connect-elaichi-to-chatgpt/</guid>
      <description>To connect Elaichi to ChatGPT, a workspace admin adds one MCP endpoint as a custom app and each person signs in with OAuth. No API key, no per-user URL.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to ChatGPT, a workspace admin on ChatGPT Business, Enterprise or Edu creates a custom app from Elaichi's one organization-wide MCP endpoint and publishes it to the workspace. Each person then signs in to it with OAuth, so there is no API key to paste and no per-user URL. Full MCP with write actions is a beta on those plans, and Pro users get read and fetch only. After sign-in, the member's role, the resources shared with them and any restrictions decide which tools ChatGPT can call.</aside>
<h2 id="how-do-you-connect-elaichi-to-chatgpt">How do you connect Elaichi to ChatGPT?</h2>
<p>To connect Elaichi to ChatGPT, a workspace admin creates one custom app from Elaichi's MCP endpoint and publishes it, and each person signs in to it with OAuth. There is no API key to paste, no per-user URL and no server to run. The rest of this guide covers the plan you need, the clicks, what people see, and the rules that decide what ChatGPT can do.</p>
<p>Your support team already lives in ChatGPT. Someone asks for Zendesk inside it, and the shortest path is a personal API token pasted into a custom setup. Do that ten times and you have ten credentials nobody can revoke centrally. One endpoint behind OAuth replaces all ten.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps, and its <a href="https://modelcontextprotocol.io/specification/2025-06-18">specification</a> is public. Elaichi serves every connected SaaS account through one organization-wide endpoint, <code>POST /mcp</code>: standard MCP over Streamable HTTP, behind OAuth.</p>
<h2 id="which-chatgpt-plans-can-use-a-custom-mcp-app">Which ChatGPT plans can use a custom MCP app?</h2>
<p>Business, Enterprise and Edu, with write actions; Pro, for reads only. OpenAI's help center says full MCP support, write actions included, is rolling out in beta to Business, Enterprise and Edu, and that Pro users can connect MCP servers with read and fetch permissions in developer mode (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI help center</a>, checked October 2026).</p>
<p>It is a beta, and the same page warns that "Functionality, UI, and permissions may change". The menu paths below are as of October 2026. If a label has moved, the value you enter has not.</p>
<h2 id="how-does-an-admin-add-the-elaichi-endpoint">How does an admin add the Elaichi endpoint?</h2>
<p>As one app, created once and published to the workspace. On Business, OpenAI's page says "Only Admins can use developer mode". Enterprise and Edu admins can grant it to chosen members through role-based access control.</p>
<ol>
<li>Open <strong>Workspace settings</strong>, then <strong>Apps</strong>, then <strong>Create</strong>.</li>
<li>Enter your organization's Elaichi MCP endpoint, and choose OAuth as the authentication.</li>
<li>Click <strong>Scan Tools</strong>, then complete the OAuth prompt so the scan can finish.</li>
<li>Click <strong>Create</strong>. The app is saved as a draft in Workspace settings.</li>
<li>Publish it. Published apps appear "in users' Apps settings in ChatGPT with the label custom".</li>
</ol>
<p>One detail costs people a second attempt. OpenAI's page says that "For Business plans, apps cannot be updated after publishing at launch." Check the name and settings before you press Publish.</p>
<p>The address is the same for every member. There is no MCP server to create, list or revoke per person, and nothing about the URL is a secret. What varies is the grant behind each person's sign-in.</p>
<p>The same address works for Claude and Cursor. An admin adds it once where each client allows, and each member connects it there. <a href="/blog/elaichi-vs-native-ai-connectors/">Claude and ChatGPT connectors vs one MCP endpoint</a> compares that model with each client's own connectors.</p>
<h2 id="what-does-a-person-see-the-first-time-they-sign-in">What does a person see the first time they sign in?</h2>
<p>A sign-in screen, then a short list of tools. ChatGPT opens Elaichi's OAuth flow, the person authenticates, and ChatGPT holds a grant scoped to that person. <a href="https://www.rfc-editor.org/rfc/rfc6749">OAuth 2.0</a> is the standard behind that handshake: the client receives a grant, never the password.</p>
<p>How people authenticate depends on what the organization set up. Elaichi supports Google, GitHub and Microsoft sign-in, email codes, TOTP multi-factor codes with recovery codes, and passkeys. Enterprise SAML and OIDC single sign-on are built in, with SCIM v2 provisioning and group-to-role mapping beside them.</p>
<p>What appears after sign-in is narrower than most people expect, by design. A member sees only what they own or what was explicitly shared with them. No org-level permission silently widens that list, org owners and admins included.</p>
<p>If the person's role lacks the <code>tool:execute</code> permission, the list comes back empty and any call returns an error naming the missing permission. Guest, Auditor and Billing Admin are the roles without it. That is the right outcome for a compliance reviewer who signs in out of curiosity.</p>
<h2 id="where-do-the-app-accounts-come-from">Where do the app accounts come from?</h2>
<p>The person connects them, inside ChatGPT or in the Elaichi console, from a catalog of 600+ connectors. Elaichi authors most of those connectors and serves them from its own infrastructure, and the rest are vendors' own MCP servers it governs, so your team runs no MCP server per app.</p>
<p>The connect step returns a one-time connect URL that carries no token, which is why it is safe to hand back through ChatGPT. Credentials never live in Elaichi itself. A separate credential service holds each account's secrets, encrypted at rest, and owns token refresh. A failed refresh marks the connection <code>needs_reauth</code>, so it shows up as a connection to fix rather than a silent failure.</p>
<p>An organization can bring its own OAuth app per connector. That right is gated on <code>connector:manage</code>, not <code>connection:manage</code>, so everyone who can delete a connection does not also gain the power to repoint the organization's OAuth app. When the catalog lacks an app, custom connectors are authored from JSON config.</p>
<h2 id="why-does-chatgpt-show-only-searchtools-and-executetool">Why does ChatGPT show only search_tools and execute_tool?</h2>
<p>Because in Elaichi, connected tools are never listed one by one, however few there are. ChatGPT looks a tool up with <code>search_tools</code> and calls it with <code>execute_tool</code>, so those two in the tool list are the expected view, not a broken connection.</p>
<p>A tool withheld by a restriction is left out of the tool list and cannot be called. Search names it, flagged restricted, with no schema. <code>execute_tool</code> is only a naming indirection: it unwraps to the same tool name and arguments and passes the same checks. Search is lexical, with a floor that keeps a query about one app from returning a tool from another, as <a href="/blog/search-tools-ranking-floor-idf/">how MCP tool search picks one tool from hundreds</a> explains.</p>
<h2 id="what-decides-which-tools-a-persons-chatgpt-can-call">What decides which tools a person's ChatGPT can call?</h2>
<p>Three layers, checked against the same resolver on every call. Keep them apart, because they fail differently.</p>
<ul>
<li><strong>Roles.</strong> 58 permissions are grouped into roles, with exactly one role per member. <code>tool:execute</code> gates the whole endpoint.</li>
<li><strong>Sharing.</strong> A grant of view, use or edit on a connection or toolbox makes it visible to somebody who does not own it.</li>
<li><strong>Restrictions.</strong> These decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</li>
</ul>
<p>Two details catch people. First, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Second, a block matches a tool's name or its operation, while an allow matches the operation only. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks match tool names but allows don't</a> explains the asymmetry.</p>
<p>Frozen parameters sit underneath. A frozen argument is removed from the schema ChatGPT is shown, and its value is merged over whatever the model sends, so the model cannot change it. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A role or restriction change takes about two minutes to apply.</p>
<h2 id="will-chatgpt-ask-before-it-writes-something">Will ChatGPT ask before it writes something?</h2>
<p>Sometimes, and you should not rely on it alone. OpenAI's page says ChatGPT may ask for confirmation before a write or modify action, depending on the app's permissions and the action's context.</p>
<p>The guarantee lives on Elaichi's side. A tool a restriction withholds cannot be called at all, however the prompt is phrased. OAuth scopes add a ceiling: reads need <code>mcp:read</code>, writes <code>mcp:write</code>, and deletes <code>mcp:destructive</code>. A tool classified forbidden is reachable under no scope.</p>
<h2 id="how-do-you-check-what-chatgpt-did">How do you check what ChatGPT did?</h2>
<p>In the audit trail. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account the call actually reached, and the OAuth client it came through, with ChatGPT marked verified. The call is recorded under the person who signed in. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the fields in full.</p>
<p>A read-only Auditor seat is free, so a reviewer can read the trail without consuming a license. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon.</p>
<h2 id="what-happens-to-chatgpt-access-when-somebody-leaves">What happens to ChatGPT access when somebody leaves?</h2>
<p>It ends on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next request from that person's ChatGPT session fails. Suspension works the same way.</p>
<p>The removal runs a preflight first, listing every connection the departing member owns, private and shared alike. A shared connection can be transferred to one active member. A private connection that a shared toolbox relies on blocks the removal until it is transferred to one member or deleted. A private connection that nothing else depends on cannot be transferred and is deleted with the member. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding AI access, contractors included</a> walks through the order.</p>
<h2 id="what-does-this-setup-not-protect-against">What does this setup not protect against?</h2>
<p>Prompt injection on the endpoint. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. By the time a call reaches the endpoint, the model has already decided what to call.</p>
<p>So do not present this internally as an anti-injection control. What it does give you is containment: a manipulated model still cannot call a tool its user was never granted, and whatever it did call is attributable afterwards. Enforcement runs against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<h2 id="when-should-you-not-connect-chatgpt-to-elaichi-yet">When should you not connect ChatGPT to Elaichi yet?</h2>
<p>When four people use ChatGPT against two apps they each own personally. That is more machinery than the problem deserves. Turn up the apps' own admin controls, and revisit when the first contractor leaves or a team asks for an account that is not theirs. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need an MCP gateway yet</a> lists the signals.</p>
<p>Cost is the other honest constraint. Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows the price for your region. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<p>If the sign-in fails, <a href="/blog/mcp-oauth-errors/">the OAuth error guide</a> says which step broke, and if a tool you expect is missing, <a href="/blog/mcp-tools-not-showing/">the missing-tools checklist</a> walks the checks in order. When you are ready, choose which connectors to turn on and which team goes first. Browse the <a href="/connectors/">connector catalog</a> or the <a href="/use-cases/">team pages</a>, and for one team's rollout, read <a href="/blog/sales-team-chatgpt-salesforce-accounts/">each rep's own Salesforce access, in ChatGPT</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Do I need an API key to connect Elaichi to ChatGPT?</strong></dt><dd>No. Elaichi serves one organization-wide MCP endpoint behind OAuth, so each person signs in instead of pasting a key. Nothing durable and copyable ends up inside ChatGPT, and there is no second API to wire up.</dd><dt><strong>Which ChatGPT plans can use Elaichi?</strong></dt><dd>OpenAI's help center says full MCP support, including write actions, is rolling out in beta to ChatGPT Business, Enterprise and Edu, where an admin creates and publishes the app. Pro users can connect MCP servers with read and fetch permissions in developer mode. Check OpenAI's page for other plans, since the beta is still changing.</dd><dt><strong>Can the same Elaichi endpoint serve Claude and Cursor too?</strong></dt><dd>Yes. It is one address for the whole organization. An admin adds it once where each client allows, and each member then connects it in that client and signs in with their own grant. A fourth MCP client is the same work.</dd><dt><strong>How quickly does a restriction change affect what ChatGPT can call?</strong></dt><dd>It takes about two minutes, because restrictions and role membership resolve through a 60-second cache plus edge propagation. Grant revocation, member removal and suspension are faster: each is effective on the next call.</dd><dt><strong>Does connecting ChatGPT through Elaichi stop prompt injection?</strong></dt><dd>No. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. It cannot apply there, because an MCP server never sees a user prompt. What does apply on the endpoint is a permission check per operation, the forbidden classification, output redaction, OAuth scope limits and audit logging of each call that reaches execution.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>Each rep&apos;s own Salesforce access, in ChatGPT</title>
      <link>https://elaichi.ai/blog/sales-team-chatgpt-salesforce-accounts/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/sales-team-chatgpt-salesforce-accounts/</guid>
      <description>Salesforce access in ChatGPT works per rep: each call runs on the rep&apos;s own connection, so Salesforce&apos;s sharing rules decide which accounts they see.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Give each rep their own Salesforce access in ChatGPT: in Elaichi, each rep connects Salesforce under their own login, so every call runs on that connection and Salesforce's own sharing rules decide which accounts the model can read. Elaichi then blocks the tools a sales team should not have, such as the record deletes, the account merge and the catch-all tools that can reassign any record. For an Enterprise Edition org that needs only Salesforce in ChatGPT, Salesforce's own hosted MCP server is the simpler choice.</aside>
<h2 id="how-should-salesforce-access-in-chatgpt-work-for-a-sales-team">How should Salesforce access in ChatGPT work for a sales team?</h2>
<p>Per rep. Each rep connects Salesforce under their own login, so every call the model makes runs on that rep's connection. Salesforce's own sharing rules then decide which accounts it can read. Elaichi takes away the tools a sales team should not have, such as the record deletes, the account merge, and the catch-all tools that can reassign any record.</p>
<p>The failure this prevents is easy to picture. A rep opens ChatGPT and asks it to tidy the close dates on every deal slipping this quarter. The model finds a tool that updates one opportunity. It also finds <code>create_a_salesforce_composite</code>, which runs "a series of Salesforce REST API requests in a single POST call", and <code>salesforce_accounts_batch_delete</code>, which deletes many accounts in one request. Nothing in the prompt asked for either. The question for IT is what the endpoint would have allowed if the model had reached for one.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves Salesforce from a 600+ catalog through one organization endpoint. <a href="/connectors/salesforce/">The Salesforce connector page</a> lists every Salesforce tool, and <a href="/connectors/category/crm/">the CRM connectors</a> sit beside it. Any AI write to a CRM rests on three separate questions, and each fails in its own way:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Who decides it</th>
<th>In a sales rollout</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Reach</strong>: which records the model can read</td>
<td>Salesforce, through the rep's own connection</td>
<td>The sharing rules and permissions your Salesforce admin already set</td>
</tr>
<tr>
<td><strong>Operation</strong>: which tools the rep's ChatGPT is offered</td>
<td>Elaichi, with block rules on the sales role</td>
<td>Deletes, merges, catch-alls and admin tools never reach the model</td>
</tr>
<tr>
<td><strong>Argument</strong>: which values a kept tool may take</td>
<td>Elaichi frozen arguments, on a shared toolbox</td>
<td>Not the right control here, because each rep reaches their own connection unfrozen</td>
</tr>
</tbody>
</table>
<h2 id="how-do-you-make-sure-a-rep-sees-only-their-own-salesforce-accounts">How do you make sure a rep sees only their own Salesforce accounts?</h2>
<p>Have each rep connect Salesforce under their own login. The rows the model can read are then the rows that Salesforce user can read, filtered by the sharing rules and permissions your Salesforce admin already set.</p>
<p>Be clear about the boundary inside your company. Elaichi's grants decide who can invoke a connection. A member sees what they own and what was explicitly shared with them, and no organization-level permission widens that list, owners and admins included. Elaichi does not filter Salesforce records by owner. Salesforce does. Mixing the two up is the difference between a control you can defend in an audit and one you only assumed existed.</p>
<p>When a sales engineer needs an account executive's reach, share the connection rather than the credential. Sharing grants <code>use</code> on the connection, and the credential never moves. A separate credential service holds per-account secrets, encrypted at rest. Reading back a connection's configuration returns <code>secret_paths</code>, the list of encrypted fields, with none of their values. Calls through the shared connection run as the executive in Salesforce, so share it with the one person who needs that reach, not with the team.</p>
<h2 id="which-salesforce-tools-should-a-sales-team-not-have">Which Salesforce tools should a sales team not have?</h2>
<p>The deletes, the merge, the catch-alls and the admin tools. Write them as block rules on the sales role:</p>
<table>
<thead>
<tr>
<th>Kind</th>
<th>Catalog tools</th>
<th>Why a rep's ChatGPT should not have it</th>
</tr>
</thead>
<tbody>
<tr>
<td>Deletes</td>
<td><code>delete_a_salesforce_account_by_id</code>, <code>delete_a_salesforce_opportunity_by_id</code>, <code>salesforce_accounts_batch_delete</code>, <code>delete_a_salesforce_record_by_id</code></td>
<td>The batch tool deletes many accounts in one request, and the record tool deletes any object by name</td>
</tr>
<tr>
<td>Account merge</td>
<td><code>salesforce_accounts_merge</code></td>
<td>It sends a raw SOAP envelope, and a merge folds duplicate accounts into one</td>
</tr>
<tr>
<td>Catch-alls</td>
<td><code>create_a_salesforce_composite</code>, <code>update_a_salesforce_record_by_id</code></td>
<td>One runs a series of REST requests in a single call, and the other updates any object by name, owner field included</td>
</tr>
<tr>
<td>Admin</td>
<td><code>create_a_salesforce_permission_set_assignment</code>, <code>update_a_salesforce_user_by_id</code></td>
<td>Assigning permission sets and editing users is an admin's job</td>
</tr>
</tbody>
</table>
<p>What reps keep is most of the catalog. Reads such as <code>list_all_salesforce_opportunities</code> and <code>get_single_salesforce_account_by_id</code> stay, and so does the SOQL tool, <code>list_all_salesforce_query</code>, whose catalog description says it runs a query "to retrieve matching records". Activity writes stay too: <code>create_a_salesforce_task</code>, <code>create_a_salesforce_event</code> and <code>create_a_salesforce_note</code> log work without touching anyone's pipeline. The opportunity update stays for close dates and stages.</p>
<p>A rep's own Salesforce permissions may already refuse most of the restricted tools. Block them anyway. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. The block also holds on the day a rep's Salesforce permissions turn out wider than anyone meant.</p>
<p>Blocks combine with other blocks and always beat allow rules, so adding one never widens anything. A block matches the tool's name or the operation Elaichi pinned when the rule was saved, so a renamed tool in a forked connector is still caught. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks and allows match differently</a> has the reasoning. Write blocks rather than a short allowlist, too. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A one-off exception for a sales manager is not a user rule. The manager files an access request, and an admin with <code>member:manage</code> approves it in the console. Approval lifts exactly the approved tool out of that manager's role rules, and every other role block keeps applying.</p>
<h2 id="can-elaichi-stop-chatgpt-from-reassigning-a-reps-accounts">Can Elaichi stop ChatGPT from reassigning a rep's accounts?</h2>
<p>With a block rule, yes. With a freeze, no. No catalog tool is called reassign. In Salesforce the owner is a field on the record, so any update tool that writes the record can write the owner. Elaichi decides per tool, not per field, so the way to take reassignment away is to block the tools that can do it.</p>
<p>Start with the catch-alls, <code>create_a_salesforce_composite</code> and <code>update_a_salesforce_record_by_id</code>, which can reassign any object. If reps never edit account records from ChatGPT, block <code>update_a_salesforce_account_by_id</code> as well, and account reassignment is off the table. Keep <code>update_a_salesforce_opportunity_by_id</code>, which reps need for close dates and stages. It can still write an opportunity's owner. There, Salesforce's own rules on who may change a record's owner decide (<a href="https://help.salesforce.com/s/articleView?id=xcloud.account_owner.htm&#x26;type=5">Salesforce Help</a>), because the call runs as the rep.</p>
<p>A freeze is the wrong tool when each person brings their own connection. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A rep reaches their own Salesforce connection directly, under "All my tools", where every connection a member holds <code>use</code> on appears unfrozen. A frozen owner field would also set the owner on every call through its entry rather than protect it. Freezes suit a connection one owner pins into a toolbox for a team, and <a href="/blog/frozen-parameters-wire-transfer-receiver/">locking a tool argument</a> shows that pattern.</p>
<h2 id="why-not-use-salesforces-own-hosted-mcp-server">Why not use Salesforce's own hosted MCP server?</h2>
<p>For an Enterprise Edition org or above that needs only Salesforce in ChatGPT, Salesforce's own server is the better choice. Salesforce made its hosted MCP servers generally available in April 2026, "for every Enterprise Edition org and above" (<a href="https://developer.salesforce.com/blogs/2026/04/salesforce-hosted-mcp-servers-are-now-generally-available">Salesforce Developers blog</a>, checked October 2026). Existing permissions "automatically apply", the post says, naming CRUD, FLS and sharing rules. "Every transaction runs as the authenticated user", and "OAuth and PKCE control access". When the agent updates a record, "that person's name appears in the audit trail". Prebuilt standard servers come with it, plus custom servers for flows and Apex. That is the same per-rep model, delivered by Salesforce itself with no second vendor.</p>
<p>Elaichi adds what reaches past Salesforce:</p>
<ul>
<li><strong>One address across several apps.</strong> Reps reach Salesforce and every other connected app through one organization endpoint, in ChatGPT, Claude and Cursor alike.</li>
<li><strong>Restrictions written once per role.</strong> The sales role's blocks cover Salesforce and every other app the role reaches, in one rule set.</li>
<li><strong>Frozen arguments.</strong> On a toolbox an owner shares, a pinned value is one the model cannot change.</li>
<li><strong>One audit trail across apps.</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), whichever app the call went to.</li>
<li><strong>One place to cut access.</strong> In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. When a rep is removed, Elaichi refuses their next call to any connected app. Their Salesforce user stays until you deactivate it in Salesforce or through your identity provider.</li>
</ul>
<p>Salesforce's post does not describe rules that span other vendors' apps, nor does it need to: it serves Salesforce's data.</p>
<h2 id="what-does-chatgpt-need-before-reps-can-update-salesforce">What does ChatGPT need before reps can update Salesforce?</h2>
<p>A plan that allows writes, and an admin who publishes the app. OpenAI says full MCP support, "including modify/write actions, is rolling out in beta to ChatGPT Business, Enterprise, and Edu plans" (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI help center</a>, checked October 2026). Only admins and owners publish an app there, and "Pro users can connect MCPs with read/fetch permissions in developer mode". A rep on Pro can read pipeline but cannot update a close date through it. <a href="/blog/connect-elaichi-to-chatgpt/">Connecting Elaichi to ChatGPT</a> walks through the setup.</p>
<p>For a write, the same page says ChatGPT "may ask for confirmation based on app permissions and the action's context". Treat that as a courtesy to the rep, not a control. Whether a prompt appears is ChatGPT's decision, while a block rule holds on every call whatever the client shows.</p>
<p>Two gates sit above the restrictions. The <code>tool:execute</code> permission gates the whole endpoint, and Guest, Auditor and Billing Admin lack it, so those roles cannot call tools at all. OAuth scopes work separately: a connected tool whose method is a delete needs <code>mcp:destructive</code> whatever the rules say, and a tool classified <code>forbidden</code> is reachable under no scope. Through Elaichi, connected tools are never listed one by one, however few there are, so ChatGPT finds a Salesforce tool by searching for it (<a href="/blog/context-window-problem-mcp-tools/">why the tool list stays short</a>).</p>
<p>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds instead is the block list: a hostile instruction in a Salesforce note cannot steer the model into a tool it cannot call.</p>
<h2 id="how-do-you-prove-the-restrictions-work">How do you prove the restrictions work?</h2>
<p>Test them once as a rep, then read the trail every month. A restriction nobody has tested is a belief, not a control.</p>
<p>Start with a search. Signed in as a test member of the sales role, ask ChatGPT for a restricted tool by name, such as <code>salesforce_accounts_batch_delete</code>. Search should name it only as restricted, with no schema. The tool is withheld from the tool list, so the model cannot call it.</p>
<p>Then read the trail each month. Filter it by actor for each rep, or by free text on the Salesforce connection's label, over the last 30 days. Read the entries on the <code>mcp</code> surface. ChatGPT's calls are recorded under the rep who signed in, with ChatGPT named as the client and marked verified. Each entry logs the one path argument that names the object, as the target id, and nothing else about the arguments, so the query shows which object an update acted on, not what was written to it. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the rest of each entry.</p>
<p>Read the result two ways:</p>
<ul>
<li><strong>A refused call to a restricted tool</strong> is rare in the trail. It appears only when a restriction changed after the tool was listed. Keep the rule, and treat the entry as evidence the risk was real.</li>
<li><strong>No such entries in a month</strong> is the normal case. A call a restriction refuses before execution writes no row. Read the writes instead, and check that each landed in the account you expected.</li>
</ul>
<p>Give the reviewer who runs the query an Auditor seat. It is read-only, cannot call tools and is not billable, so oversight costs no license. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon.</p>
<h2 id="what-happens-to-a-reps-access-when-they-leave">What happens to a rep's access when they leave?</h2>
<p>It ends with their membership. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The rep's next call through Elaichi is refused. Revoking a share or disconnecting an account also lands on the next call. Their Salesforce user is a separate step, in Salesforce or your identity provider.</p>
<p>A SCIM deprovision suspends the rep and never removes them. Suspension revokes every live grant, and removal stays a separate step an admin takes in Elaichi. Removal runs a preflight that lists every Salesforce connection the rep owns, private and shared alike. A private connection that a shared toolbox depends on blocks the removal until an admin transfers it to a member. A private connection that nothing beyond the rep depends on cannot be transferred and is deleted with them. A shared connection can go to another active member, never to the admin running the removal, and a transfer leaves every grant on it as it was. It is deleted only if the admin asks for that.</p>
<p>A new block is slower than any of these: it takes about two minutes to reach every surface. <a href="/blog/offboarding-when-the-agent-holds-access/">The two speeds of an access change</a> explains why, and gives the order to follow on a rep's last day.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Every Salesforce tool a rule can name is on the Salesforce connector page, along with each client's setup.</p><a href="/connectors/salesforce/" class="cta-button">Browse the Salesforce tools</a></aside>
<h2 id="when-does-a-sales-team-not-need-any-of-this">When does a sales team not need any of this?</h2>
<p>When Salesforce already says no. If your reps hold a read-only Salesforce profile and no write permission exists for them in Salesforce itself, a restriction layer on top adds paperwork without adding safety. Fix the Salesforce profile instead, since that is the real point of enforcement. If one person is trying Salesforce in Cursor on their own account, that is a conversation with that person, not a case for a control plane. And if Salesforce is the only app in question on an Enterprise Edition org, its own hosted server covers the per-rep model.</p>
<p>Governance earns its cost at a specific point. More than one AI client reaches more than one app, and nobody can say from memory where a given write landed. It usually shows up as an audit question. Someone asks what the assistant changed last Tuesday, and the honest answer is that nobody can reconstruct it.</p>
<p>Sales is one of twelve teams on the <a href="/use-cases/">use cases page</a>, and the <a href="/blog/marketing-team-chatgpt-hubspot-campaigns/">HubSpot playbook for marketing</a> runs the same shape on the other CRM. For the wider setup across a CRM and the apps around it, see <a href="/blog/connect-ai-to-crm/">connecting AI to your CRM</a>. <a href="/pricing/">Pricing</a> has the current price for your region, and every workspace starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. The <a href="/security/">security overview</a> covers data residency and the offboarding preflight.</p>
<h2>FAQ</h2><dl><dt><strong>Can a rep using Salesforce in ChatGPT see only their own accounts?</strong></dt><dd>Yes, if each rep connects Salesforce under their own login. Every call then runs on that rep's connection, and Salesforce's own sharing rules and permissions decide which records the model can read. Elaichi decides who can invoke a connection: a member sees only the connections they own or that were explicitly shared with them, and no organization-level permission widens that list.</dd><dt><strong>How do you stop ChatGPT from deleting Salesforce records?</strong></dt><dd>Write block rules on the sales role for delete_a_salesforce_account_by_id, delete_a_salesforce_opportunity_by_id, salesforce_accounts_batch_delete and delete_a_salesforce_record_by_id, plus the account merge and the catch-all create_a_salesforce_composite. Blocks always beat allows, and a restricted tool is withheld from the tool list and cannot be called. Deletes also need the mcp:destructive OAuth scope.</dd><dt><strong>Can a frozen owner field stop ChatGPT reassigning Salesforce accounts?</strong></dt><dd>No. A frozen value applies only to calls made through the toolbox entry that carries it, and each rep reaches their own Salesforce connection directly, without one. A frozen owner would also set the owner on every call through the entry rather than protect it. Block the tools that can reassign instead: the catch-alls, and update_a_salesforce_account_by_id if reps never edit accounts from ChatGPT.</dd><dt><strong>Why not use Salesforce's own hosted MCP server?</strong></dt><dd>For an Enterprise Edition org or above that needs only Salesforce in ChatGPT, Salesforce's hosted MCP server is the better choice. It is generally available, applies existing CRUD, field-level security and sharing rules, and runs every transaction as the authenticated user. Elaichi adds one address across several apps, restrictions written once per role across apps, frozen arguments and one audit trail across apps. A single removal in Elaichi also stops the person's calls through it to any connected app, though their Salesforce user is deactivated separately.</dd><dt><strong>Which ChatGPT plans let reps update Salesforce through an MCP app?</strong></dt><dd>OpenAI's help center, read in October 2026, puts full MCP with write actions in beta on ChatGPT Business, Enterprise and Edu. An admin creates the app there and publishes it. Pro users get read and fetch only, in developer mode, so a rep on Pro can read pipeline but cannot update it.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>How MCP tool search picks one tool from hundreds</title>
      <link>https://elaichi.ai/blog/search-tools-ranking-floor-idf/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/search-tools-ranking-floor-idf/</guid>
      <description>MCP tool search in Elaichi scores tools by matching words, then returns nothing unless a tool covers at least half the query, with rare words weighted most.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, connected tools are never listed one by one, however few there are, so MCP tool search decides what the model can call. Search scores each connected tool on word matches against its name, description and app label, then refuses any tool that covers less than half of the query, with rare words weighted more than common ones. That turns a confidently wrong result into an empty one. Elaichi chose word matching plus a floor relative to the query, because embedding similarity is weakest at telling two apps' list tools apart and a fixed score cutoff does not hold across queries of different lengths.</aside>
<h2 id="how-does-mcp-tool-search-work-in-elaichi">How does MCP tool search work in Elaichi?</h2>
<p>MCP tool search in Elaichi picks a tool in two steps. First it scores every connected tool the caller can reach by matching the words of the query against the tool's name, its description and its app's label. Then it refuses any tool that covers less than half of what the query asked for, counting rare words for more than common ones. That second step is the relevance floor. It is why a search for one app's tool comes back empty instead of returning a confident match from another app.</p>
<p>Search carries this much weight because it is the only way in. In Elaichi, connected tools are never listed one by one, however few there are. The model sends a query to <code>search_tools</code>, reads back a short ranked list and runs its choice through <code>execute_tool</code>. The pool it searches gets large fast. The <a href="/connectors/asana/">Asana</a> and <a href="/connectors/xero/">Xero</a> connector pages each list well over a hundred tools, so a member with a few accounts connected can be choosing among hundreds.</p>
<p>Keep two things apart. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> defines how a client lists a server's tools with <code>tools/list</code>, which may be paginated, and calls one with <code>tools/call</code>. Its tools page defines no search and no ranking. In Elaichi, <code>search_tools</code> and <code>execute_tool</code> are ordinary entries in that list, a choice made in the application layer rather than a protocol feature. Another server could list everything, paginate, or rank differently. Anthropic offers developers a version of the same idea for Claude, a <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">tool search tool</a> that searches a catalog instead of loading every definition up front.</p>
<p>Two things stay fixed around the search. Control-plane operations stay listed individually, and <code>search_tools</code> never returns one, because it ranks only the connected third-party tools. The other fixed point is that <code>execute_tool</code> is purely a naming indirection. It resolves to the same tool name and arguments and passes the same authorization gates as a direct <code>tools/call</code>, with no separate path and no extra privilege. So search decides only which connected tools the model gets to see. Whatever it returns is the model's whole picture of what those accounts can do.</p>
<h2 id="what-went-wrong-when-a-notion-tool-answered-a-calcom-question">What went wrong when a Notion tool answered a Cal.com question?</h2>
<p>A user with only <a href="https://www.notion.com/">Notion</a> connected called <code>search_tools</code> with <code>list_all_cal_com_schedules</code>, a guess at a <a href="https://cal.com/">Cal.com</a> tool name. The top result was <code>list_all_notion_users</code>.</p>
<p>Ranking is purely lexical, which means it matches words, not meaning. It reads three fields: the tool name, the description and the connector label. The weights are fixed. An exact name-token match scores 5, a name-token prefix in either direction 3, a connector-label match 2, and a description-token match 1. In that query, <code>list</code> and <code>all</code> scored 5 each against <code>list_all_notion_users</code>. The tokens <code>cal</code>, <code>com</code> and <code>schedules</code> scored nothing, because nothing in a Notion-only tool set contains them. The generic half of the query carried the result, and the specific half was silently discarded.</p>
<p>A ranking with no floor always returns something. It sorts a list and hands back the top of it. When the query names an app the user has not connected, the top of the list is a tool from a different app with a plausible verb in its name. That is worse than an empty result, because a model does not treat a weak match as weak. It calls it.</p>
<h2 id="how-does-search-decide-a-result-is-too-weak-to-return">How does search decide a result is too weak to return?</h2>
<p>It compares what a tool matched with everything the query asked for, weighting rare words more. A tool must account for at least half of the query's own weighted mass to be returned at all. That rule is the relevance floor.</p>
<p>The weighting is inverse document frequency (IDF), a standard measure in information retrieval. Stanford's <em>Introduction to Information Retrieval</em> explains why it exists. Some terms "have little or no discriminating power", so <a href="https://nlp.stanford.edu/IR-book/html/htmledition/inverse-document-frequency-1.html">a rare term gets a high IDF and a frequent term usually a low one</a>. The book's example is a collection about the auto industry, where "auto" appears in almost every document. In tool names, <code>list</code> plays that part.</p>
<p>Elaichi measures rarity over the tools the caller can actually see, which is the pool left after restrictions, not the full catalog. The word <code>list</code> appears in nearly every tool name in any pool, so its weight is low. The tokens <code>schedules</code>, <code>cal</code> and <code>com</code> appear in almost nothing a Notion-only user can reach, so their weight is high. The weights are computed per query against the current pool rather than stored.</p>
<p>Run the incident through it. The tool <code>list_all_notion_users</code> covers only the two cheapest tokens and none of the expensive ones. That is well under half of the query's weight, so it never clears the floor. The caller gets an empty result, and the model reports that no matching tool exists. That is the correct answer: the user has no Cal.com connection, so there is no schedule to list.</p>
<p>Half is the line where a candidate has matched at least as much of the query's informative content as it missed. Below that line, no raw score makes it an answer to the question.</p>
<h2 id="why-measure-a-match-against-the-query-instead-of-a-fixed-score">Why measure a match against the query instead of a fixed score?</h2>
<p>Because a fixed cutoff stops working as queries and catalogs change, while a share of the query's own weight stays fair for every query. The table compares three ways to add a floor.</p>
<table>
<thead>
<tr>
<th>Approach</th>
<th>How it works</th>
<th>Where it fails or holds</th>
</tr>
</thead>
<tbody>
<tr>
<td>Absolute score cutoff (for example, "return nothing scoring under 6")</td>
<td>A fixed threshold on the raw weighted score</td>
<td>Scores are not comparable across queries. A six-token query gathers more raw score than a one-token query, and a query that names the connector adds 2 to every candidate from that connector. Tune for long queries and short ones return empty; tune for short ones and long ones pass junk. The cutoff also drifts as the pool grows with each new connector.</td>
</tr>
<tr>
<td>Embedding or cosine-similarity rerank</td>
<td>Vector similarity over tool name and description embeddings</td>
<td>It still always returns a ranked list, so a top-k over embeddings has the same no-floor failure with better-sounding scores. It is also weak on this exact case: "list records from a SaaS app" sits close in embedding space whether the app is Notion or Cal.com. It adds index upkeep on every connector edit, fork or new connection, latency inside the tool-call budget, and results that are harder to explain afterward.</td>
</tr>
<tr>
<td>Weighted-share floor (relative, per query)</td>
<td>A candidate must cover at least half of the query's own IDF-weighted token mass</td>
<td>It normalizes by construction: the same rule applies to a one-word search and a six-token guessed tool name. It holds after the tenth connector is added, because both the candidate's coverage and the query's total are recomputed against the live pool on every call.</td>
</tr>
</tbody>
</table>
<p>A reranker, however good, is an upgrade to the scoring underneath. It does not remove the need for a floor, because any function that puts candidates in order will hand back a top result even when every candidate is irrelevant. The floor is a separate mechanism: a threshold on whether to return anything at all, checked after scoring.</p>
<p>Other MCP servers may reasonably choose a threshold other than half, combine a lexical floor with a semantic fallback, or show a confidence score instead of cutting to empty. The claim here is narrower than calling this the only correct design. Whatever the scoring, a floor has to be relative to the query's own weight, not a fixed score. Otherwise it breaks under the two-sided pressure of short exact-name queries and long guessed ones sharing one endpoint.</p>
<h2 id="which-two-other-ranking-bugs-did-elaichi-fix">Which two other ranking bugs did Elaichi fix?</h2>
<p>Two, and both share the floor's root cause: tokens that look like signal and are not. The floor is one of three corrections in Elaichi's ranker.</p>
<p><strong>Description stop-words.</strong> The words <code>set</code>, <code>connection</code>, <code>frozen</code> and <code>more</code> are left out of description scoring, because they appear in the description of every merged or frozen tool, whatever the tool does. A merged tool is one tool that reaches several accounts of the same app. Information retrieval calls such words <a href="https://nlp.stanford.edu/IR-book/html/htmledition/dropping-common-terms-stop-words-1.html">stop words</a>: words so common they are of little value in selecting a match. Before the fix, a query containing "connection" gave every merged tool the same description score. Ties broke on name order, so the model was handed an arbitrary account's tool. Account labels and frozen field <em>values</em> stay scorable on purpose, because a caller might legitimately search for them.</p>
<p><strong>Tie-break by codepoint, never locale collation.</strong> When two tools score the same, Elaichi orders them by raw character codes, not by locale-aware sorting. Advertised tool names use exactly the characters that locale-aware comparison reorders, and the ranked list is cut to a limit before the model sees it. A locale-dependent tie-break would therefore decide which tools the model sees at all, depending on the server's locale. Codepoint order is identical everywhere the ranker runs. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> asks for the same property in listings: servers "SHOULD return tools in a deterministic order".</p>
<h2 id="what-does-refusing-weak-matches-cost-you">What does refusing weak matches cost you?</h2>
<p>Some recall. In information retrieval, <a href="https://nlp.stanford.edu/IR-book/html/htmledition/evaluation-of-unranked-retrieval-sets-1.html">precision is the share of returned results that are relevant, and recall is the share of relevant results that get returned</a>. The same text notes that the two "clearly trade off against one another". Lexical matching has no synonyms. Search "calendar" against a connector whose tools all say "schedule", and the only path to a match runs through the description or the connector label, if either contains the word. With a floor, that near-miss stops being a weak result and becomes no result. Genuine synonym queries will sometimes come back empty where a synonym-aware system would have found the tool.</p>
<p>The two failures do not cost the same. An empty result is visible: the caller can rephrase, and the model reports it found nothing. A wrong result stays invisible until it has run against a live third-party account, and the failure shows only after the side effect. The floor gives up some recall to cut silent wrong-tool runs. The case for it is strongest where tools write: a wrong read wastes a call, while a wrong write changes a live record.</p>
<h2 id="how-do-restrictions-affect-tool-search">How do restrictions affect tool search?</h2>
<p>They shrink the pool before ranking sees it, which makes search more accurate as well as safer. A restricted tool is withheld from the tool list and cannot be called, so it never competes with the tools the caller may run. Search ranks it separately and names it, flagged restricted, with no schema. Where the client shows Elaichi's search results as a card, the card says how many matches are restricted for the person and names up to five of them. Elaichi's resolver is the code that decides allow or deny. It runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p>The practical effect shows in two members. One, whose role reaches two <a href="/connectors/">connectors</a>, searches a small, clean pool. IDF weights there discriminate sharply, few candidates share tokens, and the floor rarely settles a close call. The other, with everything connected, searches a pool where many tools compete on generic verbs like <code>list</code>, <code>get</code> and <code>create</code>. The weights flatten, and the floor does more of the work. Restrictions are a security control first, and mechanically they are a precision control on search too.</p>
<p>One timing detail: when you change a restriction, search results reflect it within about two minutes. Grant revocation, member removal and suspension are faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="when-does-a-small-server-not-need-tool-search-at-all">When does a small server not need tool search at all?</h2>
<p>When it has a handful of tools and lists them all. If you build your own MCP server with eight tools and return every one from <code>tools/list</code>, the model reads the whole list on every request. No ranker sits in the path, and a relevance floor solves a problem you do not have. The weighting and the stop-word list are irrelevant to a small, fixed, hand-written tool list. Stay there as long as the tool count lets you.</p>
<p>The floor starts to matter when two conditions hold together:</p>
<ul>
<li>The server serves tools through search rather than a full list, so a ranker is in the path at all. Elaichi does this for every connected tool.</li>
<li>The caller is a model composing a tool name from memory or inference, not a person choosing from a visible, complete list.</li>
</ul>
<p>Both conditions hold the moment a company connects its first SaaS account behind <a href="/blog/zapier-mcp-alternative/">one endpoint rather than a server per member for each client</a>. That is why the floor is an endpoint-level guarantee and not a per-connector setting.</p>
<p>For what Elaichi's endpoint serves once several accounts sit behind it, see the <a href="/product/">product overview</a> and a single connector's tool surface such as <a href="/connectors/zendesk/">Zendesk</a>. For the team-by-team view of who searches for what, start with the <a href="/use-cases/">use-cases index</a>.</p>
<h2>FAQ</h2><dl><dt><strong>How does MCP tool search choose a tool?</strong></dt><dd>In Elaichi, tool search matches the words of a query against each connected tool's name, description and app label, with fixed weights: 5 for an exact name match, 3 for a name prefix, 2 for the app label and 1 for the description. It then returns only tools that cover at least half of the query's weight, where rare words count for more than common ones. A tool that matches only generic words such as list is not returned.</dd><dt><strong>Why does MCP tool search return nothing instead of a close match?</strong></dt><dd>Because a close match from the wrong app is worse than no match: a model handed one will call it. In one real case, a user with only Notion connected searched for list_all_cal_com_schedules and got back list_all_notion_users, because list and all matched while cal, com and schedules matched nothing. Elaichi now requires a tool to cover at least half of the query's weighted words, so that search comes back empty and the model reports that no matching tool exists.</dd><dt><strong>Does Elaichi ever list connected tools instead of searching them?</strong></dt><dd>No. In Elaichi, connected tools are never listed one by one, however few there are. The model sends a query to search_tools and runs its choice through execute_tool. Control-plane operations stay listed individually, and search_tools never returns one. A restricted tool cannot be called. Search names it, flagged restricted, with no schema.</dd><dt><strong>Would an embedding reranker fix bad MCP tool search results?</strong></dt><dd>Not on its own, and not on the case that matters most. Two tools that list records from different SaaS apps sit close together in embedding space while being unrelated in fact, so mixing up apps is the failure a vector model handles worst. Cosine similarity also always returns a ranked list, so a top-k over embeddings repeats the wrong-result failure with better-sounding scores. A coverage floor is the fix, and better scoring is an upgrade layered on top of it.</dd><dt><strong>How quickly does a restriction change affect tool search results?</strong></dt><dd>Within about two minutes. Role and restriction changes pass through a cache that holds for 60 seconds and then spread to the edge, on MCP, the console and REST alike. Grant revocation, member removal and suspension take effect on the next call. Elaichi re-reads the OAuth grant's revocation state from the organization store on every call, with no cache.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Running your own MCP servers: the real cost</title>
      <link>https://elaichi.ai/blog/self-hosted-mcp-servers-vs-control-plane/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/self-hosted-mcp-servers-vs-control-plane/</guid>
      <description>Running your own MCP servers wins for one internal tool. Managed wins once credentials, token refresh, per-user sign-in and audit multiply.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Running MCP servers yourself is cheap on day one and expensive by the ninth server. Credential storage, token refresh, per-user sign-in, access rules, audit and offboarding all become yours to build and keep running. Elaichi answers them with one organization-wide endpoint, a separate credential service that owns refresh, and one resolver checked everywhere a member can reach a tool. If the server is internal, proprietary and used by one team for its own data, keep running it yourself.</aside>
<h2 id="running-your-own-mcp-servers-which-costs-keep-coming-back">Running your own MCP servers: which costs keep coming back?</h2>
<p>Running your own MCP servers is cheap to start and expensive to keep. The costs that come back are credentials, token refresh, per-user sign-in and audit, and they grow with every server.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An MCP server is a small service that offers those tools, here over the Streamable HTTP transport in the <a href="https://modelcontextprotocol.io/">MCP spec</a>. The first one takes an afternoon. You pull a server for your ticketing system, give it a token, run it somewhere the team can reach, and point Cursor at it. Nothing about that afternoon is wrong. The real question does not arrive until the ninth server. By then four of the servers hold a long-lived token in an environment variable, and two broke the week an OAuth app rotated its keys. Nobody can say which of two connected workspaces an agent wrote to last Tuesday.</p>
<p>The recurring costs arrive in roughly this order, and each one shows up only once the one before is handled:</p>
<ol>
<li><strong>Credential storage:</strong> where the secret sits and what a read-back returns.</li>
<li><strong>Refresh:</strong> what happens when a token expires overnight.</li>
<li><strong>Per-user auth:</strong> whether the server knows who is calling.</li>
<li><strong>Access rules:</strong> what each caller may reach, and where that is checked.</li>
<li><strong>Audit:</strong> which account each call actually reached.</li>
<li><strong>Offboarding:</strong> what still works after a person leaves.</li>
</ol>
<p>A backlog grows behind those six with every connector. A served control plane answers most of it, and the case for keeping a server yourself is here too.</p>
<h2 id="which-kind-of-managed-mcp-are-you-comparing-against">Which kind of managed MCP are you comparing against?</h2>
<p>Managed MCP comes in three broad shapes that fail in different ways, so name the one you mean before you compare. <a href="/blog/best-mcp-gateways/">The vendor-by-vendor map of gateway shapes</a> covers the whole field.</p>
<ul>
<li><strong>A proxy in front of servers you run.</strong> Sign-in and logging move to a gateway, but the server code, its bugs and its schema stay yours. Governance is only as good as what the proxy sees.</li>
<li><strong>A hosted registry.</strong> The vendor deploys community-maintained servers for you. That buys breadth, but rules are matched against a schema the vendor did not write.</li>
<li><strong>A first-party connector author.</strong> The vendor writes and maintains the connector code, so a rule can bind to the real upstream operation.</li>
</ul>
<p>Elaichi is the third shape: the MCP server itself for most of its 600+ connectors, which it authors, with vendors' own MCP servers governed for the rest.</p>
<h2 id="where-do-the-credentials-live-and-who-guards-them">Where do the credentials live, and who guards them?</h2>
<p>On a server you run, the credential sits on the host as an environment variable or a secret-manager entry. Anyone who can reach the server acts as that token. Elaichi keeps connector credentials out of its own store. A separate credential service holds them, encrypted at rest with AES-256-GCM.</p>
<p>The split is deliberate. One separate data store per organization holds members, roles, connections, restrictions and grants. The store that answers "may this person call this tool" never holds the token, so compromising one does not hand over the other. Reading an account's configuration returns the public values plus <code>secret_paths</code>, the list of encrypted dot-paths, with none of their values.</p>
<p>Two controls sit on top. An organization can bring its own OAuth app per connector. It takes a client ID, a client secret and scopes but no URL, so the flow cannot be pointed at another host. Elaichi gates that on <code>connector:manage</code> rather than <code>connection:manage</code>, so the right to delete a connection is not the right to repoint the OAuth app. For key custody, customer-managed keys in AWS KMS come with the Black plan, which is launching soon (<a href="https://aws.amazon.com/kms/">AWS KMS</a>).</p>
<p>Self-hosting the equivalent means you own the encryption, the key rotation and the rule about what a configuration read may echo back. With one credential and an existing secret manager, that is a few hours of wiring. At nine servers and thirty accounts, it is a product with its own backlog.</p>
<h2 id="who-owns-token-refresh-at-two-in-the-morning">Who owns token refresh at two in the morning?</h2>
<p>Someone always does. In Elaichi it is the credential service, and on a server you run it is whoever carries the pager. Refresh swaps an expired token for a new one without a fresh sign-in, on the vendor's clock rather than yours. When an Elaichi refresh fails, the connection is marked <code>needs_reauth</code> so its owner can reconnect.</p>
<p>That visible state exists because the alternative is worse than an outage. A server that keeps calling with a dead token returns errors shaped like permission problems. A model reads those as a cue to try another tool. You get a confident wrong answer instead of a connection someone can fix.</p>
<p>Write refresh handling yourself and the list is longer than it looks:</p>
<ul>
<li>Detect expiry before the call by tracking token lifetimes, not only by catching 401 errors afterward.</li>
<li>Handle rotation, where a provider retires the old refresh token on every use. A naive retry with the old one creates a race condition.</li>
<li>Tell "token expired" apart from "app revoked on the vendor's side." The second keeps failing however often you refresh.</li>
<li>Stop calling once the state is known to be bad, instead of retrying into a rate limit.</li>
<li>Show the state where the connection's owner will see it, such as a Slack DM, not a log line.</li>
</ul>
<p>Each item is small alone. Across every connector they add up to an on-call rotation for failures that look like the model's fault.</p>
<h2 id="is-the-caller-a-person-or-a-shared-service-account">Is the caller a person or a shared service account?</h2>
<p>Most self-hosted servers start with one shared credential, so every call looks like the server made it. Elaichi ties every call to the person who signed in.</p>
<p>Per-user OAuth is the expensive part to build: a consent screen, a token store keyed by user, and a rule for when that user leaves. A shared credential skips all of that, but then the answer to "who did this" is the server. Security reviews stop accepting that once a few people share the token.</p>
<p>Elaichi has one organization-wide endpoint, the address every client connects to: <code>POST /mcp</code>, speaking standard MCP over Streamable HTTP and <a href="https://www.jsonrpc.org/specification">JSON-RPC 2.0</a>. It is stateless and sits behind OAuth, the standard that gives a client a scoped grant instead of a password. Each user signs in, and the grant belongs to that person. No toolbox (a named set of tools and accounts handed to a client) gets its own URL, and no token sits in a client config. Revoking access is therefore a database write, not a hunt for a URL somebody pasted into a client. Claude, ChatGPT and Cursor share that one URL, each member connects once, and a fourth client takes the same shape.</p>
<p>Elaichi signs people in through your identity provider over SAML or OIDC single sign-on (SSO), and <a href="https://scim.cloud/">SCIM v2</a> pushes users and groups in from it.</p>
<h2 id="what-access-rules-would-you-have-to-build-yourself">What access rules would you have to build yourself?</h2>
<p>Roles, sharing and per-tool restrictions, checked the same way on every path a request takes. The MCP spec supplies none of them. A self-hosted server usually checks once, at execution, because that is where the code lives.</p>
<p>Elaichi runs one resolver (the code that decides allow or deny) at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. The advertise check matters because a tool withheld from the list is one the model cannot retry or work around.</p>
<p>Elaichi also keeps three layers apart, since mixing them makes a homegrown model hard to explain to an auditor. Permissions are 58 action strings grouped into roles, one role per member. Sharing gives a user, a team or everyone in the organization view, use or edit rights on one resource. Nobody, owners included, sees a resource they neither own nor were given. Restrictions decide which connectors and which individual tools a target may reach.</p>
<p>The rules are narrow on purpose, and restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A member is governed by their role's rules and by any rule aimed at them personally, and a tool is reachable only when both admit it. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Blocks always beat allows. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>Rules bind to operations, not labels. Elaichi pins the underlying operation when a rule is saved, because anyone who edits a connector's documentation can rename a tool. A block fires on the name or the operation, and an allow on the operation alone, as <a href="/blog/block-matches-name-allow-matches-operation/">the rename case</a> explains.</p>
<p>Some arguments should never be the model's choice. Frozen parameters are hidden from the advertised schema, and their values override whatever the caller sends. Built by hand, that is schema rewriting plus a merge order to defend to a reviewer.</p>
<p>One limit holds on both paths. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server sees only the arguments a client chose to send, never the user's prompt. What does hold at <code>POST /mcp</code> is per-operation RBAC (role-based access control), OAuth scope limits, output redaction, the <code>forbidden</code> classification and an audit row for each call that reaches execution. A server you build has none of those until you write them.</p>
<h2 id="what-does-a-defensible-audit-trail-cost-to-build">What does a defensible audit trail cost to build?</h2>
<p>Per-server log files are easy. A trail a reviewer accepts needs one record shape across every server, and rows no other organization can query. Each connected-tool call that reaches execution in Elaichi leaves one record naming who or what made it, what ran and which account it reached. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an AI audit log must hold</a> are set out in full elsewhere.</p>
<p>Two parts cost more than a log table. The first is tenancy. An <code>org_id</code> filter in a <code>WHERE</code> clause leaks the day someone drops the clause. Elaichi scopes each organization's audit history in the type system, so a wrong scope returns nothing. The second is error text. A vendor's error message can carry that vendor's data, and audit records may be forwarded to a SIEM (security monitoring system). Elaichi keeps the caller's error text out of the trail for that reason.</p>
<p>Two caveats remain. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon (<a href="https://docs.datadoghq.com/logs/">Datadog</a>). Elaichi accepts <a href="https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector">Splunk HEC</a> and <a href="https://learn.microsoft.com/en-us/azure/sentinel/">Microsoft Sentinel</a> as destinations but delivers events only to Datadog. And deleting an organization deletes its connector credentials but leaves three stores: the audit history (each record ages out under the log server's 90-day retention, counted from when it was written), analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name.</p>
<h2 id="what-happens-to-a-leavers-access-on-each-path">What happens to a leaver's access on each path?</h2>
<p>On servers you host, offboarding is a checklist: revoke the keys, shut down the instance, and hope nobody kept a copy of the URL. In Elaichi, grant revocation, member removal and suspension take effect on the next call, whichever client makes it, and so do revoking a share and disconnecting an account. The grant is re-read on every call, and removing or suspending a member revokes every live grant in the same transaction as the membership change. Role and restriction changes take the slower path of about two minutes, so treat the two kinds of change separately.</p>
<p>Removal in Elaichi also runs a preflight. A private connection that a shared toolbox depends on blocks the removal until an admin transfers it to a member. A transfer goes to one member, never to a team or the organization. A private connection that nothing beyond the person depends on cannot be transferred and is deleted with them. <a href="/blog/offboarding-when-the-agent-holds-access/">The order of operations for a member's last day</a> is written up step by step.</p>
<h2 id="what-else-sits-on-the-build-backlog">What else sits on the build backlog?</h2>
<p>Connector upkeep, tool discovery, orchestration and residency. Each is easy to leave out of a first estimate.</p>
<p>Connector upkeep scales with breadth times churn. Every connector is a contract with somebody else's API: fields appear, pagination changes, and endpoints are deprecated on the vendor's schedule. Two internal services are cheap, since you write their release notes. Thirty SaaS apps are a standing claim on engineering time. Elaichi maintains its connectors centrally, so a vendor's API change is not your deploy. The trade is that you cannot patch a connector you did not write at 4pm on the day a vendor renames a field.</p>
<p>Tool discovery changes too: a server you build lists its tools in <code>tools/list</code>, and the model picks from whatever you put there. In Elaichi, connected tools are never listed one by one, however few there are. The model finds them with <code>search_tools</code>, where a tool must clear <a href="/blog/search-tools-ranking-floor-idf/">a relevance floor</a> before it is returned, and runs them with <code>execute_tool</code>.</p>
<p>Orchestration and residency finish the list. Elaichi's synthetic tools chain steps across connections, and each step passes the same restriction checks as a direct call. The run is audited as one row, with counts and no step results. A homegrown version is a second enforcement path that drifts from the first. Elaichi regions are chosen at organization creation. There are three, EU, US and APAC. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. Promising regions yourself multiplies deployment and log isolation by each region a customer asks for.</p>
<h2 id="how-do-the-two-paths-compare-cost-by-cost">How do the two paths compare, cost by cost?</h2>
<p>Self-hosting keeps every cost in-house. A served control plane moves most of them onto a line item.</p>
<table>
<thead>
<tr>
<th>Cost</th>
<th>You run the server</th>
<th>Served control plane (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Credential storage</td>
<td>Your secret manager, key rotation and read-back rules</td>
<td>Separate credential service, AES-256-GCM at rest, value-free <code>secret_paths</code> read-back; customer-managed keys come with the Black plan, launching soon</td>
</tr>
<tr>
<td>Refresh</td>
<td>You detect expiry, handle rotation, spot vendor-side revocation and surface the state</td>
<td>The credential service owns refresh; a failure marks the connection <code>needs_reauth</code></td>
</tr>
<tr>
<td>Per-user auth</td>
<td>Usually one shared credential, so every call is the service account</td>
<td>One <code>POST /mcp</code> behind OAuth; the grant varies per person, the address does not</td>
</tr>
<tr>
<td>Access rules</td>
<td>Checked once, at execution</td>
<td>One resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file</td>
</tr>
<tr>
<td>Audit</td>
<td>A schema you design and usually change twice</td>
<td>One record per executed call naming the account reached, in each organization's own audit history</td>
</tr>
<tr>
<td>Offboarding</td>
<td>A checklist, plus every copy of the URL</td>
<td>Grants cut on the next call; a preflight for connections others depend on</td>
</tr>
<tr>
<td>Connector upkeep</td>
<td>Every vendor API change is your on-call</td>
<td>Maintained centrally; forks pull upstream changes through a review screen</td>
</tr>
</tbody>
</table>
<h2 id="when-should-you-keep-running-your-own-mcp-servers">When should you keep running your own MCP servers?</h2>
<p>Keep them when the tool is yours, the risk is bounded and the audience is small. Self-hosting wins when all of these hold:</p>
<ul>
<li>The system is internal and proprietary, so there is no third-party OAuth app to refresh against.</li>
<li>The blast radius (how much can go wrong if something breaks) is one team's own data, usually read-only.</li>
<li>The network, or the service the server fronts, already settles identity, such as through a VPN.</li>
<li>A handful of engineers use it from one client.</li>
</ul>
<p>Under those conditions the build is small. A single-credential server with a long-lived static token takes a day or two, deploy and review included. Refresh for a token that really expires adds one to two days. Per-user OAuth adds two to four more, plus upkeep whenever the provider changes its rotation behavior. An audit schema a reviewer accepts will change after the first internal audit asks a question it cannot answer. That server does not need a control plane, and with one connected app and two people <a href="/blog/when-you-dont-need-an-mcp-gateway/">a gateway of any kind is premature</a>.</p>
<p>Two more cases favor writing the server. One is logic that is not config-shaped, such as an internal pricing service with real branching or a datastore with no API. The other is placement. Elaichi is hosted, so a deployment inside your own network, or in a region Elaichi does not offer, means running it yourself.</p>
<p>Self-hosting does not have to mean writing the governance layer too. Lunar.dev describes MCPX as a self-hosted enterprise MCP gateway between agents and the servers, APIs and LLM providers they use (<a href="https://www.lunar.dev/">lunar.dev</a>). Tyk's MCP Gateway proxies and governs remote MCP servers on every Tyk Gateway license, with upstream OAuth on Tyk Enterprise Edition (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk docs</a>, checked October 2026). Composio lists self-hosting at its Enterprise tier (<a href="https://composio.dev/enterprise">Composio enterprise</a>). All three pages were checked September 2026.</p>
<p>A middle path exists when the internal system is an HTTP API rather than bespoke MCP logic. An Elaichi custom connector written from JSON config brings it under the same resolver and audit trail, with no server to run. The <code>connector:create</code> permission behind it is flagged high-trust, because a custom connector can point at any destination.</p>
<h2 id="how-do-you-price-the-two-paths-and-decide">How do you price the two paths and decide?</h2>
<p>Put a line item next to headcount, then run five checks. Elaichi Gold lists at $15 per seat each month in USD, or $120 per seat for a year, and the <a href="/pricing/">pricing page</a> shows the price for your region. The plans include a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Suspended members and the Guest, Billing Admin and Auditor roles are not billed, so a compliance reviewer can read the audit trail without a license.</p>
<p>Ten seats cost $1,200 to $1,800 a year depending on billing cadence, 50 seats cost $6,000 to $9,000, and 200 cost $24,000 to $36,000. <a href="/blog/mcp-gateway-pricing/">Per-seat and per-call metering across vendors</a> is compared separately. On the self-hosted side, the recurring cost is refresh edge cases, deferred per-user OAuth, audit schema changes and an on-call rotation. Multiply that by every connector you run, and give each item an owner, because a cost with no owner is one you have not priced.</p>
<p>The five checks take an afternoon:</p>
<ol>
<li><strong>List the systems and the people.</strong> Two internal systems and one team means you keep the servers and stop here.</li>
<li><strong>Multiply AI clients by servers.</strong> That product is how many configurations you maintain yourself. The control plane has one address.</li>
<li><strong>Run the leaver test.</strong> Ask how long a recent leaver's access to each server survived.</li>
<li><strong>Ask the audit question.</strong> After an unexpected change, ask which of your two Notion workspaces the agent wrote to. If no single query answers it, the record is the gap.</li>
<li><strong>Trial one team for two weeks,</strong> starting with the app you can least afford to get wrong.</li>
</ol>
<p>Decide on blast radius, not on taste. One internal server against a system you own: keep it. Third-party accounts, several people, several clients and a regulator's question about who called what are different. At that point these costs are infrastructure that needs an owner. The <a href="/connectors/">connector catalog</a> shows what Elaichi already authors, and <a href="/use-cases/">team-by-team starting points</a> show where a rollout can begin.</p>
<h2>FAQ</h2><dl><dt><strong>Is it cheaper to self-host MCP servers than to use a managed control plane?</strong></dt><dd>It depends on how many credentials, people and AI clients are involved. One internal MCP server with one credential, one team and one client is cheaper to self-host. Once third-party accounts, several clients and several people are in play, credential storage, token refresh, per-user sign-in, access rules and audit become ongoing engineering work rather than a one-week build. On the managed side the cost is a line item. Elaichi's Gold plan lists at $15 per seat each month in USD, or $120 per seat for a year, with a 14-day trial. Suspended members, plus Guest, Billing Admin and Auditor seats, are excluded from the billable count.</dd><dt><strong>What happens when the OAuth token behind an MCP connector expires?</strong></dt><dd>In Elaichi, a separate credential service holds per-account secrets, encrypted at rest, and owns refresh. If a refresh fails, Elaichi marks the connection needs_reauth instead of failing silently, and the person who owns the connection can reconnect it. That state matters because a server that keeps calling with a dead token returns errors that look like permission problems. A model treats a permission problem as a reason to try a different tool, not as a failure to report.</dd><dt><strong>How quickly does revoking an agent's access take effect?</strong></dt><dd>Grant revocation, member removal and member suspension take effect on the next call. Elaichi re-reads the revoked_at flag from the organization store on every call with no cache, and removing or suspending a member revokes every live grant in the same transaction as the membership change. Role changes and restriction changes are different. They resolve through a 60-second cache plus edge propagation, so allow about two minutes, on the MCP endpoint, the console and the REST API alike.</dd><dt><strong>Can a managed MCP control plane sit in front of MCP servers I already run?</strong></dt><dd>Only in part. Elaichi is the MCP server itself for the connectors it authors, and it governs vendors' own MCP servers in its catalog. On Gold, or on Black once it launches, it can also front a company server reachable over public HTTPS, added as the organization's own remote MCP connector. A proprietary internal server keeps its own address, credential and access rules, and sits beside Elaichi in the client's list of connections. If the internal system is an HTTP API and not bespoke MCP logic, a custom connector written from JSON config brings it under the same restriction resolver and audit trail.</dd><dt><strong>Where are restrictions enforced on a governed MCP call?</strong></dt><dd>Against the same resolver, at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. Restrictions target a role or an individual user only. A member is governed by their role's rules and by any rule aimed at them personally, and a tool is reachable only when both admit it. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. With no rule at all, nothing is restricted. Within each layer, blocks always beat allows. Also note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</dd><dt><strong>Does Elaichi run inside our own network?</strong></dt><dd>No. Elaichi is a hosted MCP control plane. It has three regions, EU, US and APAC, chosen when the organization is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region. If the requirement is a deployment inside your own network, a self-hosted MCP server or a self-hosted gateway is the better fit.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>When you don&apos;t need an MCP gateway yet</title>
      <link>https://elaichi.ai/blog/when-you-dont-need-an-mcp-gateway/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/when-you-dont-need-an-mcp-gateway/</guid>
      <description>Per-user connectors plus SSO are enough while you can name everyone connected. That is when you don&apos;t need an MCP gateway, and four signals end it.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> If your AI use is one client, a roster you can recite and accounts your identity provider already owns, per-user connectors plus single sign-on are the right design, and a control plane such as Elaichi is premature. Four signals end the wait: a second AI client or team, more accounts than people, a departure that leaves a grant nobody can list, and someone outside the team who has to answer for what agents did. Moving early costs seats; moving late costs a reconstruction of records nobody kept.</aside>
<h2 id="when-you-dont-need-an-mcp-gateway-which-three-company-shapes">When you don't need an MCP gateway: which three company shapes?</h2>
<p>Most writing in this category exists to sell a control plane, so start from the other end. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An MCP gateway, or control plane, is a central service that manages which assistants may reach which tools. So start by asking when you don't need an MCP gateway. The answer does not depend on company size. It depends on whether you can answer three questions today: who is connected, what can they reach, and can you revoke it in one action.</p>
<p>Call this the inventory test. Some companies pass it today with per-user connectors in <a href="https://claude.ai">Claude</a>, <a href="https://chatgpt.com">ChatGPT</a> or <a href="https://cursor.com">Cursor</a>, plus an SSO policy on the SaaS underneath. SSO, single sign-on, is one company login for many apps. For them, a governed MCP endpoint, one web address that every assistant connects to, buys a migration, a bill and a second place to look. In return they get controls that nothing in the business is asking for. Three company shapes are the honest cases for waiting. Each one is a specific way the inventory test still passes, and each one ends with a specific change.</p>
<h3 id="one-ai-client-and-a-roster-you-can-recite">One AI client and a roster you can recite</h3>
<p>If you can name, from memory, every person who has connected an AI assistant to a company system, you have an inventory. It is in your head, it is accurate, and it costs nothing to query. A control plane's whole value at the small end is that it turns a hard listing problem into a list. When the list is six people and one client, buying the list is buying something you already have.</p>
<p>The thing to watch is not headcount. It is whether the roster survives a week when you are not paying attention. Roster knowledge decays the moment someone can connect an account without telling you. That usually starts when a second AI client or a second team arrives.</p>
<h3 id="read-only-work-against-a-single-system-of-record">Read-only work against a single system of record</h3>
<p>A sales team running research questions over one CRM, with no write path, has a narrow blast radius. Blast radius means how much can go wrong if something breaks. The assistant acts as the person, so the person's existing CRM permissions limit it. If a rep cannot see enterprise pipeline in the CRM, the assistant cannot either. You did the access design once, in the CRM, and the AI inherits it. No separate policy layer is needed, because there is nothing for one to add.</p>
<p>This stops being true the moment writes are in scope. A write is where the difference between what a person would do and what a model will do starts to matter. A second system matters as well, because the CRM's permission model has no opinion about what the other system allows. Once agents can write to more than one account, a surprise change raises a question read-only work never does: which account made it.</p>
<h3 id="every-reachable-account-owned-by-your-identity-provider">Every reachable account owned by your identity provider</h3>
<p>Suppose every SaaS account an assistant can touch is federated, created through <a href="https://datatracker.ietf.org/doc/html/rfc7644">SCIM</a> and removed by the same action that closes the laptop. SCIM is the standard way an identity provider (IdP) creates and removes accounts automatically. Then your IdP is already the control plane for the parts that matter. Central sign-in, MFA (multi-factor authentication), session revocation and group membership are real controls, and you already pay for them.</p>
<p>The qualifier is the word every. Think of the shared vendor portal with its own login, the personal Notion workspace for meeting notes, or the API key pasted into a script. The IdP owns none of them. Each one carries a grant, the stored permission that lets an assistant act for a person, and that grant outlives the account closure. In practice, "every" is the condition that breaks first. Most companies find the exception during an offboarding, not during an audit.</p>
<h2 id="what-do-per-user-connectors-and-sso-already-cover">What do per-user connectors and SSO already cover?</h2>
<p>They cover authentication well, authorization partly, and inventory not at all. Authentication means proving who someone is, and authorization means deciding what they may do. Be precise about the split, because vendors in this category tend to be vague about what the cheap setup does well.</p>
<p><strong>Authentication is covered.</strong> Sign-in goes through one identity, with MFA enforced centrally and sessions revocable centrally.</p>
<p><strong>Authorization is partly covered.</strong> OAuth is the sign-in flow where a person approves access in the browser without handing over a password. An OAuth consent binds a connector to what it asked for, and a connector that only requested read cannot write. Inheritance adds a second limit, since an assistant acting as a person can do no more than that person can. Both limits are real, but both are set per connection, not once for a team.</p>
<p><strong>What none of it covers is the register.</strong> The register is the missing record: a single place that lists which grants exist, who made them, and which account each one reached. Each seat holds a fragment of that answer, and no seat holds the whole. That is not a flaw in SSO, which was never built to be the inventory. Every signal that ends the wait is, at bottom, a question only a register can answer.</p>
<table>
<thead>
<tr>
<th>Question you will be asked</th>
<th>Per-user connectors plus SSO</th>
<th>Governed MCP control plane</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who signed in, and with what factor</td>
<td>Covered by the IdP</td>
<td>Covered, plus SSO, SCIM and group-to-role mapping in Elaichi itself</td>
</tr>
<tr>
<td>What can this person reach in the target system</td>
<td>Inherited from that system's own permissions</td>
<td>Inherited, plus restrictions on a role or a user</td>
</tr>
<tr>
<td>Which grants exist across the company</td>
<td>Not answerable without polling each seat</td>
<td>Listed centrally</td>
</tr>
<tr>
<td>Which account did the agent actually write to</td>
<td>Not recorded in one place</td>
<td>Named in the audit entry for each executed call</td>
</tr>
<tr>
<td>Does removing a person end the AI's access</td>
<td>Only where the IdP removes the account itself</td>
<td>Yes: removing or suspending a member revokes every live grant in the same transaction as the membership change</td>
</tr>
<tr>
<td>What does a second AI client add</td>
<td>Every account connected again, by each person, in the new client</td>
<td>The same address; each member signs in from the new client</td>
</tr>
</tbody>
</table>
<h2 id="signal-one-has-a-second-ai-client-or-team-arrived">Signal one: has a second AI client or team arrived?</h2>
<p>The first signal is multiplication. One client and one team is a setup task. Two clients across three teams is a matrix, and every account has to be connected again in each cell of it.</p>
<p>A mental roster is per person, not per system. A second client doubles the places where a connection can happen without you noticing, and a second team brings accounts you never set up. Nobody decides to stop tracking. The matrix simply outgrows memory.</p>
<p>A control plane collapses the matrix to one row. In Elaichi, each SaaS account is connected once, and Claude, ChatGPT and Cursor all point at the same organization-wide endpoint, <code>POST /mcp</code>, behind OAuth. Where a client lets an admin add it for everyone, that happens once. Each member then signs in with their own grant. A fourth client repeats the same small job and does not fork the setup.</p>
<h2 id="signal-two-are-there-more-accounts-than-people">Signal two: are there more accounts than people?</h2>
<p>Count accounts, not headcount. Once your team holds more SaaS accounts than it has members, the question "which account did the agent just write to" stops having an obvious answer.</p>
<p>The extra accounts arrive quietly. A second workspace of the same app, opened for a client project. A shared finance login that two people know. A service account for the warehouse that nobody remembers creating. Each one breaks the assumption the small setup rested on: one human, one account, one log line. With per-user connectors, the evidence is split between each person's chat history and each app's own log. A shared login makes that log name nobody in particular.</p>
<p>Elaichi's audit log, its record of who did what, names the account each call reached, with one entry for each connected-tool call that reaches execution (a call refused earlier writes none). <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> covers the rest of what belongs in one. Frozen parameters stop the wrong choice before it happens. Freeze the workspace on a shared tool, and the model cannot change that field, so it cannot pick the other account.</p>
<h2 id="signal-three-does-a-leavers-ai-still-hold-access">Signal three: does a leaver's AI still hold access?</h2>
<p>The third signal is a departure that leaves a grant nobody can list. It usually arrives on an account the IdP never owned.</p>
<p>Someone connected a shared billing portal and a personal project workspace to their assistant in March. In October they resign. You disable the IdP account within the hour, and the SSO logins die with it.</p>
<p>Now answer two questions. Which grants did that person hold, and which of them were tied to an account your IdP never federated? If the answer to the first is an email to their manager, and the answer to the second is a shrug, the cheap setup has run out. The grant you cannot list is the grant you cannot revoke. An OAuth refresh token does not check with your IdP before renewing itself.</p>
<p>This is what a control plane is actually for. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is checked again on every call, with no cache, so the next call fails, whichever AI client sends it. Verify that on the current <a href="/security/">security page</a> rather than taking it on faith. The steps for the last day are laid out in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding a member with MCP connections</a>.</p>
<h2 id="signal-four-does-someone-besides-the-operator-answer-for-it">Signal four: does someone besides the operator answer for it?</h2>
<p>The fourth signal is a person outside the room asking what agents can reach, or what they did. A customer security questionnaire, a clause in a renewal, an internal auditor, a board packet.</p>
<p>This is the signal most teams misread, because it does not feel like a technical event. It is a change in who the audience for the record is. With per-seat setup, "what can Sales reach" is a survey. You ask fourteen people, get eleven replies, and three of them are wrong because nobody remembers what they authorized in March. "What did the agent do" is a screenshot of a chat window. A screenshot stops being evidence once the reader is not the person who made the call.</p>
<p>In Elaichi, every account a person can reach is one they connected or one shared with them, and that sharing is written down. Restrictions, the rules that decide which connectors and which individual tools a target may reach, narrow that reach for a role or a user. A role or restriction change takes effect within about two minutes, so check a rushed change before telling a reviewer it is live. The reviewer can read Elaichi's audit log from an Auditor seat, which is free and cannot call a tool.</p>
<h2 id="what-does-not-count-as-a-signal">What does not count as a signal?</h2>
<p>Volume, curiosity, catalog size and a departure you can close in one place all feel like the moment, and none of them is.</p>
<p>Volume is the usual one. Ten thousand tool calls a month through one person's own account is still one person's own account, and a control plane governs nobody new. Curiosity is another. Wanting to understand MCP is a good reason to read <a href="https://modelcontextprotocol.io/specification">the specification</a> and a poor reason to buy a seat for everyone.</p>
<p>Catalog size sits in the same bucket. A catalog of 600+ connectors matters when you need the twelfth one governed, not when you need the first one working.</p>
<p>A single departure is not a signal either, if it closes cleanly. When a contractor leaves and you can revoke their one account in the one app, do that today and move on. It becomes a signal only when it leaves a grant nobody can list.</p>
<h2 id="what-other-kinds-of-mcp-gateway-exist">What other kinds of MCP gateway exist?</h2>
<p>Several, and they are not interchangeable. The inventory test tells you which one fits today, whichever vendor, or no vendor, you end up choosing.</p>
<ul>
<li><strong>Per-user connectors plus SSO:</strong> the setup most small teams already run. It needs no separate infrastructure, inherits the target system's permissions, and has no central register.</li>
<li><strong>Per-member servers inside an automation account:</strong> Zapier MCP is the example. Every client shares one Zapier URL, and each member gets a server per client, created at sign-in. In an organization rollout, each member still signs in and runs tool calls as themselves, through OAuth in most clients (<a href="https://docs.zapier.com/mcp/manage/rollout/overview">rollout guide</a>). Clients not on Zapier's list use a connection token, which Zapier's <a href="https://docs.zapier.com/mcp/overview/how-connections-work">connection docs</a> say to treat like a password, with "their own server and token" for each user (both checked October 2026). That shape suits a company whose AI work already lives in a Zapier account.</li>
<li><strong>Self-hosted MCP proxies:</strong> you run your own gateway process, and open-source options exist for basic request routing and logging. You own uptime, patching and log storage, and in return you do not depend on a vendor. The cost curve is worked through in <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the run-it-yourself math</a>.</li>
<li><strong>Commercial MCP gateways and control planes:</strong> hosted and governed, with a central register, at the cost of a subscription and a new dependency. Elaichi is one. Composio is another, a hosted platform that gives AI agents tools and managed authentication. Its <a href="https://composio.dev/enterprise">enterprise page</a> describes role-based permissions, audit logs and SSO (checked September 2026).</li>
</ul>
<h2 id="what-does-a-control-plane-cost-you-besides-the-bill">What does a control plane cost you besides the bill?</h2>
<p>It changes how tools reach the model, and it leaves some risks exactly where they were. A fair comparison names that friction, not just the capability.</p>
<p><strong>Tools reach the model differently.</strong> In Elaichi, connected tools are never listed one by one, however few there are. The model reaches them through two tools, <code>search_tools</code> to find one and <code>execute_tool</code> to run it. Do not expect the flat, hand-picked list that native connectors show.</p>
<p><strong>Prompt injection stays your problem.</strong> Prompt injection means hidden instructions in text that trick an AI into acting. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server sees only the tool call a model already chose, never the prompt behind it. Permissions still bound what a hijacked call can do, and a call that reaches execution is still on record. That is containment, not defense, and the two are easy to mix up.</p>
<p><strong>Deletion leaves a residue.</strong> Deleting an organization removes the workspace and its credentials, but three stores stay behind: the audit history (each record ages out under the log server's 90-day retention, counted from when it was written), analytics events and the credential service's connector configuration rows. The deletion response names them. If your obligation is total removal, test that gap first. <a href="/security/">Elaichi's security page</a> is where to check all of this against your own requirements.</p>
<h2 id="where-does-the-money-land-either-way">Where does the money land either way?</h2>
<p>Moving early costs seats and a setup you did not strictly need yet. Moving late costs a reconstruction job, and only that one comes with a deadline.</p>
<p>Elaichi is a paid product with two plans, Gold and Black, and no unpaid tier. Gold lists at $15 per user per month in US dollars. Paid yearly, it is $120 per user. At that list price, five seats come to $75 a month, spent on a problem that has not arrived. That is the honest reason to wait for a signal.</p>
<p>The late bill looks different. Someone has to work out which of four accounts an agent touched, from logs that were never written, for a reviewer who wants an answer this week. That work costs more than the seats would have.</p>
<p>Checking is cheap either way. Gold comes with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Let a trial lapse and the workspace pauses instead of disappearing: plan-gated features lock and nothing is deleted. Confirm current figures on <a href="/pricing/">the pricing page</a> before you budget. Visitors in some countries see a regional price there, in their own currency.</p>
<h2 id="what-is-a-simple-rule-for-deciding">What is a simple rule for deciding?</h2>
<p>Stay with per-user connectors and SSO while the inventory test passes. You can name everyone who has connected an assistant, every account they reach is federated, and nobody outside the team needs an answer. Move when any one of these becomes true:</p>
<ol>
<li>A second AI client or a second team starts connecting accounts.</li>
<li>The team holds more accounts than it has people, and agents can write to them.</li>
<li>A departure leaves a grant you cannot list, usually on an account the IdP never owned.</li>
<li>Someone who is not the operator has to answer for what agents can reach or did.</li>
</ol>
<p>All four are the same failure underneath: an inventory question with no register to query. One is enough to start looking, though none of them obliges you to buy anything.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>When the signals are there, the setup guides take Claude, ChatGPT and Cursor through it one client at a time.</p><a href="/blog/category/setup/" class="cta-button">See the setup guides</a></aside>
<h2 id="where-do-you-start-when-you-outgrow-per-user-connectors">Where do you start when you outgrow per-user connectors?</h2>
<p>Start small: one team, one AI client and the accounts that team already uses. Three pages cover most of what you need before deciding.</p>
<ul>
<li><a href="/blog/connect-elaichi-to-chatgpt/">Connecting ChatGPT to one endpoint</a> walks through a first rollout, from what the admin adds to what each person sees at first sign-in. The same address then serves Claude and Cursor.</li>
<li>For cost, <a href="/pricing/">the plans and seat prices</a> page is the current source, including regional prices and trial terms.</li>
<li>If your automations already run in Zapier, <a href="/blog/zapier-mcp-alternative/">the Zapier MCP comparison</a> sets out when Zapier MCP is the shorter path. It also covers when one organization endpoint fits better.</li>
</ul>
<p>To check coverage first, the <a href="/connectors/">connector catalog</a> lists the 600+ connectors that Elaichi serves, most of them its own work and the rest vendors' own MCP servers. The <a href="/use-cases/">team pages</a> show the order in which one team is usually set up. If none of the four signals has fired yet, none of this is urgent, and the setup you already run is the right one.</p>
<h2>FAQ</h2><dl><dt><strong>When do you not need an MCP gateway?</strong></dt><dd>You do not need one while three things hold. You can name every person who has connected an AI assistant to a company system. Every account those assistants reach is owned by your identity provider. And nobody outside the team has to answer for what the assistants did. Per-user connectors in the AI client plus an SSO policy then give you central sign-in, MFA, session revocation and permission inheritance, which is most of what a control plane adds. The gap is a register of which grants exist. It starts to cost you when a second AI client or team arrives, when accounts outnumber people, when a departure leaves a grant nobody can list, or when an outside reviewer asks what agents did.</dd><dt><strong>Does deprovisioning a user in your identity provider revoke their AI assistant's access to SaaS?</strong></dt><dd>It revokes SSO sign-in, which is not the same thing. An OAuth grant that a person authorized from their own AI client is a separate object with its own refresh cycle. And any account that was never federated, such as a shared vendor portal login or a personal workspace, is outside the identity provider's reach entirely. In Elaichi the two are tied together when SCIM drives membership: a deprovision suspends the member, and removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call with no cache, so the cut holds from the next call. Role and restriction changes are slower and take effect within about two minutes.</dd><dt><strong>Do I need an MCP control plane if only one person uses AI at work?</strong></dt><dd>No. If one person connects one account they already own, in one AI client, a control plane governs nobody new. The app's own roles are the restriction, and the app's own log names the one human involved. The answer changes when a second AI client, a second account or an outside reviewer appears.</dd><dt><strong>Does a compliance reviewer need a paid Elaichi seat to read the audit trail?</strong></dt><dd>No. The Auditor role is a free seat and is excluded from the billable count, along with Guest and Billing Admin. Auditor is read-only and lacks the tool:execute permission, so the seat can review the audit trail but cannot call any tool.</dd><dt><strong>Does Elaichi have an unpaid tier?</strong></dt><dd>No. Elaichi has two plans, Gold and Black, and both are paid. Gold's list price is $15 per user per month or $120 per user per year in US dollars, and visitors in some countries see a regional price in their own currency on the pricing page. Gold comes with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Billable seats are active memberships, with a minimum of one. Suspended members and the free-seat roles, which are Guest, Billing Admin and Auditor, are excluded from the count. If a trial ends without checkout, the workspace pauses and nothing is deleted, so subscribing picks up where it left off.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>Lock AI agent tool arguments, like a wire&apos;s payee</title>
      <link>https://elaichi.ai/blog/frozen-parameters-wire-transfer-receiver/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/frozen-parameters-wire-transfer-receiver/</guid>
      <description>Lock AI agent tool arguments with frozen parameters: Elaichi removes the field from the model&apos;s schema and writes your value over whatever the call sends.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi locks AI agent tool arguments with frozen parameters, which are values an admin sets on one tool inside a toolbox. A frozen field is removed from the schema the AI client receives, so the model cannot set it, and the frozen value is written over the caller's arguments at execution, so sending the field anyway changes nothing. Entry defaults lose to caller arguments, and both lose to frozen values.</aside>
<h2 id="how-do-you-lock-ai-agent-tool-arguments">How do you lock AI agent tool arguments?</h2>
<p>You lock AI agent tool arguments in Elaichi with frozen parameters. An admin sets a value on one tool inside a toolbox. Elaichi then leaves that field out of the schema the model is shown, and at execution it writes the admin's value over whatever the call contains. The model still composes the call. The admin composes the part nobody gets to argue about, such as the account a payment goes to.</p>
<p>A finance analyst opens Claude and asks it to wire this month's payroll funding. The payment tool takes a source account, a payee account, an amount, a currency and a memo. The amount and the memo are the analyst's to decide. The two accounts are not. The controller settled them once, and a language model should not re-decide them on a Tuesday.</p>
<p>The payment tool here is an illustration. Its field names are invented to show the mechanic, and they do not describe any bank's or payment provider's real API. The same mechanic applies to a CRM owner field, a support macro or a reporting workspace ID.</p>
<p>Payments make the case sharply, because where the money goes is exactly what payment fraud tries to change. <a href="https://www.ic3.gov/PSA/2024/PSA240911">The FBI's Internet Crime Complaint Center</a> describes business email compromise as a scam aimed at people who make legitimate transfer-of-funds requests. Its September 2024 announcement puts exposed losses from the scam at about $55.5 billion between October 2013 and December 2023. Its first prevention tip is to verify requests to change account information through a second channel. An agent that reads email can be handed exactly that kind of request.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A toolbox is a named set of tools assembled once and shared with people. In the <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a>, every tool carries an <code>inputSchema</code>, a JSON Schema that defines the arguments it expects. That schema is how the model learns which fields to fill.</p>
<h2 id="how-do-frozen-parameters-work">How do frozen parameters work?</h2>
<p>A frozen parameter is a fixed value attached to one field of one toolbox entry, and it does two things. Elaichi removes the frozen field from the tool's schema before any client sees it. At execution, Elaichi merges the frozen value over the caller's arguments, so the caller cannot change it.</p>
<p>Technically, it is a per-entry map over the tool's flattened argument space. Both qualifiers matter.</p>
<p>Per-entry means the lock belongs to one toolbox entry, not to the tool in the abstract. An entry pairs one tool with one connection, and a connection is one connected account of one app. The same payment tool can appear twice in an organization. One copy sits in a sandbox toolbox with a test payee locked in, and the other in a payables toolbox with the real payroll account. Freezing is a property of the pairing, so the two never mix.</p>
<p>Flattened means every argument is addressable by its dot path, however deep it sits. A top-level field such as <code>currency</code> can be frozen. So can <code>payee.account_id</code>, and so can a field three levels deep. That matters when the field you care about is nested, as the payee is in this example.</p>
<h2 id="why-doesnt-the-model-see-a-frozen-field">Why doesn't the model see a frozen field?</h2>
<p>Because Elaichi takes frozen fields out of the tool's schema before the client receives it. The schema is the argument shape the endpoint hands a client when the client lists tools. If <code>payee.account_id</code> is frozen, it is not in that shape. The model is not asked to fill it and cannot set it. The tool's description carries a note, such as "(frozen: payee.account_id=acct_payroll)", so the model can see that the field is locked, and often the value, but it has nothing to change.</p>
<p>That removes a duller failure as well. A model handed a field it cannot work out from the conversation may invent a value, or stop and ask the user for one. Both are bad outcomes on a payment. Leaving the field out of the schema leaves only the inputs the caller can actually supply.</p>
<p>This is the shape OWASP recommends in its guidance on <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">excessive agency</a>. It advises avoiding open-ended extensions in favor of ones with narrower functionality, and it names indirect prompt injection among the common triggers. A payment tool with an open payee field is open-ended in the one field that decides where money goes. Locking that field narrows the tool without anyone writing a new one.</p>
<p>The lock survives tool search. In Elaichi, connected tools are never listed one by one, however few there are. The model looks them up with <code>search_tools</code>, which returns the same reduced schema, and calls them through <code>execute_tool</code>. That second step only adds a layer of naming. Elaichi unwraps it to the same tool and arguments, and the call meets the same checks as any other.</p>
<p>Search also decides how the tool gets found. Ranking is purely lexical over the tool name, its description and the connector label. The word <code>frozen</code> is dropped from description tokens, because every frozen tool carries it as scaffolding. The frozen values themselves stay searchable on purpose. The reasoning, including the minimum score a match needs, is in <a href="/blog/search-tools-ranking-floor-idf/">how tool search is scored</a>.</p>
<h2 id="which-value-wins-when-the-model-sends-one-anyway">Which value wins when the model sends one anyway?</h2>
<p>The frozen value wins, every time. The order is short and runs one way:</p>
<pre><code>entry defaults  &#x3C;  caller/model args  &#x3C;  frozen params
</code></pre>
<p>Entry defaults are conveniences. An admin sets <code>currency</code> to <code>USD</code> so nobody has to type it on every call. The caller may change it, and being changeable is the whole point of a default.</p>
<p>Caller and model arguments are whatever arrives in the call. They beat defaults, and they carry the analyst's actual request as the model expressed it.</p>
<p>Frozen parameters are applied last and win outright. This is enforcement on the server, which is where the MCP specification puts it: servers <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">must validate all tool inputs</a> and implement proper access controls. Here is one illustrative payment call resolved against all three layers:</p>
<table>
<thead>
<tr>
<th>Argument</th>
<th>Entry default</th>
<th>Model sent</th>
<th>Frozen</th>
<th>Executed</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>amount</code></td>
<td>none</td>
<td><code>48210.00</code></td>
<td>none</td>
<td><code>48210.00</code></td>
</tr>
<tr>
<td><code>currency</code></td>
<td><code>USD</code></td>
<td>none</td>
<td>none</td>
<td><code>USD</code></td>
</tr>
<tr>
<td><code>memo</code></td>
<td><code>Payroll funding</code></td>
<td><code>October payroll</code></td>
<td>none</td>
<td><code>October payroll</code></td>
</tr>
<tr>
<td><code>source.account_id</code></td>
<td>none</td>
<td>none</td>
<td><code>acct_operating</code></td>
<td><code>acct_operating</code></td>
</tr>
<tr>
<td><code>payee.account_id</code></td>
<td>none</td>
<td><code>acct_7731</code></td>
<td><code>acct_payroll</code></td>
<td><code>acct_payroll</code></td>
</tr>
</tbody>
</table>
<p>Read the <code>currency</code> row first: nobody overrode the default, so it stands. The <code>memo</code> row shows the caller beating a default. The source row shows a frozen field the model was never asked to fill and never sent. The last row is the frozen case that matters. Something in the model's context asked for a different payee. The analyst may have typed it, or it may have arrived in an email claiming the payroll provider had changed banks. The model can emit a field the schema never advertised. Elaichi merges the frozen value over it, and <code>acct_payroll</code> is what leaves the system. Sending the field cannot unlock it. The instruction can be written, and it cannot take effect.</p>
<h2 id="how-do-you-lock-the-payee-on-a-payment-tool">How do you lock the payee on a payment tool?</h2>
<p>Work in this order, because each step assumes the one before it. Pick whichever payments connector your finance team runs, such as <a href="/connectors/airwallex/">Airwallex</a>. Read the real field names from that tool's schema, not from this example.</p>
<ol>
<li>Connect the account once, from the account of someone who will stay responsible for it, and do not share the connection itself with the finance team. Credentials do not live in Elaichi. Each account's secrets sit in a separate credential service, encrypted at rest with AES-256-GCM, and that service owns token refresh. A failed refresh marks the connection <code>needs_reauth</code> instead of failing quietly.</li>
<li>Create the toolbox entry by pairing the payment tool with that connection. This is the object the lock attaches to, and the entry records you as the person who vouches for it.</li>
<li>Freeze the fields that are policy rather than input, here the payee account and the source account. Write them as dot paths, exactly as they appear in the tool's flattened arguments. Leave amount and memo alone, because those are the analyst's job.</li>
<li>Share the toolbox, not the connection, with the finance team, at <code>use</code>. The team then runs the payment tool only through the entry. The connection is absent from their own tool list, and they cannot open or share it. Sharing works the same way everywhere: you grant view, use or edit on one resource to a person, a team or everyone in the organization.</li>
<li>List tools from a real client and read the schema back. The frozen field should be absent from the schema, not present with a value. If you can still see it, the freeze is on a different path than the one the tool uses.</li>
<li>Check that nobody on the team holds the connection itself. Anyone with <code>use</code> on it, directly or through a team or organization share, can call the payment tool unfrozen. Remove that share rather than writing a restriction, because a block on the payment tool withholds the frozen entry too. Revoking a share takes effect on the next call.</li>
<li>Run one real payment and open the audit log. Confirm the entry names the connection you expected. Then check the payee in the payments app itself, because the log records the one path argument that names the object, as the target id, and nothing else about the arguments.</li>
</ol>
<h2 id="when-does-locking-an-argument-make-the-tool-worse">When does locking an argument make the tool worse?</h2>
<p>When the field genuinely varies. A frozen parameter buys certainty by removing range, and it is easy to overpay.</p>
<p>Lock the payee and the entry can only ever pay that account. For payroll funding or a monthly tax payment, that is exactly right. For an accounts payable team paying sixty suppliers, it is wrong. Sixty locked entries means sixty near-identical tools competing in a lexical ranking, and the model has to choose between them on name and description alone. In that case, leave the payee open and restrict the operation to the roles that should hold it. Verify any change to a supplier's bank details through a second channel, and read the audit trail.</p>
<p>There is a second case where a frozen parameter is the wrong answer. If nobody should ever send payments from an assistant, do not lock the payee. Block the operation. A locked argument on a tool that should not be reachable at all is a decision made one layer too late.</p>
<h2 id="what-doesnt-a-locked-argument-protect-against">What doesn't a locked argument protect against?</h2>
<p>It does not make the endpoint safe against prompt injection. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. Freezing removes one argument from the set an injected instruction can influence. It does not stop the model from calling a tool it is permitted to call, with amounts it is permitted to choose. Other protections do hold on the endpoint: per-operation permission checks, the <code>forbidden</code> tool class, output redaction, OAuth scope limits and an audit row for each call that reaches execution.</p>
<p>It does not replace a restriction either, and the two can collide. Frozen parameters bind an entry. Restrictions bind a target, which is a role or a user, and Elaichi checks them at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file, on toolbox entries as well as direct calls. So a block on the payment tool withholds the frozen entry too. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. If a member can connect their own account to the same app, calls through that account bypass the entry, and no restriction can stop them without stopping the entry as well. Keep payment credentials with the people who run payments, and treat the entry as the shape of the call rather than the gate on it.</p>
<h2 id="what-does-the-audit-log-show-after-a-locked-call">What does the audit log show after a locked call?</h2>
<p>It shows that the call happened and which account it went through, not what was in the payload. The audit log holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Elaichi reads the recorded connection from the call as it ran, not from what was asked for. After an unexpected change, that is the first thing you want to know.</p>
<p>For each call that reaches execution, the entry captures the operation and tool, the connection and how the call was classified. It also records whether the call was approved, how it ended and, on a failure, an error code. Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. So the log tells you which payments account the agent used, and it does not tell you which payee was in the body. A call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. The client is recorded rather than guessed.</p>
<p>A failed call produces two error messages. The caller gets one built from the third party's response. The audit trail gets a separate one that never draws on the request or the response. Audit records are visible across the organization, and Elaichi's in-product assistant can read them. Keeping the two apart means a third party's error text never leaves through the log.</p>
<h2 id="what-happens-to-a-locked-entry-when-someone-leaves">What happens to a locked entry when someone leaves?</h2>
<p>Removal and suspension cut access on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's <code>revoked_at</code> field is re-read on every call. Changing a role or a restriction is slower. It waits on a 60-second cache and then on the edge network, so allow about two minutes.</p>
<p>The offboarding preflight lists every connection the departing member owns. A private connection a shared toolbox relies on blocks the removal, and the fix is to transfer it to one other active member or delete it. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. A connection is never handed to the organization, to a team, or to the admin running the removal. A shared connection the team still depends on is deleted only if you explicitly ask for that, so transfer it to someone who is staying and every grant on it stays as it was. Delegated toolbox entries show up as a warning that does not block the removal, and re-pinning the entry clears it. The contractor version is in <a href="/blog/offboarding-when-the-agent-holds-access/">what to do the day access ends</a>.</p>
<h2 id="when-can-you-skip-frozen-parameters">When can you skip frozen parameters?</h2>
<p>When every argument on a tool is genuinely the caller's business, freezing is configuration that buys nothing. A team of six with one payments account, one workspace and read-heavy tools gets most of the value from the audit trail alone. The same holds early in a rollout, while the list of connected apps is short enough to keep in your head. The wider version of that argument is in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting on a gateway</a>.</p>
<p>There is also the case where the routing logic already lives somewhere else. If an internal service already picks the payment account from rules in your code, point the connector at that service and let it decide. You then own and run that service, which is a real cost. The shape of that bill is in <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">self-hosted versus managed</a>.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Before a team relies on this, the security page sets out how Elaichi holds credentials, shares access and attributes each call to a person.</p><a href="/security/" class="cta-button">Open the security overview</a></aside>
<h2 id="how-do-frozen-parameters-fit-with-roles-and-restrictions">How do frozen parameters fit with roles and restrictions?</h2>
<p>Frozen parameters are the narrowest control in the stack, and they answer a different question from the layers above them. Permissions decide which actions a member may take, with exactly one role per member. Resource sharing decides what a member can see at all. Restrictions decide which connectors and which individual tools a target may reach. Frozen parameters decide what a permitted call must contain.</p>
<p>That ordering is why the payment case works. The analyst keeps the tool. The controller keeps the payee. Neither has to trust the model's judgment about where the money goes.</p>
<p>For the same layering on a revenue team, read the <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Salesforce rollout walkthrough</a>. More on roles, restrictions and the trail sits under <a href="/blog/category/governance/">governance</a>, and the per-team sequences are under <a href="/blog/category/team-playbooks/">team playbooks</a>. To see which apps you can lock arguments on, browse the <a href="/connectors/">connector catalog</a> or the <a href="/use-cases/">team use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>How do I stop an AI agent from changing a tool argument?</strong></dt><dd>In Elaichi, freeze the argument on the toolbox entry. A frozen field is removed from the schema the AI client receives, so the model cannot set it. At execution, the frozen value is written over whatever the caller sends. Any argument can be frozen by its dot path, including nested ones such as payee.account_id. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</dd><dt><strong>Can a model override a frozen parameter by sending the field anyway?</strong></dt><dd>No. Frozen values are merged over caller arguments at execution, so a model that sends the field regardless of the schema still executes against the frozen value. Entry defaults lose to caller or model arguments, and both lose to frozen parameters, which are applied last.</dd><dt><strong>Which wins in Elaichi: a default, the model's value or a frozen value?</strong></dt><dd>The frozen value. Entry defaults lose to caller or model arguments, and both lose to frozen parameters. A default is a convenience the caller may change. A frozen parameter is policy the caller cannot change, because it is merged in last on every execution of that toolbox entry.</dd><dt><strong>Do frozen parameters stop prompt injection?</strong></dt><dd>No. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees a user prompt, so it cannot apply that gate. Freezing removes one argument from the set an injected instruction can influence, which limits the damage rather than preventing the attack. The endpoint still enforces per-operation permissions, the forbidden classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution.</dd><dt><strong>Does the audit log record the frozen value that was used?</strong></dt><dd>No. Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. Each entry records which operation and tool ran, through which connection, how it was classified, whether it was approved and how it ended, with an error code on failure. The recorded connection comes from the call as it ran, not from the request, so the log answers which account was used rather than which value was in the body.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Ironclad contracts in ChatGPT, signing blocked</title>
      <link>https://elaichi.ai/blog/legal-team-chatgpt-ironclad-contracts/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/legal-team-chatgpt-ironclad-contracts/</guid>
      <description>Legal reads Ironclad contracts in ChatGPT through Elaichi. The connector has no signing or approval tool, and a role rule blocks launching or cancelling.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi serves Ironclad to ChatGPT through one organization-wide MCP endpoint, so a legal team can list and read contract workflows, each member signed in as themselves. The catalog's Ironclad connector has no tool that approves a step or sends a contract for signature. Block rules on the legal role keep its writes, launching or cancelling a workflow and deleting a user, out of reach, and a rule change takes about two minutes to take effect.</aside>
<h2 id="what-can-legal-do-with-ironclad-contracts-in-chatgpt">What can Legal do with Ironclad contracts in ChatGPT?</h2>
<p>Legal can find and read Ironclad contracts in ChatGPT through Elaichi. With one block on the legal role, nothing asked there can push a contract toward signature. The first requests are reads: which vendor agreements are still in review, who launched the MSA for a given counterparty, how far along a renewal is. Elaichi's <a href="/connectors/ironclad/">Ironclad connector</a> answers them from Ironclad's workflows. The <code>list_all_ironclad_workflows</code> and <code>get_single_ironclad_workflow_by_id</code> tools return each contract's title, template, current step, status and the values entered for its fields.</p>
<p>The requests that arrive in week two are different in kind. Send this version out for signature. Approve the step so the deal closes today. Those change the world outside the company, because a counterparty receives the result. Elaichi's Ironclad connector has no tool that approves a step or sends a signature packet. It sits in the <a href="/connectors/category/e-signature/">e-signature category</a>, and its few writes are what Legal blocks.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected account through one organization-wide MCP endpoint, <code>POST /mcp</code>, and ChatGPT reaches Ironclad through it. In ChatGPT, full MCP support with write actions is a beta on Business, Enterprise and Edu plans (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help article</a>, as of October 2026). On those plans, an admin creates the app under Workspace settings > Apps and publishes it to the workspace. Pro users can connect with read and fetch permissions only, in developer mode. Each lawyer then signs in with their own grant, and <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a> walks through the steps.</p>
<h2 id="why-does-the-setup-start-with-a-rule-not-a-connection">Why does the setup start with a rule, not a connection?</h2>
<p>Because the default is allow-all. A restriction is a rule about which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Sharing Ironclad with Legal and configuring nothing is a decision, not a neutral starting point. The Ironclad user behind the connection carries whatever rights that user has, and a model driving it inherits all of them. Write the rules first and share the connection second.</p>
<p>Every lawyer's call through a shared connection reaches Ironclad as the connection's owner, so Ironclad scopes results to that one user and its own log names that user. Share it only if that user's Ironclad access fits all of Legal; otherwise have each lawyer connect their own account.</p>
<p>Learn precedence once before you write anything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Use the role rule for the team posture, and use a user rule only to narrow one person. A lawyer who needs a tool the role blocks files an access request instead, and an admin approves it for that person alone.</p>
<h2 id="which-ironclad-tools-should-legal-block">Which Ironclad tools should Legal block?</h2>
<p>Block all four writes the connector carries: <code>create_a_ironclad_workflow</code> and <code>create_a_ironclad_async_workflow</code>, which launch a workflow, <code>ironclad_workflows_cancel</code>, which cancels one, and <code>delete_a_ironclad_user_by_id</code>, which deletes an Ironclad user. The reads stay open.</p>
<p>Launching is the one that matters for signing. In Ironclad, a workflow "consists of a contract and all the business processes needed to execute it, such as approvals and signatures" (<a href="https://support.ironcladapp.com/hc/en-us/articles/24858534941079-Workflows-Overview">Ironclad's help center</a>). The same article says "Once all approvals have been collected, a signature packet is prepared". The connector cannot approve a step or send that packet, so through it, a launch is the only road from ChatGPT toward signature. Block the launch tools, and that road is closed.</p>
<p>Signing can also start outside Ironclad. If <a href="/connectors/docusign/">DocuSign</a> is connected too, <code>create_a_docusign_envelope</code> can send an envelope the moment it creates one, and <code>update_a_docusign_envelope_by_id</code> can send a draft. Block both on the same legal role, and the promise holds across apps.</p>
<p>Two shapes are available. A block list names the few tools you refuse and lets new read tools keep working as the Ironclad connector gains them. The cost is that a write the connector gains later is open until someone blocks it. An allowlist names the reads you want and denies the rest, which is stricter and needs upkeep every time Legal asks for one more report. Within each layer, allow rules union, block rules union, and blocks always beat allows.</p>
<p>One trap catches people. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is the strictest rule you can express, and it is almost always written by accident.</p>
<h2 id="does-a-renamed-tool-get-around-the-rule">Does a renamed tool get around the rule?</h2>
<p>No. A block matches the name or the operation, and an allow matches the operation, so renaming a tool changes neither.</p>
<p>A rule is written against a connector and a tool, and the canonical resource and method are pinned against the catalog at write time. A block matches on the tool name or the pinned operation. An allow matches the pinned operation only. Whoever edits the connector's documentation can change a tool's advertised name, so the name is a token the governed party controls. Governance binds the operation, never the label.</p>
<p>For Legal the consequence is small and specific: write "do not launch" as a block, not as the absence of an allow. The full argument is in <a href="/blog/block-matches-name-allow-matches-operation/">the case for matching blocks on names and allows on operations</a>.</p>
<h2 id="what-does-legal-see-in-chatgpt-once-ironclad-is-connected">What does Legal see in ChatGPT once Ironclad is connected?</h2>
<p>No Ironclad tool by name. In Elaichi, connected tools are never listed one by one, however few there are. ChatGPT finds an Ironclad tool with <code>search_tools</code> and calls it through <code>execute_tool</code>. Elaichi's own control-plane operations stay listed individually, and <code>search_tools</code> never returns one.</p>
<p>A restricted tool is withheld from the tool list and cannot be called. Once Legal's block is saved, a search for <code>create_a_ironclad_workflow</code> names it, flagged restricted, with no schema.</p>
<p>Search also has a relevance floor, so a lawyer looking for a clause tool gets nothing rather than something from an unrelated app. The reasoning is in <a href="/blog/search-tools-ranking-floor-idf/">the relevance floor in search_tools</a>.</p>
<h2 id="which-ironclad-arguments-should-legal-freeze">Which Ironclad arguments should Legal freeze?</h2>
<p>Often none, while Legal only reads. Frozen parameters matter the day you open a write. They are a per-entry map over a tool's flattened argument space, set on a toolbox entry (one tool tied to one connected account). A frozen key is removed from the schema ChatGPT is shown. A frozen value is merged over the caller's arguments at execution, so passing the key cannot un-freeze it.</p>
<p>Suppose legal ops wants ChatGPT to start NDAs and nothing else. Build a toolbox with the reads and <code>create_a_ironclad_workflow</code>, and freeze that entry's <code>template</code> argument to your NDA template. Ironclad's API calls that field "The identifier of the workflow template" (<a href="https://developer.ironcladapp.com/reference/launch-a-new-workflow">Ironclad's API reference</a>), and the template identifiers come from <code>list_all_ironclad_workflow_schemas</code>. The lock binds only calls made through the entry. Share the toolbox with Legal in place of the Ironclad connection, and only then lift the block on <code>create_a_ironclad_workflow</code>, keeping the one on the async launch. That reopens one road toward signature, through Ironclad's own Review step and the reviewers your administrator configured, so decide it on purpose.</p>
<h2 id="where-does-the-ironclad-credential-live">Where does the Ironclad credential live?</h2>
<p>Not in Elaichi. A separate credential service holds per-account secrets, encrypted at rest, and owns refresh. A failed refresh marks the connection <code>needs_reauth</code> rather than failing silently.</p>
<p>Ironclad is one of the connectors where you bring the OAuth app. The <a href="/connectors/ironclad/">Ironclad connector page</a> asks an admin, once, for the client ID and secret of an app registered in Ironclad. OAuth is the sign-in standard that lets a client act for a user without holding their password. The accepted body is <code>client_id</code>, <code>client_secret</code> and scopes, so anything shaped like an endpoint is unrepresentable. It is gated on <code>connector:manage</code>, not <code>connection:manage</code>, so everyone who can delete a connection does not quietly gain the power to repoint the organization's OAuth app.</p>
<h2 id="does-the-compliance-reviewer-need-a-paid-seat">Does the compliance reviewer need a paid seat?</h2>
<p>No. Auditor is a free, read-only seat in Elaichi, so a reviewer who only reads the audit log does not use a license.</p>
<p>Auditor sits off the role chain, and it lacks <code>tool:execute</code>. That permission gates the whole MCP endpoint ahead of every scope. Without it, <code>tools/list</code> comes back empty and a call returns an in-band error naming the missing permission. An Auditor cannot reach Ironclad at all, even where a restriction would allow the tool.</p>
<p>A working lawyer sits on Member and sees only what they own or what was explicitly shared with them. Billable seats are active memberships, with Guest, Billing Admin and Auditor excluded. Gold lists at $15 per user per month in USD, or $120 per user per year, and <a href="/pricing/">the pricing page</a> shows the price in your region.</p>
<h2 id="what-does-the-audit-trail-show-after-an-unexpected-change">What does the audit trail show after an unexpected change?</h2>
<p>The trail holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Every entry records the Ironclad account the call reached, taken from what executed rather than from what was asked.</p>
<p>The <code>actor_kind</code> field is recorded, not inferred. Its values include <code>user</code>, <code>system</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from ChatGPT is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named, and ChatGPT is marked verified. Each record also carries the operation and tool, the connection, the classification and whether the call was approved, with its outcome and an error code only.</p>
<p>The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments, so clause text a lawyer pushed through a tool does not reach the log pipe. The error text it stores is never derived from Ironclad's response either, because audit records are visible across the organization and readable by the in-product assistant.</p>
<p>The trail is append-only, newest-first and filterable by text, category, actor and time. It is eventually consistent, so a row may take a moment to appear. The trail inside Elaichi is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog.</p>
<h2 id="how-fast-do-changes-land-and-what-happens-when-a-lawyer-leaves">How fast do changes land, and what happens when a lawyer leaves?</h2>
<p>A role or restriction change in Elaichi takes effect within about two minutes, on the MCP endpoint, the console and REST alike.</p>
<p>Grant revocation, member removal and suspension take effect on the next call instead. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>Joiners can come through SCIM v2 with group-to-role mapping. Adding a lawyer to the legal group in your identity provider then creates the member and assigns the role that already carries the Ironclad blocks. Invites, verified-domain auto-join and just-in-time SSO are the other three paths.</p>
<p>Offboarding runs a preflight. It lists every Ironclad connection the departing lawyer owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until it is transferred to another active member, never to the admin running the removal. A private connection nothing else depends on cannot be transferred and is deleted with the lawyer. A shared connection Legal still depends on is left untouched unless the admin deletes it, so transfer it to a lawyer who is staying and every grant on it stays as it was. The same sequence for short-term staff is in <a href="/blog/offboarding-when-the-agent-holds-access/">contractor offboarding AI access</a>.</p>
<h2 id="can-a-clause-in-a-contract-steer-chatgpt">Can a clause in a contract steer ChatGPT?</h2>
<p>It can try, and the endpoint never sees the attempt. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees a user prompt, so a clause drafted to read like an instruction is just text as far as the endpoint is concerned.</p>
<p>The endpoint does enforce role permissions per operation, redacted output, limits set by OAuth scopes, and an audit row for each call that reaches execution. A tool classified <code>forbidden</code> is reachable under no scope at all.</p>
<p>Client prompts are a second, weaker layer. The MCP specification says a person should always be able to deny a tool call (<a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a>). OpenAI's article adds that "For write or modify actions, ChatGPT may ask for confirmation" (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help center</a>). "May" is not a control you can show an auditor. The block on launching is, which is why it carries the weight here rather than any filter on what a document says.</p>
<h2 id="which-region-should-legal-choose-before-the-first-contract">Which region should Legal choose before the first contract?</h2>
<p>Choose before you create the organization, because the region is fixed then. Elaichi has three regions, EU, US and APAC. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region. Pick the region that matches where your contracts and your counsel sit.</p>
<h2 id="why-not-use-ironclads-own-mcp-server">Why not use Ironclad's own MCP server?</h2>
<p>Ironclad's own MCP is the simpler path if Ironclad is the one app Legal will query. Ironclad says it "now connects with ChatGPT, Claude, and Slackbot via MCP" (<a href="https://ironcladapp.com/resources/articles/mcp-integrations">Ironclad's MCP announcement</a>, checked October 2026). Its page adds that "Results are scoped to each user's permissions". That is Ironclad's own permission model applied per user, with no second vendor in the path.</p>
<p>Elaichi's case is the rest of Legal's stack. One address serves Ironclad, DocuSign and <a href="/connectors/salesforce/">Salesforce</a>, in ChatGPT, Claude and Cursor alike. The block on launching and on sending envelopes is written once for the legal role and covers every app it names. A frozen argument, such as a fixed template, holds a value the model cannot change. One audit trail spans every app Legal reaches, and one removal ends a departing lawyer's access through Elaichi to all of them. Their accounts inside each app are a separate step. Ironclad's page does not describe those cross-app controls, and they are what a second vendor has to earn.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Every Ironclad tool a rule can name is on the Ironclad connector page, along with each client's setup.</p><a href="/connectors/ironclad/" class="cta-button">Browse the Ironclad tools</a></aside>
<h2 id="when-does-a-legal-team-not-need-any-of-this">When does a legal team not need any of this?</h2>
<p>One lawyer, one Ironclad login, read-only rights on that login, and no reviewer asking who did what. Then a restriction layer is overhead, and Ironclad's own MCP or the client's built-in connector is enough. The threshold arguments are in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when an MCP gateway is still premature</a> and in <a href="/blog/elaichi-vs-native-ai-connectors/">the comparison with native AI connectors</a>.</p>
<p>The picture changes when a second client appears, when the Ironclad account can launch workflows, or when somebody has to produce an attributable record. It also changes if the alternative is running MCP servers yourself, which is costed out in <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">self-hosted MCP servers versus a control plane</a>. For the same playbook in another team, read <a href="/blog/sales-team-chatgpt-salesforce-accounts/">how a sales team gets governed Salesforce access from ChatGPT</a>. More governance writing sits under <a href="/blog/category/governance/">governance</a>, the 600+ connectors are in the <a href="/connectors/">connector catalog</a>, and the per-team starting points are on <a href="/use-cases/">use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Legal read Ironclad contracts in ChatGPT without being able to send them for signature?</strong></dt><dd>Yes. Elaichi's Ironclad connector has no tool that approves a workflow step or sends a contract for signature. Its writes launch or cancel a workflow and delete a user, and block rules on the legal role keep all of them out of reach while search and reads stay open. If DocuSign is connected as well, block its envelope-sending tools on the same role.</dd><dt><strong>Why not use Ironclad's own MCP instead of Elaichi?</strong></dt><dd>If Ironclad is the only app Legal queries, Ironclad's own MCP is the simpler path. Ironclad says it connects with ChatGPT, Claude and Slackbot, with results scoped to each user's permissions. Elaichi adds one address across Ironclad and Legal's other apps, one set of role rules and one audit trail across all of them, frozen arguments, and one removal that ends access through Elaichi to all of them.</dd><dt><strong>Does the audit log show which Ironclad account an agent reached?</strong></dt><dd>Yes. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the account the call actually reached, taken from the execution rather than from the intent, plus the operation and tool, the classification, whether the call was approved, its outcome and an error code only. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments, so contract text passed as an argument does not land in the log.</dd><dt><strong>Does a compliance reviewer need a paid seat to read the audit log?</strong></dt><dd>No. Auditor is a free, read-only seat in Elaichi, and it is excluded from the billable seat count along with Guest and Billing Admin. An Auditor lacks the tool:execute permission that gates the whole MCP endpoint, so tools/list comes back empty for that member and a tool call returns an in-band error naming the missing permission. Billable seats are on Gold, which lists at $15 per user per month in USD.</dd><dt><strong>Is an MCP endpoint protected against instructions hidden in contract text?</strong></dt><dd>No, and it cannot be, because an MCP server never sees a user prompt. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. The endpoint still enforces permissions per operation, the forbidden classification, redacted output, scope limits on each grant and audit logging. For contract workflows, the control you rely on is a block on the tools that launch or cancel, not a filter on what a document says.</dd><dt><strong>What happens to a lawyer's personal Ironclad connection when they leave?</strong></dt><dd>Elaichi runs a preflight before removal. It lists every connection the departing lawyer owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until it is transferred to another active member, never to the admin running the removal. A private connection nothing else depends on cannot be transferred and is deleted with the lawyer. A shared connection the team still depends on is left untouched unless the admin deletes it, so transfer it to someone staying and every grant on it stays as it was.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Employees pasting customer data into AI</title>
      <link>https://elaichi.ai/blog/shadow-ai-coo-customer-emails-pasted/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/shadow-ai-coo-customer-emails-pasted/</guid>
      <description>No single log records employees pasting customer data into AI. Measure it from three partial sources, report a range, and remove the reason to paste.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Employees pasting customer data into AI leave partial traces in three places: network and endpoint telemetry, the source system's own audit log, and QA screen recordings. None of them records every paste, so the defensible answer to a COO is a range with the blind spots named. Elaichi removes most of the reason to paste by serving governed tool access through one organization-wide MCP endpoint, where each connected-tool call that reaches execution is recorded with the account actually reached.</aside>
<p>No single system records employees pasting customer data into AI. Network logs see the destination, the helpdesk sees an ordinary read, and QA recordings catch the act one screen at a time. The defensible answer to "how much?" is a range from one team and one week, with the blind spots named. The fix that lasts is giving the approved assistant governed access to the system the data came from, so the copy step has no purpose.</p>
<p>It usually starts in a quality review. A COO watches one support recording: a ticket on the left and a chat assistant on the right. For forty seconds the agent copies the account history across to get a cleaner reply. Nothing in the clip is malicious. It is the fastest route to a good answer, and the question afterwards is about scale, not about that agent.</p>
<h2 id="where-does-the-evidence-of-employees-pasting-customer-data-into-ai-actually-live">Where does the evidence of employees pasting customer data into AI actually live?</h2>
<p>In three places on your side, and none is complete. The network edge sees traffic leaving a managed device. The source system's audit log sees the read that produced the data. Human artifacts such as QA recordings, tickets and internal chat see the act itself.</p>
<p>Each source covers a blind spot in the other two, and none records the paste as an event with a customer identifier attached. The network sees an encrypted request, the helpdesk sees an agent doing their job, and the recording sees one agent on one day.</p>
<p>A fourth source exists only when the paste went into a company workspace. OpenAI's help center says <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">user conversations are available in its Compliance API</a> for ChatGPT Enterprise and Edu customers. A paste into a personal account shows up in none of these. Any number you report is an estimate assembled from partial views, and saying so is more defensible than false precision.</p>
<h2 id="what-can-a-qa-screen-recording-prove">What can a QA screen recording prove?</h2>
<p>That the behavior exists, and why. It proves nothing about volume.</p>
<p>From one clip you learn which fields moved, which assistant received them, which step was slow, and what the agent was avoiding doing by hand. That tells you what to fix, because the fix is usually a missing capability rather than a missing policy.</p>
<p>A recording cannot scale. Coverage is whatever share of interactions QA reviews, sampled for coaching rather than measurement. It also captures the managed desktop and nothing else: if the agent picks up a personal phone, the clip shows a person looking down. Use recordings as the qualitative source, never as the denominator.</p>
<h2 id="why-do-network-logs-undercount-the-paste">Why do network logs undercount the paste?</h2>
<p>Network controls see devices and networks you administer, and they see destinations more readily than content. A secure web gateway logs a connection to an assistant provider and the volume of traffic. The session is encrypted with TLS, so the payload stays hidden unless the gateway decrypts it.</p>
<p>TLS inspection is the usual answer, and it is expensive. Microsoft's own guide warns that many mobile apps pin their certificates, which <a href="https://learn.microsoft.com/en-us/entra/global-secure-access/concept-transport-layer-security">"prevents successful TLS inspection"</a> and ends in failed handshakes. It also raises a privacy question once an employee signs into a personal account on the same network. Even where it works, a paste inside an HTTPS session is hard to tell apart from typing.</p>
<p>Blocking the domain has a second problem. A blocked paste is often a redirected one, to a device you do not manage, so the undercount grows as enforcement tightens. When the device was never yours, the <a href="/blog/offboarding-when-the-agent-holds-access/">contractor offboarding playbook</a> is the better starting point.</p>
<h2 id="can-endpoint-dlp-or-a-browser-extension-catch-the-paste">Can endpoint DLP or a browser extension catch the paste?</h2>
<p>On a managed device in a supported browser, often yes. Microsoft Purview's <a href="https://learn.microsoft.com/en-us/purview/endpoint-dlp-learn-about">Endpoint DLP</a> can audit or block a paste into a restricted site, and it evaluates the pasted content itself rather than the file it came from. Where it is deployed, endpoint DLP (data loss prevention that runs on the device) is the closest thing to a paste counter.</p>
<p>Its limits are coverage and shape. Purview's <a href="https://learn.microsoft.com/en-us/purview/dlp-learn-about-dlp">DLP overview</a> lists keywords, regular expressions, validation functions and machine learning among its matching methods. A card number has a shape those methods catch well. An account history or an angry email thread has no fixed shape, so whether it trips a rule depends on how well a classifier was trained. None of it runs on a device you do not manage. <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">What a CASB and DLP see of AI agents</a> covers the network side in more depth.</p>
<p>Browser extensions that read the assistant's text box are the other common control, and they are brittle. Assistant vendors ship frontend changes often, and one renamed element breaks the script. Users also move to the desktop app, where the extension never ran. Treat both controls as partial coverage, not as a census.</p>
<h2 id="does-the-source-systems-audit-log-show-the-paste">Does the source system's audit log show the paste?</h2>
<p>No. The read that fed the assistant was legitimate, and the log has no field for what happened next.</p>
<p>Your helpdesk or CRM records that a named user viewed or exported a record at a time, the same entry you would see with no assistant involved. Bulk exports deserve a review, because an export outside a role's normal pattern is a real signal. The paste that matters is usually small and repeated: one account at a time, dozens of times a day, shaped exactly like work. To use the source system as evidence, build per-role volume baselines and a comparison period, and expect a weak signal.</p>
<h2 id="why-do-employees-paste-customer-data-in-the-first-place">Why do employees paste customer data in the first place?</h2>
<p>Because the approved tool cannot see what they need. Support agents work against handle-time targets, sales reps need an account summarized before a call, and an assistant reads faster than a person does. When the approved assistant cannot see the system of record, people bridge the gap by hand. The clipboard is the only bridge available, and it is the one surface nobody governs.</p>
<p>Training still has a place. The OWASP Top 10 for LLM applications lists <a href="https://genai.owasp.org/llmrisk/llm022025-sensitive-information-disclosure/">sensitive information disclosure</a> as LLM02:2025, and says users need to understand the risk of unintentionally providing sensitive data. Its mitigations include teaching people what not to enter. Education reduces the careless paste. It does not close a capability gap, and a ban leaves the gap in place while moving the traffic somewhere you cannot see.</p>
<h2 id="how-do-you-measure-it-in-a-way-you-can-defend">How do you measure it in a way you can defend?</h2>
<p>Run it on one team for one week, then report a range with the blind spots named. A bounded estimate that states its own coverage survives a board question. A single confident percentage does not.</p>
<ol>
<li>Pick the team with the most customer data in front of it, usually support or billing, and fix one week so every source covers the same period.</li>
<li>Re-watch that week's existing QA sample and count the clips where data moves from a company system into an assistant. Note which fields moved, which assistant received them, and whether it was a company workspace or a personal account.</li>
<li>Pull read and export counts for that team and week from the source system's own audit log, and compare them with the same week a quarter earlier.</li>
<li>Ask each AI vendor's admin surface what it reports for your workspace, and write down what it does not report.</li>
<li>Give the COO a range derived from the QA rate, plus an explicit list of the surfaces none of the sources can see.</li>
</ol>
<p>The account each paste went into matters as much as the count, because the vendors' terms differ by plan. OpenAI's <a href="https://openai.com/enterprise-privacy/">enterprise privacy page</a> says it does not train on business data from ChatGPT Business, Enterprise or Edu by default. Anthropic's <a href="https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training">privacy center</a> says the same of commercial products such as Claude for Work, unless someone sends feedback or otherwise opts in. A Team or Enterprise owner can stop members sending that feedback with the Rate chats setting, under Organization settings, Data and Privacy, as of October 2026. Neither commitment covers a personal account signed in on the same laptop.</p>
<h2 id="how-does-governed-access-remove-the-reason-to-paste">How does governed access remove the reason to paste?</h2>
<p>It gives the assistant the read the agent was doing by hand. The agent in the recording copied data because the assistant could not see the ticket. When the assistant can read the ticket through a governed call, the copy step has no purpose.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi connects each SaaS account once and serves its tools through one organization-wide MCP endpoint, <code>POST /mcp</code>. The endpoint sits behind OAuth, the standard sign-in that issues each person a grant instead of a shared token. An admin adds that address once where the client allows it, and each person then connects and signs in with their own grant. In ChatGPT, <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">full MCP with write actions is a beta</a> on Business, Enterprise and Edu as of October 2026, and an admin creates and publishes the app. The <a href="/blog/connect-elaichi-to-chatgpt/">ChatGPT setup guide</a> has the steps.</p>
<p>Elaichi serves 600+ connectors and authors most of them on its own infrastructure. The helpdesk the agent needs, such as the <a href="/connectors/zendesk/">Zendesk connector</a>, is something Elaichi maintains rather than a server your team runs.</p>
<p>Anthropic draws the same line between a paste and a tool read on its consumer plans. Its <a href="https://privacy.claude.com/en/articles/10023580-is-my-data-used-for-model-training">privacy article</a> says the chat data it may use to improve models excludes raw content from connectors, including remote MCP servers. Data copied straight into the conversation can still be included.</p>
<h2 id="where-does-the-credential-sit-while-the-model-works">Where does the credential sit while the model works?</h2>
<p>Outside Elaichi, and outside the chat window. Connector credentials live in a separate credential service that holds per-account secrets, encrypted with AES-256-GCM at rest, and owns the refresh cycle. A failed refresh marks the connection <code>needs_reauth</code> rather than failing quietly.</p>
<p>A connect URL is a one-time session that carries no token, which is why it is safe to return over MCP. The model never receives an API key, so there is no key for anyone to paste into a prompt.</p>
<h2 id="how-do-you-limit-which-tools-the-assistant-can-reach">How do you limit which tools the assistant can reach?</h2>
<p>With restrictions: rules for which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>A block can match a tool's name. An allow matches only the operation recorded with the rule, because anyone editing the connector can change a displayed name. <a href="/blog/block-matches-name-allow-matches-operation/">Block on the name, allow on the operation</a> explains why. Frozen arguments go further. An admin fixes a value on a tool entry; the model cannot change it, and anything the caller sends for it is overridden. Role and restriction changes take about two minutes to take effect. Grant revocation, member removal and suspension apply on the next call.</p>
<h2 id="what-does-the-audit-trail-answer-that-a-recording-cannot">What does the audit trail answer that a recording cannot?</h2>
<p>Which account was reached, by whom, with what operation, and through which client. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection on each entry is the account the call actually reached, taken from the execution rather than the intent. That is the first thing to check when two helpdesk accounts are connected and something changed in one of them.</p>
<p>Each entry also carries the operation, the classification, whether the call was approved and its outcome. It records the one path argument that names the object, as the target id, and nothing else about the arguments, so the ticket body does not get copied into the log while you are trying to stop it being copied into a prompt. The <code>actor_kind</code> field stores who acted, and its values include <code>ai_assistant</code>, which marks the Elaichi Agent. A call from Claude or ChatGPT is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</p>
<p>A compliance reviewer reads all of it on a free read-only Auditor seat, which cannot run tools. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon. The post on <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must record</a> covers the rest of each entry.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Before a team relies on this, the security page sets out how Elaichi holds credentials, shares access and attributes each call that runs to a person.</p><a href="/security/" class="cta-button">Open the security overview</a></aside>
<h2 id="what-does-this-not-fix-and-when-should-you-wait">What does this not fix, and when should you wait?</h2>
<p>A governed endpoint does not stop a person from pasting. Someone who wants to drop an account history into a personal assistant on a personal phone is outside every control described here. Data that lives in no connected system, such as a PDF attached to a customer email, still gets pasted, because no tool call would reach it. One more limit applies: The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call.</p>
<p>If you have one small team, three people using assistants and no compliance request in front of you, this decision can wait. The case for <a href="/blog/when-you-dont-need-an-mcp-gateway/">holding off on a gateway</a> is real, and the cheaper move is to close the capability gap the QA recording exposed. When you are ready for the governed version, the <a href="/connectors/">connector catalog</a> and the <a href="/use-cases/">twelve team playbooks</a> show what that agent's workflow looks like under audit. More on the same problem sits in <a href="/blog/category/shadow-ai/">shadow AI</a>, and the rollout order team by team is in the <a href="/blog/category/team-playbooks/">playbooks category</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can you measure how much customer data employees paste into AI assistants?</strong></dt><dd>Not exactly. The behavior leaves partial traces in three places: network or endpoint telemetry on managed devices, the read and export entries in the source system's own audit log, and human artifacts such as QA screen recordings. A company AI workspace may add its own record, but a personal account adds nothing. The defensible output is a range derived from a QA sample for one team and one week, reported alongside an explicit list of surfaces none of the sources can see, such as personal phones and photographed screens.</dd><dt><strong>Can network logs detect when an employee pastes customer data into an AI prompt?</strong></dt><dd>Rarely. Traffic to an assistant provider is encrypted with TLS, so a secure web gateway records the destination and the volume, not the content, unless it decrypts the session. TLS inspection breaks certificate pinning in some applications and raises privacy questions when employees use personal accounts on the same network. Even with inspection, a paste inside an HTTPS session is hard to tell apart from typing. Endpoint DLP on a managed device is the better instrument for the paste itself.</dd><dt><strong>Does blocking pastes into ChatGPT solve the problem?</strong></dt><dd>It protects the devices you manage and pushes the rest out of sight. On a managed laptop, a managed browser or endpoint DLP can audit or block a paste into a known assistant site, and that is real protection. A personal laptop, a phone on cellular or a photographed screen leaves no record. A block is therefore not always a prevented disclosure, and the undercount grows as enforcement tightens. Giving the assistant governed read access to the system of record changes the incentive rather than the route.</dd><dt><strong>Does ChatGPT or Claude train on customer data employees paste in?</strong></dt><dd>Not by default on business plans. OpenAI says it does not use business data from ChatGPT Business, Enterprise or Edu for training by default. Anthropic says it will not use inputs or outputs from commercial products such as Claude for Work to train its models by default, unless someone sends feedback or otherwise opts in. Those commitments cover the company workspace. A paste into a personal account falls under that product's consumer terms instead.</dd><dt><strong>What does Elaichi record when an AI assistant reads a customer record?</strong></dt><dd>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records who acted, the operation and tool, the classification, whether the call was approved, its outcome, and the account actually reached, taken from the execution rather than the intent. For arguments it records the one path argument that names the object, as the target id, and nothing else about the arguments. The actor_kind field stores who acted, with values including user, scim, api_token and ai_assistant, which marks the Elaichi Agent. A call from Claude or ChatGPT is recorded under the person who signed in, with the client named.</dd><dt><strong>How quickly does a restriction change take effect in Elaichi?</strong></dt><dd>A role or restriction change takes about two minutes to take effect, on the MCP endpoint, the console and the REST API alike. Three changes apply on the next call instead: OAuth grant revocation, member removal and suspension, because the grant is checked on every single call. During an incident, suspend the member rather than editing a rule.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>Zapier MCP alternative for a whole company</title>
      <link>https://elaichi.ai/blog/zapier-mcp-alternative/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/zapier-mcp-alternative/</guid>
      <description>Elaichi is a Zapier MCP alternative: one organization endpoint with role restrictions and an audit log. What each costs, and when Zapier fits.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi is a Zapier MCP alternative that serves connectors it mostly authors from one organization-wide MCP endpoint, with restrictions on a role or a user and an audit entry for each call that reaches execution. Zapier MCP connects each member's AI client to a Zapier account and spends two plan tasks per successful call, while Elaichi is priced per seat. Zapier is the shorter path if your team already runs on Zapier and call volume is modest. Elaichi fits when Claude, ChatGPT and Cursor need one place to manage who may reach what, instead of a server per member per client, and a removal that takes effect on the next call.</aside>
<h2 id="zapier-mcp-or-one-organization-endpoint-which-design-fits-your-team">Zapier MCP or one organization endpoint: which design fits your team?</h2>
<p>Your company wants Claude, ChatGPT and Cursor to work with the apps you already pay for. Before you compare features, you choose a design. Zapier MCP connects an AI client to a Zapier account, and each member signs in as themselves. Elaichi is a Zapier MCP alternative built on a different design. It offers one organization-wide endpoint. An endpoint is the web address a client connects to. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. OAuth is the sign-in method where a person approves access in their browser without sharing a password. The saved record of that approval is a grant. On Elaichi's endpoint the address never changes, and the grant is what varies from person to person.</p>
<p>Both designs are governed. Zapier applies its app and action restrictions to MCP and records tool calls in a History tab. The difference is where control lives. With Zapier, it lives in a Zapier account and its apps. With Elaichi, it lives in connectors that Elaichi serves, with restrictions written against a role or a user. Three questions decide between them: what happens when a person leaves, who may reach what, and what the bill counts as usage grows.</p>
<p><em>Disclosure: Elaichi is the vendor, so its claims here are self-reported and current as of publication. Where a number matters to your decision, check the <a href="/security/">security page</a> or the <a href="/pricing/">pricing page</a>.</em></p>
<h2 id="what-does-zapier-mcp-give-each-person">What does Zapier MCP give each person?</h2>
<p>Each person gets access to the apps connected on their own Zapier account. In most MCP clients, the member adds Zapier as a connector and signs in from inside the client. Zapier creates and sets up the server during that sign-in. Clients that are not on Zapier's list, and code you write yourself, use a connection token instead. Zapier describes that token as long-lived, tied to one server, and good for anyone who holds it. Zapier says to treat it like a password (Zapier, <a href="https://docs.zapier.com/mcp/get-started/quickstart">MCP quickstart</a> and <a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>, checked September 2026).</p>
<p>That design is coherent for the reader it is built for. Someone who already automates work in Zapier gets tools backed by apps already connected there, with no second system to set up.</p>
<p>The address is shared, and the server is not. Every client connects to the same Zapier URL, and Zapier's docs go on: "Each MCP client gets its own MCP server: one for Cursor, one for Claude, one for ChatGPT." For token-based clients, Zapier's docs add: "give each user their own server and token rather than sharing one" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>, checked October 2026). In an organization rollout, an admin acts in the MCP client, and each member still signs in to Zapier as themselves. Admins can limit members to a Zapier workspace, and Zapier's app and action restrictions apply to MCP (Zapier, <a href="https://docs.zapier.com/mcp/manage/rollout/overview">organization rollout</a> and <a href="https://docs.zapier.com/mcp/manage/security">security and governance</a>, checked September 2026). So "what can Sales reach" is answered by how that Zapier account is set up. The trade-off is that the tool layer, the restrictions and the History belong to Zapier accounts. Your AI clients may also reach apps that are not in Zapier at all.</p>
<h2 id="how-do-zapier-mcp-and-elaichi-compare-side-by-side">How do Zapier MCP and Elaichi compare side by side?</h2>
<p>They differ most on where control lives, what happens when someone leaves, and what the bill counts.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Zapier MCP</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>How a person signs in</td>
<td>OAuth from inside most clients; a connection token for code-based clients</td>
<td>OAuth from inside the client</td>
</tr>
<tr>
<td>What exists per member</td>
<td>A Zapier MCP server per client, on one shared URL</td>
<td>One OAuth grant per client, against one organization server</td>
</tr>
<tr>
<td>Whose accounts the tools run against</td>
<td>The app connections on that member's Zapier account</td>
<td>Accounts connected once in Elaichi, shared to a person, a team or the organization by a grant</td>
</tr>
<tr>
<td>Where "what can Sales reach" is written</td>
<td>Zapier's app and action restrictions and workspace settings</td>
<td>A restriction written against the role or a user</td>
</tr>
<tr>
<td>How it follows your identity provider</td>
<td>Enterprise SAML SSO extends to MCP access</td>
<td>SAML and OIDC SSO, SCIM v2 for users and groups, and group-to-role mapping, on Gold</td>
</tr>
<tr>
<td>Where the record of calls lives</td>
<td>A History tab with user-level activity logs</td>
<td>The Elaichi audit log, on Gold; export to your own Datadog with the Black plan, launching soon</td>
</tr>
<tr>
<td>Where the connectors come from</td>
<td>Zapier's apps and actions, the same ones Zaps use</td>
<td>Connectors authored, maintained and served by Elaichi</td>
</tr>
<tr>
<td>What use is counted in</td>
<td>Two tasks per successful tool call, from the plan's allowance</td>
<td>Seats: Gold lists at $15 per user per month in USD</td>
</tr>
<tr>
<td>What happens when a member leaves</td>
<td>Not stated on Zapier's MCP security page</td>
<td>The next call is refused</td>
</tr>
<tr>
<td>Where the data is stored</td>
<td>AWS US-East 1</td>
<td>EU, US or APAC, chosen at creation. For EU and US, the data store and org-scoped request execution stay in that jurisdiction. APAC is best-effort placement, not a residency guarantee. The audit trail sits in one EU log instance</td>
</tr>
</tbody>
</table>
<p>The Zapier column follows Zapier's own pages, checked September 2026, with the per-member row re-checked in October 2026 on <a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>. The last two rows come from its <a href="https://docs.zapier.com/mcp/manage/security">MCP security page</a>. The identity row comes from that same page, checked October 2026.</p>
<h2 id="what-happens-to-ai-access-when-someone-leaves">What happens to AI access when someone leaves?</h2>
<p>On Elaichi, the next call from a departed person's AI client is refused. Revoking access is a write to the grant record, not a hunt through each person's servers.</p>
<p>Every call is checked against the OAuth grant, not against the address it was sent to. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Elaichi re-reads the revocation flag from the organization store on every single call, with no cache. That holds whichever client made the call, and suspension works the same way. There is no per-user MCP server to find and remove.</p>
<p>Role membership and restriction changes are slower. They resolve through a 60 second cache plus edge propagation. So they take effect within about two minutes, on MCP, in the console and over REST alike. Write that window into the change ticket. Confirm the current numbers against the <a href="/security/">security page</a> before they go into a compliance document.</p>
<p>Zapier's MCP security page does not state what happens to a member's own server when that member leaves the Zapier account (<a href="https://docs.zapier.com/mcp/manage/security">MCP security</a>, checked September 2026). Put that question to Zapier before rollout, and keep the answer in writing. For Elaichi's side, <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding a member with MCP connections</a> gives the order of steps.</p>
<h2 id="how-does-each-design-follow-your-identity-provider">How does each design follow your identity provider?</h2>
<p>Elaichi reads your directory through SSO and SCIM on the Gold plan. Zapier documents SAML SSO for MCP access on Enterprise.</p>
<p>Elaichi has SAML and OIDC SSO built in-house, plus SCIM v2 for users and groups and group-to-role mapping. Those are Gold features. A SCIM group mapping can confer at most one role, and nothing else. SCIM never sets team membership, so people who join that way are added to teams afterward. A SCIM deprovision suspends the member rather than removing them. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Removing the member, with its offboarding preflight, is a separate step an admin takes in Elaichi.</p>
<p>Zapier's MCP security page states that Enterprise SAML SSO extends to MCP access (<a href="https://docs.zapier.com/mcp/manage/security">MCP security</a>, checked October 2026). What happens to a member's own server when that member leaves is not stated there, so ask Zapier.</p>
<h2 id="is-elaichi-a-zapier-mcp-alternative-for-the-whole-organization">Is Elaichi a Zapier MCP alternative for the whole organization?</h2>
<p>Yes, for teams that want one server and one place for policy. Elaichi serves one endpoint for the whole organization: <code>POST /mcp</code>. It uses standard <a href="https://modelcontextprotocol.io/specification">MCP</a> over Streamable HTTP with JSON-RPC 2.0. It is stateless, which means it keeps no session between calls, and it sits behind OAuth. There are no per-member servers or tokens to create, list or revoke.</p>
<p>Claude, ChatGPT and Cursor all use that one address. An admin adds it once where the client allows, and each member then connects and signs in with their own OAuth grant. Any other MCP client uses it the same way, so a fourth client does not fork the deployment.</p>
<p>Elaichi authors, maintains and serves most of the connectors behind that address from its own infrastructure, and the rest are vendors' own MCP servers it governs. There are 600+ of them as of publication, listed in the <a href="/connectors/">connector catalog</a>. Your company does not run MCP servers, and the endpoint is not a wrapper around an open registry.</p>
<p>Connector credentials are not held in Elaichi either. A separate credential service holds per-account secrets, encrypted at rest, and owns their refresh. A failed refresh marks the connection <code>needs_reauth</code>, meaning it needs a fresh sign-in, instead of failing quietly. Whatever you evaluate, ask what state a broken credential ends up in.</p>
<h2 id="how-does-elaichi-decide-who-may-reach-what">How does Elaichi decide who may reach what?</h2>
<p>Elaichi uses three separate layers: permissions, sharing and restrictions. Keeping them distinct is what makes each access question answerable.</p>
<p><strong>Permissions.</strong> Permissions say what a person may do in Elaichi: 58 action strings, grouped into roles, with exactly one role per member. The <code>tool:execute</code> permission gates the whole MCP endpoint ahead of every other check. Guest, Auditor and Billing Admin do not have it.</p>
<p><strong>Sharing.</strong> Sharing has one building block: a grant of <code>view</code>, <code>use</code> or <code>edit</code> on a resource to a user, a team or the whole organization. A member sees only what they own or what was explicitly shared with them. No organization-level permission silently widens a listing, owners and admins included.</p>
<p><strong>Restrictions.</strong> Restrictions decide which connectors and which individual tools a target may reach. In short, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A member is governed by their role's rules and by any rule aimed at them personally, and a tool is reachable only when both admit it. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema.</p>
<p><strong>A worked example.</strong> The Sales role carries one restriction: a block on the HubSpot "delete contact" tool. A rep named Priya needs bulk deletes for data cleanup. She files an access request, and an admin with <code>member:manage</code> approves it. Approval creates an access grant for Priya alone. The grant lifts exactly that tool out of her role rules, and every other Sales rep still hits the role block. Her other role rules keep applying, no rule is written and the role is not edited. A rule aimed at her personally could not do this, because a personal rule can only narrow what her role allows.</p>
<p>Two details matter when you write the first rule. First, note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Second, a block matches the tool name or the operation Elaichi pinned at write time, while an allow matches the pinned operation only. Whoever edits a connector's documentation can rename a tool, so <a href="/blog/block-matches-name-allow-matches-operation/">governance binds the operation, never the label</a>.</p>
<p>Zapier shares at a different grain. A Zapier MCP server can be shared on Team and Enterprise plans, with Owner, Editor and View only roles. Sharing is limited to members of the same Zapier account (<a href="https://docs.zapier.com/mcp/manage/server-access">server access</a>, checked September 2026).</p>
<h2 id="how-does-one-endpoint-handle-a-large-number-of-tools">How does one endpoint handle a large number of tools?</h2>
<p>In Elaichi, connected tools are never listed one by one, however few there are. The model finds them with <code>search_tools</code> and runs them with <code>execute_tool</code>. So the list a client sees stays short, however many accounts sit behind the address. The <code>execute_tool</code> call is only a naming indirection, with the same gates and no privilege of its own.</p>
<p>Ranking matches words, not meaning, and applies a relevance floor. A user with only Notion connected searched for a Cal.com tool and got back a Notion one, because the generic words scored. A tool from the app you did not ask about is worse than nothing, because the model calls it. The <a href="/blog/search-tools-ranking-floor-idf/">relevance floor, from first principles</a> covers the ranking.</p>
<h2 id="what-does-the-audit-log-answer-afterwards">What does the audit log answer afterwards?</h2>
<p>It answers who did what, through which account, and whether it worked. The audit log holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account actually reached, taken from the execution and not from the intent. That answers the first question after an unexpected change: which of two Notion workspaces the agent wrote to.</p>
<p>The <code>actor_kind</code> field is recorded, not inferred, and <code>ai_assistant</code> marks the Elaichi Agent. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named, and those three clients are marked verified. Each entry also carries the operation and tool, the classification, whether the call was approved, the outcome and an error code only. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments, so it cannot become a second place where secrets leak.</p>
<p>Audit and application logs share one record shape, so a single query answers what happened. Export forwards the trail to your own destination. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon (<a href="https://docs.datadoghq.com/logs/">Datadog's log docs</a>). <a href="https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector">Splunk HEC</a> and <a href="https://learn.microsoft.com/en-us/azure/sentinel/overview">Microsoft Sentinel</a> are accepted as destinations, but Elaichi delivers events only to Datadog.</p>
<p>Zapier MCP's record is a History tab with user-level activity logs for tool calls (<a href="https://docs.zapier.com/mcp/manage/security">MCP security</a>, checked September 2026). Ask whether it names the account reached when a member holds two accounts of the same app.</p>
<h2 id="what-do-zapier-mcp-and-elaichi-cost-as-headcount-grows">What do Zapier MCP and Elaichi cost as headcount grows?</h2>
<p>Zapier MCP is metered in tasks and Elaichi in seats, so the two costs grow on different axes. Zapier MCP has no separate charge. Each successful tool call uses two tasks from your Zapier plan's allowance, and a failed call uses none (<a href="https://docs.zapier.com/mcp/features/usage">MCP usage</a>, checked September 2026).</p>
<p>Run that number before rollout, because an assistant makes calls in bursts. One user question can turn into a search, two reads and a write, which is four successful calls and eight tasks. Take a hypothetical 50-person rollout where each person makes 20 successful calls a working day. That is 2,000 tasks a day, or about 44,000 over a 22-day month. Set that against the allowance your existing Zaps leave spare, not the plan's full total. Failed calls cost nothing, which helps while prompts are still being tuned.</p>
<p>Elaichi Gold lists at $15 per user per month in USD, or $120 per user per year, and the <a href="/pricing/">pricing page</a> shows the price for your region. At the list price, the same 50 people cost $750 a month on Gold, however many calls they make. There are two plans, Gold and Black, and a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Suspended members and the free-seat roles, Guest, Billing Admin and the read-only Auditor, are not billed. So seating a compliance reviewer does not cost a license.</p>
<p>As headcount grows, the seat bill grows with people. The task bill grows with people times calls per person, so it also climbs as each person leans on the assistant more. At low volume the comparison flips. Three people making ten calls each a month use 60 tasks on Zapier, but still cost three Gold seats, $45 a month, on Elaichi.</p>
<h2 id="what-are-the-limits-to-know-before-you-move">What are the limits to know before you move?</h2>
<p>Elaichi has two limits that belong in the body rather than a footnote. The endpoint has no prompt-injection gate, and deletion leaves three stores behind. After those two, check where the data lives.</p>
<p>Prompt injection means hidden instructions in text that trick an AI into acting. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. It cannot apply to <code>POST /mcp</code>, because an MCP server never sees a user prompt. What does hold on the endpoint is permission checks per operation and the <code>forbidden</code> classification, which no OAuth scope can reach. Output redaction, scope limits and an audit row for each call that reaches execution hold too. Anyone claiming this endpoint defends against injection is describing a different surface.</p>
<p>Organization deletion deletes the credentials and tears down the workspace, but it leaves three stores behind: the audit history (each record ages out under the log server's 90-day retention, counted from when it was written), analytics events and the credential service's connector configuration rows. Elaichi returns that leftover by name. If data-deletion rules apply to you, confirm the details directly with Elaichi.</p>
<p>An Elaichi organization picks its region at creation: EU, US or APAC. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. Every organization's audit trail, whatever its region, is stored in one log instance in the EU. Zapier states that Zapier MCP data is stored in AWS US-East 1. Its <a href="https://docs.zapier.com/mcp/manage/security">security page</a> also names the certification the service runs under (checked September 2026).</p>
<h2 id="when-is-zapier-mcp-the-right-choice">When is Zapier MCP the right choice?</h2>
<p>Zapier MCP is the right choice when your team already lives in Zapier. Use Zapier MCP when all of the following hold:</p>
<ul>
<li>Your team already builds in Zapier, and the apps you want to reach are already connected there.</li>
<li>The people who need access sign in to Zapier themselves. Zapier's own restrictions and History answer the access questions your reviewer asks.</li>
<li>The value you want is the automation platform itself, not just MCP access to your other tools.</li>
<li>Your task allowance absorbs two tasks per successful call at the volume you expect.</li>
</ul>
<p>Move to a governed, single-endpoint design when any of the following becomes true instead:</p>
<ul>
<li>Someone other than the user has to describe, change and prove access for more than one person. They need one place for it, across accounts that are not all in Zapier.</li>
<li>Offboarding is a recurring event, not a one-time setup.</li>
<li>A security or compliance reviewer needs to answer "what can this role reach" without interviewing each team member.</li>
</ul>
<p>There is a smaller case still: one app, three people, one client, and no reviewer asking questions. Neither Zapier MCP nor Elaichi earns its keep there, and <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for skipping a gateway for now</a> is the more useful read.</p>
<h2 id="how-do-you-sort-your-own-case-in-an-afternoon">How do you sort your own case in an afternoon?</h2>
<p>Most of the sorting comes down to whether the work is automation-shaped or client-shaped. Automation-shaped means the actions you want are the ones your Zaps already fire. Client-shaped means several AI clients need governed access to systems of record. Five desk checks settle which one you have.</p>
<ol>
<li>Count the AI clients your people use, and check each against Zapier's supported list. Anything outside it needs a connection token, which Zapier says to treat like a password (<a href="https://docs.zapier.com/mcp/get-started/quickstart">quickstart</a>, checked September 2026).</li>
<li>Estimate successful calls per person per working day, then multiply by two tasks and by headcount.</li>
<li>List the apps the assistant must reach. Check how many are already connected in Zapier, and how many are in Elaichi's <a href="/connectors/">connector catalog</a>. On Elaichi, every account is connected once, even one Zapier already holds.</li>
<li>Write down the offboarding path for one leaver in each design, and ask Zapier what becomes of that member's server.</li>
<li>Name who must answer "which account did the agent write to", and check that each record names it.</li>
</ol>
<p>If most answers point at Zapier, stay there. Otherwise, test both designs for two weeks.</p>
<h2 id="how-do-you-test-zapier-mcp-against-elaichi-in-two-weeks">How do you test Zapier MCP against Elaichi in two weeks?</h2>
<p>Run both against one team with a real workload, such as <a href="/use-cases/">support or finance</a>, and give each product the same five tasks. Two weeks fits inside Elaichi's trial, and a trial that ends without checkout pauses the workspace without deleting anything.</p>
<ol>
<li>Connect one shared business account in each product, and point the same MCP client at both.</li>
<li>Give three people access, and have each run the five tasks from their own client.</li>
<li>Block one destructive action in each product, and confirm from the client that it can no longer be called.</li>
<li>Remove a test member, and time from the client how long access keeps working.</li>
<li>Open each record and check the account reached, who called, and which client made the call.</li>
<li>Multiply the observed calls per person by your headcount, and price both bills at that volume.</li>
</ol>
<p>The <a href="/product/">product overview</a> describes the endpoint and console, and the <a href="/blog/category/governance/">governance posts</a> cover roles, restrictions and offboarding. If running your own servers is also on the table, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the real cost of self-hosting</a> covers that fork.</p>
<h2>FAQ</h2><dl><dt><strong>How does Zapier MCP differ from a single organization-wide MCP endpoint?</strong></dt><dd>Zapier MCP connects each AI client to a Zapier account. Every client uses the same URL, but each member gets a server per client, one for Claude, one for ChatGPT and one for Cursor, created when they sign in. Code-based clients use a connection token instead (Zapier, how connections work, checked October 2026). Elaichi serves one endpoint and one control plane for the whole organization: POST /mcp over Streamable HTTP, behind OAuth. Nothing is created per member except the OAuth grant. The tools are connectors that Elaichi authors, and restrictions and the audit log live in Elaichi, not in a Zapier account.</dd><dt><strong>If someone leaves the company, how fast does their AI client lose access?</strong></dt><dd>In Elaichi, it happens on the next call, because removing or suspending a member revokes every live grant in the same transaction as the membership change. Elaichi re-reads the revocation flag from the organization store on every call, with no cache, so the next request from any client is refused. Role and restriction changes are slower. They resolve through a 60 second cache plus edge propagation, and they take effect within about two minutes. Zapier's MCP security page does not say what happens to a departed member's server (checked September 2026), so ask Zapier before rollout.</dd><dt><strong>Does Zapier MCP cost extra on top of a Zapier plan?</strong></dt><dd>No. Zapier documents no separate billing for Zapier MCP. Each successful tool call uses two tasks from the plan's allowance, and a failed call uses none (Zapier, MCP usage, checked September 2026). Estimate calls per person per working day, multiply by two and by headcount, and compare the result with the allowance your automations leave spare. Elaichi is priced per seat instead. Gold lists at $15 per user per month in USD, however many calls each person makes.</dd><dt><strong>Is Zapier MCP ever the better choice?</strong></dt><dd>Yes. If your team already builds in Zapier, or one person is automating their own accounts, Zapier MCP reaches the apps already connected there with no second system. At low call volume, two tasks per successful call can also cost less than a seat per person. A separate control plane earns its place when you want one endpoint for every AI client, connectors that one vendor maintains, and who-may-reach-what described in one place instead of in each tool's own settings.</dd><dt><strong>What does a single MCP endpoint record about each tool call?</strong></dt><dd>Elaichi's audit log holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account actually reached, taken from the execution and not from the intent. Each record carries the operation and tool, the connection, the classification, whether the call was approved, the outcome, and an error code only. The log records the one path argument that names the object, as the target id, and nothing else about the arguments. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with the client named, as a recorded field and not a guess.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>CASB and AI agents: what each layer can see</title>
      <link>https://elaichi.ai/blog/casb-dlp-vs-governed-mcp-endpoint/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/casb-dlp-vs-governed-mcp-endpoint/</guid>
      <description>CASB and AI agents: a CASB sees who reached which AI service and how much data moved, but not which tool an agent ran or which account it changed.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A CASB sees AI agents from outside the call: who reached which AI service, from where, and what a sanctioned SaaS tenant reports afterwards. DLP reads content on the browsers, devices and networks it inspects. Neither records which operation an agent ran on which connected account, because that is settled where the call executes. Elaichi records it at the governed MCP endpoint, so the CASB stays the tool for discovery and content, and Elaichi becomes the record of what agents did.</aside>
<p>A CASB and AI agents meet at two edges: the employee's network path, and the SaaS tenant the CASB reads through an API. From those edges a CASB can tell you who reached which AI service, from where and when, and what the tenant logged afterwards. It cannot tell you which operation an agent ran, on which connected account, or whether the call worked. That record exists only where the call executes, which with a governed MCP endpoint is the endpoint itself.</p>
<p>Security asks for a report on what the AI agents are doing with company data. The CASB and the DLP tool both work as designed, and neither answers the question in that form. That is a difference in vantage point, not a defect. Most companies run both, so the work is deciding which one is the record for which question.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Everything below assumes an assistant that can act in your systems, not one that only chats.</p>
<h2 id="what-does-a-casb-see-when-someone-uses-an-ai-agent">What does a CASB see when someone uses an AI agent?</h2>
<p>A CASB sees sessions and tenant events, not tool calls. CASB stands for cloud access security broker: a control point that reads traffic to cloud services, reads a sanctioned SaaS tenant through its API, or both. Microsoft documents its own CASB, Defender for Cloud Apps, in enough detail to show all three vantage points.</p>
<p>Discovery reads the network. Defender's cloud discovery <a href="https://learn.microsoft.com/en-us/defender-cloud-apps/set-up-cloud-discovery">analyzes traffic logs from firewalls and proxies</a> against its catalog of cloud apps. Depending on the appliance, a log line gives it the app's URL and IP, the username, the origin IP and the bytes uploaded. That is enough to say who reached ChatGPT or Claude, from where, and how much data went up. The same page notes that by default it cannot discover an app missing from its catalog.</p>
<p>App connectors read the tenant. Defender's <a href="https://learn.microsoft.com/en-us/defender-cloud-apps/enable-instant-visibility-protection-and-governance-actions-for-your-apps">app connectors use each provider's APIs</a> to collect users, admin and user activity, and the tokens issued to third-party apps. They can also remove those tokens, though support varies by app. Where it exists, an MCP server holding an OAuth grant to your CRM shows up as an app with permissions. The CASB can see it and cut it off.</p>
<p>Session control proxies the browser. Defender's <a href="https://learn.microsoft.com/en-us/defender-cloud-apps/proxy-intro-aad">Conditional Access app control</a> puts browser sessions behind a reverse proxy and applies policy to interactive sign-ins. Its page says installed apps with noninteractive sign-in flows cannot be used with those access controls. A tool call that a server makes on an agent's behalf has no browser session to proxy.</p>
<h2 id="what-can-dlp-read-in-assistant-traffic-and-where-does-it-stop">What can DLP read in assistant traffic, and where does it stop?</h2>
<p>DLP reads content that passes through something it inspects. Microsoft Purview's <a href="https://learn.microsoft.com/en-us/purview/dlp-learn-about-dlp">DLP overview</a> describes matching on keywords, regular expressions, validation functions, nearby supporting matches and machine learning. It lists inline coverage for ChatGPT, Gemini, DeepSeek and Microsoft Copilot through Edge for Business and network integrations.</p>
<p>For a pasted prompt, this is the right layer. Purview's <a href="https://learn.microsoft.com/en-us/purview/endpoint-dlp-learn-about">Endpoint DLP</a> can audit or restrict a paste into a restricted service domain in a supported browser. It evaluates the pasted text itself, wherever it came from. An account list dropped into a chat window on a managed laptop is the case it was built for.</p>
<p>Content inspection stops in two places. It stops where the path is not inspected: an unmanaged device, a personal phone, or a client that never routes through the proxy. It stops again where the data never touches the device. A tool result carrying customer records into a model's context is an exchange between servers. The employee reads a summary, and the records never cross the link DLP watches.</p>
<h2 id="where-do-a-casb-and-ai-agents-cross-paths">Where do a CASB and AI agents cross paths?</h2>
<p>On at most two of the three hops a tool call takes, and never on the hop that reaches your SaaS app. Following one call from a prompt to a CRM shows where each control sits next to an MCP endpoint.</p>
<ol>
<li><strong>Employee to AI service.</strong> The browser or desktop app talks to ChatGPT, Claude or Cursor. This is the hop a CASB and DLP watch well: the destination, the person, the volume and, where inspected, the prompt.</li>
<li><strong>AI service to the MCP endpoint.</strong> Where this hop starts depends on the client. Claude's help center says <a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">custom connectors connect from Anthropic's cloud</a>, not from the user's device, on every Claude client. That hop never crosses your network. A client that runs on the device, such as Cursor, does cross it, to a single hostname.</li>
<li><strong>MCP endpoint to the SaaS app.</strong> The call leaves from Elaichi's infrastructure, to the CRM itself or, for a native MCP connector, to the vendor's own MCP server. No proxy on your network sees it. The CASB meets it again later, as an activity in the tenant's log under the connected account. If several people share that connection, the tenant log cannot say whose agent made the call.</li>
</ol>
<p>The current MCP specification gives an inspecting proxy more to read on the second hop. Its <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http">Streamable HTTP transport</a> sends every message as an HTTP POST to one endpoint. Clients must copy the method and the tool name into <code>Mcp-Method</code> and <code>Mcp-Name</code> headers, so intermediaries can inspect a request without parsing its body. Behind TLS, a proxy reads those headers only if it decrypts the session.</p>
<p>In Elaichi, the header names a wrapper, because connected tools are never listed one by one, however few there are. A model looks a tool up with <code>search_tools</code> and calls it through <code>execute_tool</code>. Where a client sends the header, it reads one of those two names for every connected app. The real tool name and its arguments travel in the JSON body. Even a proxy that parses the body learns only what the model asked for. Which account the call actually reached, and whether a rule stopped it, is settled inside Elaichi. The wrapper carries no privilege of its own, and <a href="/blog/context-window-problem-mcp-tools/">why connected tools stay unlisted</a> explains the design.</p>
<h2 id="what-does-a-governed-mcp-endpoint-record-for-each-call">What does a governed MCP endpoint record for each call?</h2>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry carries the operation and tool, the connection, the classification, whether the call was approved, its outcome and an error code. The connection recorded is the account the call actually reached, taken from the execution rather than from what the model asked for.</p>
<p><code>actor_kind</code> is a stored field, not an inference. Its values include <code>user</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks the Elaichi Agent. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. The client is written down when the call happens, not guessed later from a user agent string.</p>
<p>Arguments are where the endpoint deliberately sees less than DLP. The trail records the one path argument that names the object, as the target id, and nothing else about the arguments, so it will never tell you what text was in a field. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the full record and how to query it.</p>
<h2 id="where-do-a-casb-and-a-governed-endpoint-overlap">Where do a CASB and a governed endpoint overlap?</h2>
<p>On three fields: a person, a destination app and a time. Underneath those, they answer different questions from opposite ends of the same session.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>CASB and DLP</th>
<th>Governed MCP endpoint</th>
</tr>
</thead>
<tbody>
<tr>
<td>What it covers</td>
<td>Managed networks and devices, plus tenants it reads by API</td>
<td>Only what is connected to it</td>
</tr>
<tr>
<td>Unit of record</td>
<td>A session: user, service, volume</td>
<td>A call: operation, connection, outcome</td>
</tr>
<tr>
<td>Finds unsanctioned AI apps</td>
<td>Yes, that is its job</td>
<td>No, by design</td>
</tr>
<tr>
<td>Reads prompt text</td>
<td>Yes, where the path is inspected</td>
<td>No, never sees a user prompt</td>
</tr>
<tr>
<td>Names the tool and the account reached</td>
<td>No</td>
<td>Yes, per call</td>
</tr>
<tr>
<td>Records argument values</td>
<td>Yes, if visible</td>
<td>No, records the one path argument that names the object, as the target id, and nothing else about the arguments</td>
</tr>
<tr>
<td>What it can block</td>
<td>A destination, a session or an upload</td>
<td>A connector or one tool, for a role or a user</td>
</tr>
<tr>
<td>Sends records to your SIEM</td>
<td>Yes</td>
<td>Not on Gold: export to your own Datadog comes with the Black plan, which is launching soon</td>
</tr>
</tbody>
</table>
<p>The sharpest split is content. DLP can read the prompt. Elaichi stores no field contents, so it cannot say what was in a field. Whether somebody pasted a customer list into a chat window is a question for the CASB and DLP. Which connected account ran the delete, and whether it worked, is a question for the audit trail.</p>
<p>Coverage is the other split. A CASB sees every managed path, including clients nobody approved. The endpoint sees only what is connected to it. Treat the CASB as discovery and the endpoint as the record of authorized agent actions, and the two stop competing. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Two more destinations, Splunk HEC and Microsoft Sentinel, are accepted as destinations, but Elaichi delivers events only to Datadog.</p>
<h2 id="which-rules-can-only-be-enforced-at-the-tool-call">Which rules can only be enforced at the tool call?</h2>
<p>Any rule about what an account may do, rather than what a payload contains. "This role may read opportunities but may not run a delete" is not a pattern in a body of text. DLP cannot express it, and a CASB that blocks a hostname cannot either.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks beat allows. One trap catches people: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>Rules bind the operation, not the advertised label, because whoever edits a connector's documentation can rename a tool. A block matches either the tool's name or the operation recorded when the rule was written; an allow matches that operation only. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks and allows match differently</a> sets out the reasoning.</p>
<p>Frozen arguments go one step further. An admin fixes an argument's value on a tool entry, such as the account or the record type. The key disappears from the schema the model is shown, and the fixed value is merged over whatever the caller sends. Elaichi checks every rule at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<h2 id="what-can-neither-layer-stop">What can neither layer stop?</h2>
<p>Prompt injection: an instruction hidden in content the model reads. An MCP server never sees the user's prompt, so it has nothing to judge. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. Content inspection misses it too, because the instruction arrives inside a document or a tool result, not in anything the employee typed.</p>
<p>What holds on the endpoint is narrower and real. It enforces role-based permissions per operation, a <code>forbidden</code> classification that no OAuth scope can reach, output redaction, scope limits and audit logging of each call that reaches execution. The human check belongs to the client. The MCP specification says there <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">should always be a human in the loop</a> who can deny a tool call. <a href="https://cursor.com/docs/mcp">Cursor asks for approval</a> before using MCP tools by default, and <a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">ChatGPT may ask for confirmation</a> before a write.</p>
<p>Timing matters to an incident responder. A role or restriction change takes about two minutes to land. Grant revocation, member removal and suspension take effect on the next call. To cut access during an incident, suspend the person rather than editing a rule.</p>
<h2 id="when-is-a-casb-enough-on-its-own">When is a CASB enough on its own?</h2>
<p>If nobody has connected an AI client to a system of record, you do not need a control plane yet. Assistant use that is read, copy and paste is a content problem, and content inspection is the right instrument for it. A governance layer over traffic with no tool calls in it adds an address to maintain and answers nothing you were asked.</p>
<p>The signals that the balance has shifted are specific. Somebody requests an API key for an agent. A team wires an assistant to the CRM with a personal token. A manager switches on a connector that an admin console offers. At that point the action leaves the device, and <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting</a> runs out. Offboarding is usually where it bites first, which is the subject of <a href="/blog/offboarding-when-the-agent-holds-access/">what to revoke when a contractor leaves</a>.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page puts the credential model, sharing and per-person attribution in one place, written for the reviewer who signs off.</p><a href="/security/" class="cta-button">See the security page</a></aside>
<h2 id="how-do-you-run-both-without-two-versions-of-the-truth">How do you run both without two versions of the truth?</h2>
<p>Pick which system answers which question, then send both to one place. The failure mode is two partial records that disagree, and an auditor reconciling them by hand.</p>
<ol>
<li>Give each question one owner. Content inspection and unsanctioned apps go to the CASB and DLP. Authorized agent actions go to the control plane.</li>
<li>Plan for one SIEM. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon. That export filters by log type: no filter forwards everything, and an empty list forwards nothing.</li>
<li>Give the reviewer a free Auditor seat. Auditor is read-only and not billable, and it lacks <code>tool:execute</code>, so the MCP endpoint lists no tools for that account.</li>
<li>Choose the region before you need it. Elaichi has three regions, <code>eu</code>, <code>us</code> and <code>apac</code>, chosen when the organization is created. For <code>eu</code> and <code>us</code>, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region.</li>
<li>Write down the erasure gap. Deleting an organization tears down the workspace and deletes every connector credential. Three stores keep residue, and the deletion names them: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. Never call it total erasure.</li>
</ol>
<p>For which clients each plane covers, <a href="/blog/elaichi-vs-native-ai-connectors/">built-in assistant connectors compared</a> is the closer fit. The trail's controls are on <a href="/security/">the security page</a>, the 600+ connectors are in the <a href="/connectors/">catalog</a>, and team examples are in <a href="/use-cases/">use cases</a>. More on restrictions is filed under <a href="/blog/category/governance/">governance</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can a CASB see what an AI agent did in a SaaS app?</strong></dt><dd>Only part of it. A CASB reads network sessions and the activity a sanctioned SaaS tenant reports through its API. The tool call itself may never cross the employee's network: Claude, for example, reaches custom connectors from Anthropic's cloud. The tenant then logs the change under the connected account, which several people may share. An MCP control plane such as Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), recording the person, the account actually reached, the operation and the outcome.</dd><dt><strong>What does an MCP control plane log that DLP does not?</strong></dt><dd>The action rather than the content. Elaichi records the operation and tool, the connection used, the classification, whether the call was approved, its outcome and an error code. For arguments it records the one path argument that names the object, as the target id, and nothing else about the arguments. DLP works the other way around: it inspects content in its path, such as a prompt typed into a browser, and cannot express a rule about which operation an account may run.</dd><dt><strong>Do you still need DLP if you have an MCP control plane?</strong></dt><dd>Yes, for content on devices and networks. A control plane covers what is connected to it and records the calls that pass through it. It does not see somebody pasting a spreadsheet into a chat window on an unmanaged laptop, and Elaichi stores no field contents, so it will never report what text was in a field. Keep DLP and the CASB for content inspection and for discovering unsanctioned AI apps, and use the control plane as the record of authorized agent actions.</dd><dt><strong>Does Elaichi defend against prompt injection at the tool call?</strong></dt><dd>No. An MCP server never sees a user prompt, so it has no way to judge whether an instruction was injected. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds on the endpoint is role-based permissions per operation, a forbidden classification reachable under no OAuth scope, output redaction, scope limits and audit logging of each call that reaches execution. Content inspection does not catch injection either, because the instruction arrives inside content the model read.</dd><dt><strong>How fast does a restriction change take effect compared with revoking access?</strong></dt><dd>In Elaichi, a role or restriction change takes about two minutes to take effect. Grant revocation, member removal and suspension are effective on the next call, because the grant is checked on every call. During an incident, revoke the grant or suspend the member rather than editing a rule.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>Connect Elaichi to Cursor for a whole team</title>
      <link>https://elaichi.ai/blog/cursor-mcp-one-endpoint-vs-per-developer/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/cursor-mcp-one-endpoint-vs-per-developer/</guid>
      <description>To connect Elaichi to Cursor, add one URL to mcp.json or share it as a Team MCP server, and each developer signs in with OAuth. No API key.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To connect Elaichi to Cursor, each developer adds Elaichi's one organization-wide MCP endpoint, https://api.elaichi.ai/mcp, to Cursor's mcp.json and signs in with OAuth. A Cursor team admin can instead share it as a Team MCP server in the team marketplace. Developers then install it from Customize, and each one still signs in as themselves. After that, the developer's role, what is shared with them and any restrictions decide which tools Cursor can call.</aside>
<h2 id="what-does-it-take-to-connect-elaichi-to-cursor">What does it take to connect Elaichi to Cursor?</h2>
<p>To connect Elaichi to Cursor, add one URL, <code>https://api.elaichi.ai/mcp</code>, as a remote MCP server and sign in with OAuth. Each developer can add it to their own <code>mcp.json</code>, or a Cursor team admin can share it once as a Team MCP server. Either way there is no API key, no header and no per-developer URL.</p>
<p>An engineering team that adopts Cursor usually ends up with one JSON block per laptop. Each block points at a different server with its own token. Forty developers means forty copies of the wiring, and nobody holds a list of what they contain. One URL behind OAuth replaces the copies, because the address is the same for everyone and only the grant behind each sign-in differs.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Cursor speaks it, as do Claude and ChatGPT, and the <a href="https://modelcontextprotocol.io/specification/2026-07-28">specification</a> is public. Elaichi serves every connected SaaS account through one organization-wide endpoint, <code>POST /mcp</code>, behind OAuth.</p>
<h2 id="how-does-each-developer-add-elaichi-in-mcpjson">How does each developer add Elaichi in mcp.json?</h2>
<p>With a short entry that holds only the URL. Cursor reads MCP servers from <code>~/.cursor/mcp.json</code>, which applies in every project, or from a project's <code>.cursor/mcp.json</code>, which applies to that project (<a href="https://cursor.com/docs/mcp">Cursor's MCP docs</a>, checked October 2026).</p>
<pre class="shiki elaichi-terminal" style="background-color:#262420;color:#e6e1d8" tabindex="0"><code><span class="line"><span style="color:#928D84">{</span></span>
<span class="line"><span style="color:#928D84">  "</span><span style="color:#D7B46A">mcpServers</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">    "</span><span style="color:#D7B46A">elaichi</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> {</span></span>
<span class="line"><span style="color:#928D84">      "</span><span style="color:#D7B46A">url</span><span style="color:#928D84">"</span><span style="color:#928D84">:</span><span style="color:#928D84"> "</span><span style="color:#7BC496">https://api.elaichi.ai/mcp</span><span style="color:#928D84">"</span></span>
<span class="line"><span style="color:#928D84">    }</span></span>
<span class="line"><span style="color:#928D84">  }</span></span>
<span class="line"><span style="color:#928D84">}</span></span></code></pre>
<p>Add the entry alongside any servers already in the file. It has no <code>headers</code> block and no key in <code>env</code>. Cursor's docs say it "supports OAuth for servers that require it". Cursor registers itself with Elaichi as an OAuth client through dynamic client registration, the standard defined in <a href="https://www.rfc-editor.org/rfc/rfc7591">RFC 7591</a>, which Elaichi supports. So nobody pastes a client ID or a secret, and each developer authenticates to Elaichi as themselves.</p>
<p>A project file is safe to commit. It holds a public URL and nothing else, so every clone of the repository carries the same entry and no credential.</p>
<h2 id="can-a-cursor-admin-share-elaichi-with-the-whole-team">Can a Cursor admin share Elaichi with the whole team?</h2>
<p>Yes, as a Team MCP server, though each developer still installs it and signs in. Cursor's docs separate the two jobs: Team admins can distribute shared MCP servers, and Enterprise admins set MCP policy.</p>
<ol>
<li>Under <strong>Dashboard > Plugins &#x26; MCPs</strong>, configure Elaichi as a shared Team MCP server, using the URL above.</li>
<li>Under <strong>Team MCP Servers</strong>, select <strong>Add to Team Marketplace</strong>. That makes it available in Cursor's Agent Window, IDE and CLI.</li>
<li>Ask developers to install it from <strong>Customize</strong> and sign in.</li>
</ol>
<p>The docs are plain that a marketplace listing is an offer, not an install: linking a server to the marketplace installs and enables it for nobody. What an admin saves is the copying and the typos, not the sign-in. Every developer still authenticates as themselves, and that is the point, because each grant belongs to one person.</p>
<h2 id="what-changes-if-your-cursor-enterprise-org-runs-an-allowlist">What changes if your Cursor Enterprise org runs an allowlist?</h2>
<p>Add the Elaichi URL to it, or Cursor blocks the server. Enterprise admins choose which MCP servers and tools the team may run under <strong>Team Settings > MCP Configuration</strong>. Cursor's enterprise docs say that when an allowlist is active, "only servers matching an allowlist entry can run" (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor enterprise docs</a>, checked October 2026).</p>
<p>An allowlist approves a server but does not distribute it. The same page says that adding a server "does not push it to users' machines", so each team member still configures it in their own Cursor settings. Run the two together: the allowlist decides what may run, and the marketplace offers Elaichi to install.</p>
<p>The allowlist can name tools too, but it cannot see inside Elaichi. Every connected tool reaches Cursor through <code>execute_tool</code>, so a Cursor rule cannot tell a Jira read from a Jira delete. Write that distinction in Elaichi's restrictions instead.</p>
<h2 id="why-does-cursor-show-so-few-elaichi-tools">Why does Cursor show so few Elaichi tools?</h2>
<p>Because connected tools are not listed one at a time. In Elaichi, connected tools are never listed one by one, however few there are. Cursor's agent looks a tool up with <code>search_tools</code> and runs it with <code>execute_tool</code>, so a short tool list is the expected view, not a failed connection.</p>
<p><code>execute_tool</code> is only a naming indirection. It unwraps to the same tool name and arguments and passes the same checks as a direct call. Search is lexical, and it returns nothing rather than a tool from an app the developer never connected. <a href="/blog/search-tools-ranking-floor-idf/">The relevance floor behind search_tools</a> explains how.</p>
<h2 id="where-do-the-connected-accounts-come-from">Where do the connected accounts come from?</h2>
<p>From Elaichi, not from Cursor. A developer or an admin connects each SaaS account once, from a catalog of 600+ connectors that Elaichi serves, most of them written by Elaichi itself. Nothing about an account lives in <code>mcp.json</code>, and your team runs no MCP server per app.</p>
<p>Credentials stay out of Cursor entirely. A separate credential service holds each account's secrets, encrypted at rest, and owns token refresh. A failed refresh marks the connection <code>needs_reauth</code>, so it shows up as a connection to fix rather than a silent failure.</p>
<h2 id="what-decides-which-tools-a-developers-cursor-can-call">What decides which tools a developer's Cursor can call?</h2>
<p>The developer's role, what has been shared with them, and restrictions, checked on every call. A role is a set of permissions, with exactly one role per member, and <code>tool:execute</code> gates the whole endpoint. Sharing makes a connection that someone else owns usable by a developer.</p>
<p>Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Watch for one trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>Frozen parameters pin an argument the model must not choose, such as the Jira project an engineer may write to. A frozen key is removed from the schema Cursor sees, and its value is merged over whatever the model sends. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A role or restriction change takes about two minutes to apply, and <a href="/blog/offboarding-when-the-agent-holds-access/">the guide to offboarding AI access</a> sets out which changes land on the next call instead.</p>
<h2 id="will-cursor-run-an-elaichi-tool-without-asking">Will Cursor run an Elaichi tool without asking?</h2>
<p>Not by default. Cursor's docs say it "asks for approval before using MCP tools by default", and that clicking the arrow next to the tool name shows the arguments. For an Elaichi call the prompt names <code>execute_tool</code>, and the real tool is in those arguments, so expand them before you approve a write.</p>
<p>Cursor's Run Modes can loosen that. In Auto-review mode, the docs say, allowlisted MCP tools run straight away and everything else goes to a classifier. Treat the approval prompt as a convenience, not the control.</p>
<p>The guarantee sits on Elaichi's side. A tool that a restriction withholds cannot be called, however the prompt is phrased. OAuth scopes set a ceiling: reads need <code>mcp:read</code>, writes <code>mcp:write</code> and deletes <code>mcp:destructive</code>. A tool classified forbidden is reachable under no scope.</p>
<h2 id="how-do-you-see-what-cursor-did">How do you see what Cursor did?</h2>
<p>In Elaichi's audit trail. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account the call reached and the OAuth client it came through, with Cursor marked verified. The call is recorded under the engineer who signed in. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the fields.</p>
<p>The Auditor role is free and read-only, so a compliance reviewer can read the trail without a paid seat. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon.</p>
<h2 id="what-happens-to-a-developers-cursor-access-when-they-leave">What happens to a developer's Cursor access when they leave?</h2>
<p>It ends on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next request from that developer's Cursor fails. A SCIM deprovision from your identity provider suspends the member, which has the same effect.</p>
<p>The <code>mcp.json</code> entry left on the laptop does not matter. It holds a public URL and no token, and the grant behind it is gone. Removing the member runs a preflight first. A personal connection that a toolbox entry depends on has to be transferred or deleted before the removal goes through.</p>
<h2 id="what-does-elaichi-not-control-inside-cursor">What does Elaichi not control inside Cursor?</h2>
<p>Two things: prompt injection, and any MCP server a developer runs outside Elaichi. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. By the time a call reaches the endpoint, the model has already decided what to call. What Elaichi gives you is containment. A manipulated model still cannot call a tool its developer was never granted, and every call it ran is attributable afterwards.</p>
<p>Elaichi governs only the calls that go through its endpoint. A local server a developer adds to <code>mcp.json</code> beside it, such as one started with <code>npx</code>, runs on the laptop and never touches Elaichi. On Cursor Enterprise, the allowlist is the control for those.</p>
<h2 id="when-is-a-per-developer-mcpjson-still-enough">When is a per-developer mcp.json still enough?</h2>
<p>When three developers share one read-only account and nobody is asking who called what. A prototype against a public API needs no OAuth app and no log. Keep each app's own server in the file, keep any secrets in a password manager, and revisit when a contractor joins or someone asks for a record. Check <a href="/blog/when-you-dont-need-an-mcp-gateway/">the signals that you need a gateway</a> before you buy one.</p>
<p>Cost is the other honest constraint. Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows the price for your region. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<p>The same address serves the rest of the company: <a href="/blog/connect-elaichi-to-claude/">the Claude setup</a> and <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a> use it unchanged. If a developer's sign-in fails, start with <a href="/blog/mcp-oauth-errors/">what each OAuth error means</a>. For a rollout with Jira and Slack, read <a href="/blog/engineering-team-cursor-jira/">how to roll out Cursor to an engineering team</a>, or browse the <a href="/connectors/">connector catalog</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Do I need an API key to connect Elaichi to Cursor?</strong></dt><dd>No. The mcp.json entry is only a URL, https://api.elaichi.ai/mcp. Cursor supports OAuth for servers that require it, and it registers itself with Elaichi as an OAuth client. Each developer signs in instead of pasting a key or a header.</dd><dt><strong>Can a Cursor admin set up Elaichi for the whole team?</strong></dt><dd>Partly. A team admin can share Elaichi as a Team MCP server and add it to the team marketplace, and an Enterprise admin can allowlist it. Neither step installs it for anyone. Each developer still adds it from Customize and signs in with their own grant.</dd><dt><strong>Why does Cursor list only a few Elaichi tools?</strong></dt><dd>In Elaichi, connected tools are never listed one by one, however few there are. Cursor finds a connected tool with search_tools and runs it with execute_tool, so a short list is the expected view, not a broken connection.</dd><dt><strong>What happens to Cursor access when a developer leaves?</strong></dt><dd>It ends on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next request from that developer's Cursor fails. The URL left in their mcp.json is public and carries no token.</dd><dt><strong>Does Elaichi stop prompt injection in Cursor?</strong></dt><dd>No. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What Elaichi does enforce on every call from Cursor is the developer's role, restrictions, frozen arguments and OAuth scopes, and it writes an audit row for each call that reaches execution.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>setup</category>
    </item>
    <item>
      <title>SCIM and AI agents: where provisioning stops</title>
      <link>https://elaichi.ai/blog/identity-provider-scim-vs-mcp-grants/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/identity-provider-scim-vs-mcp-grants/</guid>
      <description>SCIM and AI agents meet at the user account: SCIM creates, updates and deactivates it, but it never decides which tools an agent may call.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> SCIM and AI agents meet at one point, the user account. SCIM, the standard an identity provider uses to push users and groups into an application, handles joiner, mover and leaver well, and Elaichi supports SCIM v2 with group-to-role mapping. What SCIM never carries is which tool a model may call, with which arguments, against which connected account. Elaichi adds that layer: one role per member, restrictions on a role or a user, frozen arguments, and an audit trail with one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</aside>
<h2 id="how-do-scim-and-ai-agents-fit-together">How do SCIM and AI agents fit together?</h2>
<p>SCIM and AI agents meet at one point: the person's account. SCIM (System for Cross-domain Identity Management) is the standard an identity provider uses to manage that account. It creates the account in each application, keeps its groups current and deactivates it when the person leaves. It never says which tool an agent may call, with which arguments, or against which connected account. That decision belongs to the system that serves the tools. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>The gap shows up like this. Support and finance get Claude and ChatGPT. Sign-in runs through the company identity provider, SCIM pushes the directory into every application, and the access review closes. Three weeks later a Salesforce opportunity changes owner overnight. Nothing in the identity provider's logs says which assistant did it, under whose account, or against which connected workspace.</p>
<p>Both layers are needed, and neither substitutes for the other. A person exercises judgment before running a command; a model follows the instruction it was handed. The directory is the right source of truth for identity and the wrong place to express a tool rule.</p>
<h2 id="what-does-scim-handle-well">What does SCIM handle well?</h2>
<p>SCIM handles joiner, mover and leaver, and it handles them better than anything you would build in-house. Keep it.</p>
<p>The protocol standard describes SCIM as an HTTP-based protocol for provisioning and managing identity data. It covers creating, changing, retrieving and discovering users and groups (<a href="https://www.rfc-editor.org/rfc/rfc7644">RFC 7644</a>). Microsoft describes provisioning in Entra ID in similar terms. It means creating user identities and roles in the apps people need, then maintaining and removing them as status or roles change (<a href="https://learn.microsoft.com/en-us/entra/identity/app-provisioning/user-provisioning">Microsoft Learn</a>).</p>
<p>In practice a new hire has accounts on day one. A department change updates groups everywhere. A termination deactivates accounts across every application SCIM reaches, without a ticket.</p>
<p>Elaichi supports SCIM v2 for users and groups, with group-to-role mapping, alongside SAML and OIDC single sign-on (SSO, one company login across applications). The single sign-on is built in-house rather than bought from an auth vendor. There are four onboarding paths in total: emailed single-use invite links with roles and teams pre-assigned, verified-domain auto-join with a configurable default role, SCIM provisioning, and just-in-time SSO. Use SCIM for employees and invite links for anyone the directory does not hold.</p>
<h2 id="what-can-an-identity-provider-not-see-in-a-tool-call">What can an identity provider not see in a tool call?</h2>
<p>It cannot see the call itself, because the call never passes through it. An identity provider sees authentication and directory state, and a tool call is neither.</p>
<table>
<thead>
<tr>
<th>Question the auditor asks</th>
<th>SCIM / identity provider</th>
<th>Elaichi grants and restrictions</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who is this person?</td>
<td>Directory of record</td>
<td>Reads from the directory of record</td>
</tr>
<tr>
<td>Are they still an employee?</td>
<td>Deprovision flag</td>
<td>Refuses the next call once the grant is revoked</td>
</tr>
<tr>
<td>What group are they in?</td>
<td>Group membership</td>
<td>Mapped to at most one role</td>
</tr>
<tr>
<td>Which tool can they invoke?</td>
<td>No standard field for it</td>
<td>A role, plus restrictions on a role or a user</td>
</tr>
<tr>
<td>Which connected account is used?</td>
<td>Not represented</td>
<td>A sharing grant on that connection</td>
</tr>
<tr>
<td>Who picked the amount?</td>
<td>Not represented</td>
<td>Frozen parameters, set by an admin</td>
</tr>
<tr>
<td>What did the agent do, and where?</td>
<td>Not represented</td>
<td>Audit trail with one entry for each connected-tool call that reaches execution (a call refused earlier writes none)</td>
</tr>
</tbody>
</table>
<p>After sign-in, the client holds an OAuth grant: an authorization to act for the user, issued at sign-in and revocable. Under the MCP specification, a protected MCP server acts as an OAuth 2.1 resource server, and the client makes requests on the user's behalf (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a>). Calls go to an endpoint, one network address that accepts them. Elaichi serves one for the whole organization at <code>POST /mcp</code>. Each call names a tool, a set of arguments and a connected third-party account.</p>
<p>Group membership encodes none of those three. SCIM's core schema does define free-form <code>roles</code> and <code>entitlements</code> attributes on a user, but it specifies no vocabulary or syntax for either (<a href="https://www.rfc-editor.org/rfc/rfc7643#section-4.1.2">RFC 7643</a>). Membership in a Finance group does not say whether a member may run a refund tool. It does not say which of two connected Xero organizations the call lands in. It does not say whether the model chose the amount or an administrator fixed it. An agent that reads a record and an agent that deletes it travel the same authenticated path.</p>
<p>There is a quick test. Take one record change made by an assistant last week and look for it in your sign-in logs. If the tool name and the account are both there, you can stop reading.</p>
<h2 id="what-has-to-be-decided-below-group-membership">What has to be decided below group membership?</h2>
<p>Four things: the role, the reach, the arguments and the account. The directory has already spoken by the time any of them comes up.</p>
<p><strong>Role.</strong> Elaichi gives each member exactly one role, enforced by a unique index, so every role is a complete persona instead of a stack of add-ons. Roles group 58 action strings such as <code>tool:execute</code>, <code>restriction:manage</code> and <code>audit:view</code>. That is role-based access control, or RBAC. The <code>tool:execute</code> permission gates the whole endpoint ahead of every other check. Without it, <code>tools/list</code> comes back empty and a call returns an in-band error naming the permission. Guest, Auditor and Billing Admin do not have it.</p>
<p><strong>Reach.</strong> A restriction says which connectors and which individual tools a target may reach. The rules on targets are strict: restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. One trap catches people: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. A block can match either a tool's name or its underlying operation. An allow matches the operation only, because whoever edits a connector's documentation can rename a tool. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. <a href="/blog/block-matches-name-allow-matches-operation/">Why an allow binds the operation and not the name</a> sets out the reasoning.</p>
<p><strong>Arguments.</strong> Frozen parameters pin values inside a tool's argument space, so an administrator owns a field instead of the model. A frozen key is stripped from the schema the model is shown. At execution the frozen value is merged over whatever the caller sent, so supplying the key anyway changes nothing. Entry defaults lose to caller arguments, and caller arguments lose to frozen parameters. Use frozen parameters for the sending domain, the ledger account, or the workspace a ticket has to land in.</p>
<p><strong>Account.</strong> Sharing is one building block: a grant of view, use or edit on a resource to a user, a team or the whole organization. A member's view holds only what they own and what others have shared with them. No organization-level permission widens that listing, org owners and admins included.</p>
<h2 id="how-does-elaichi-use-the-directory-instead-of-replacing-it">How does Elaichi use the directory instead of replacing it?</h2>
<p>The directory sets who someone is and which role they get. Elaichi sets what that role may reach, and records what it did.</p>
<p>Group-to-role mapping turns an existing group into an Elaichi role, so the joiner and mover flows you already run keep working. Clients then point at one address. Nothing is created per person or per team: there is no separate toolbox URL and no token embedded in a link. A toolbox here is a saved collection of configured tool entries.</p>
<p>An admin adds that address once where the client allows it, and each member then connects with their own sign-in. In Claude Team and Enterprise, an owner adds it under Organization settings > Connectors, and members connect it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166">Claude Help Center</a>). In Cursor, the admin MCP allowlist is Enterprise only and does not push a server to anyone's machine, so each developer still adds it (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor docs</a>). The ChatGPT steps are in <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup guide</a>, and <a href="/blog/elaichi-vs-native-ai-connectors/">the comparison with built-in AI connectors</a> covers why one address matters.</p>
<p>Credentials do not live in Elaichi. Per-account secrets are kept by a separate credential service, AES-256-GCM encrypted at rest, which also owns token refresh. If a refresh fails, the connection shows <code>needs_reauth</code> rather than breaking without a word. The catalog is 600+ connectors. Elaichi authors and serves most of them, and the rest are vendors' own MCP servers that Elaichi staff publish and each organization governs. The current list sits on the <a href="/connectors/">connector directory</a>.</p>
<h2 id="when-does-a-deprovision-actually-stop-an-agents-tool-calls">When does a deprovision actually stop an agent's tool calls?</h2>
<p>On the next call. When the identity provider deactivates or deletes a user over SCIM, Elaichi suspends that member, and suspending revokes every live grant in the same step. A role change or a restriction change takes about two minutes, because the change waits out a 60-second cache and then reaches the edge, on MCP, the console and the REST API alike. Write both numbers into the runbook, because they are not the same number.</p>
<p>The OAuth grant is checked with no cache. Its <code>revoked_at</code> value is re-read from the organization store on every single call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>SCIM itself leaves the meaning of deactivation to each application. RFC 7643 defines a user's <code>active</code> flag as an administrative status whose definitive meaning is set by the service provider (<a href="https://www.rfc-editor.org/rfc/rfc7643#section-4.1.1">RFC 7643</a>). So test what it does in your rollout. Deactivate a test user in the identity provider, then confirm the member shows as suspended and the next call fails.</p>
<p>SCIM suspends the member but never removes them. Removal is a separate step an admin takes in Elaichi, and it runs a preflight. Any private connection that a shared toolbox depends on must be dealt with first: transferred to another active member, or deleted. Otherwise the removal is refused. A transfer goes to one member and never to a team or the organization, and sharing with more people is a separate step. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with the member. Delegated toolbox entries raise a non-blocking warning, and re-pinning the entry is the fix. <a href="/blog/offboarding-when-the-agent-holds-access/">The contractor offboarding runbook</a> walks through the same shape for contractors.</p>
<h2 id="what-does-the-audit-trail-record-that-a-sign-in-log-cannot">What does the audit trail record that a sign-in log cannot?</h2>
<p>It records the tool call. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). An audit log here is the chronological, org-visible record of what was done and by whom.</p>
<p>The connection on each entry is the account the call actually reached, not the one it was aimed at. After an unexpected change, the first question is which of two connected Salesforce workspaces the agent wrote to. The <code>actor_kind</code> field is stored at the point of action, not inferred later from a user agent. Its values include <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</p>
<p>A record names the operation, the tool and the connection. It also holds the call's classification, whether it was approved, how it ended, and an error code, never the remote error text. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. Audit events and application logs share one record shape, so a single query answers what happened instead of two systems being correlated by eye. Every region's audit trail is stored in one EU log instance, and each organization's records are kept apart by the type system rather than by a WHERE clause. A dropped clause leaks, while a wrong scope returns nothing.</p>
<p>The trail is append-only, newest-first and cursor-paginated, filterable by free text, category, actor, action kind and time. It is eventually consistent, so a row can take a moment to appear. Export can forward the trail to your own destination. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog. A reviewer who only reads does not cost a license, because Auditor is a free seat. One honest gap: deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name. The rest of the controls are listed on the <a href="/security/">security page</a>.</p>
<h2 id="when-is-your-identity-provider-enough-on-its-own">When is your identity provider enough on its own?</h2>
<p>When no assistant in your company holds a connected account that can write. In that case SCIM is enough, so add nothing.</p>
<p>That case is real. Two engineers running a read-only MCP server locally do not need a control plane. Neither does an internal agent that only queries public documentation, or a sales assistant that can only read a knowledge base. The honest threshold is written up in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the post on not needing a gateway yet</a>. Revisit it when the first write tool goes live, or when the second person asks for access to the same account.</p>
<p>Know one limitation before you buy anything. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. It cannot apply there, because an MCP server never sees a user prompt. What does hold on the endpoint is per-operation permissions, the <code>forbidden</code> classification that no OAuth scope can reach, output redaction, scope limits and an audit row for each call that reaches execution.</p>
<p>Region is chosen when the organization is created. Elaichi has three regions, <code>eu</code>, <code>us</code> and <code>apac</code>, fixed once chosen. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. User accounts, sign-in sessions, API tokens, SSO settings and MCP OAuth token records are kept globally. The audit trail is stored in one EU log instance for every region. Gold lists at $15 per user per month, or $120 per user per year, in USD, and <a href="/pricing/">pricing</a> shows the price in your region. Black is the other plan, and there is a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<h2 id="which-layer-sets-what-from-sign-in-to-a-tool-call">Which layer sets what, from sign-in to a tool call?</h2>
<p>Each layer decides one thing, and the layers run on different clocks. Read the table in the order a new member meets them.</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Where it is set</th>
<th>What it decides</th>
<th>When a change applies</th>
</tr>
</thead>
<tbody>
<tr>
<td>SSO (SAML or OIDC)</td>
<td>Your identity provider and Elaichi</td>
<td>Who can sign in; an organization that enforces SSO refuses other sign-in methods</td>
<td>At the next sign-in</td>
</tr>
<tr>
<td>Default role</td>
<td>Elaichi, on each verified domain and SSO connection</td>
<td>The role a new member gets; Member when none is set</td>
<td>When they join</td>
</tr>
<tr>
<td>SCIM v2 users and groups</td>
<td>Your identity provider</td>
<td>Joiners and leavers; a group mapping can confer at most one role, and never sets team membership</td>
<td>At the next sync</td>
</tr>
<tr>
<td>Restriction on a role</td>
<td>Elaichi</td>
<td>Which connectors and tools that role may reach</td>
<td>Within about two minutes</td>
</tr>
<tr>
<td>OAuth grant</td>
<td>Each AI client's sign-in</td>
<td>Which client acts for which person, with which scopes</td>
<td>When the person signs in or reconnects</td>
</tr>
<tr>
<td>Deprovision</td>
<td>Your identity provider, through SCIM</td>
<td>Suspends the member and revokes every live grant</td>
<td>In the same transaction as the suspension</td>
</tr>
</tbody>
</table>
<p>SSO, SCIM and group-to-role mapping are Gold features. Team membership is set separately, by invite or by an admin, because SCIM and group mapping never set it.</p>
<h2 id="how-do-you-set-up-scim-and-tool-level-control-together">How do you set up SCIM and tool-level control together?</h2>
<p>Do it in this order, because each step depends on the one before it.</p>
<ol>
<li>Map directory groups to Elaichi roles. Each member ends up with exactly one role, so pick the group that describes the whole job, not a side function.</li>
<li>Connect each account a team needs. The member who connects an account owns that connection, and sharing it at use with a person, a team or the whole organization is what lets others call through it. A member sees only what they own or what was shared with them.</li>
<li>Write restrictions against roles first, and use an access request, approved by an admin, for a named exception.</li>
<li>Freeze the arguments the model should not pick, such as the sending domain or the ledger account.</li>
<li>Add the endpoint once in each AI client that allows it, then have each member connect and sign in.</li>
<li>Rehearse a leaver end to end: deactivate a test user, run the offboarding preflight, and confirm the audit trail names the account that was reached.</li>
</ol>
<p>Team-by-team starting points are on the <a href="/use-cases/">use cases page</a>. Role design gets its own treatment under <a href="/blog/category/governance/">governance</a>, and the other side-by-side write-ups sit under <a href="/blog/category/comparisons/">comparisons</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does SCIM control which tools an AI agent can call?</strong></dt><dd>No. SCIM (System for Cross-domain Identity Management) creates, updates and deactivates accounts in downstream applications and keeps group membership in sync. Its core schema has free-form roles and entitlements fields but defines no vocabulary for them, so it carries no tool-level rule. Whether a model may call a specific tool, with which arguments, against which connected account, is decided by the system serving the tools. In Elaichi that is a role, a restriction on a role or a user, and frozen parameters on individual tool entries.</dd><dt><strong>Does Elaichi replace an identity provider?</strong></dt><dd>No. Elaichi sits behind the identity provider and uses its signal. It supports SAML and OIDC single sign-on built in-house, SCIM v2 for users and groups, and group-to-role mapping, plus verified-domain auto-join and single-use invite links. The directory stays the source of truth for who exists and which groups they belong to. Elaichi decides what each role may reach at the tool layer and records each call that reaches execution.</dd><dt><strong>How fast does a SCIM deprovision stop an agent's tool calls?</strong></dt><dd>On the next call. A SCIM deactivation or delete suspends the Elaichi member, which revokes every live grant at once. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call with no cache. A role change or a restriction change is slower: it resolves through a 60-second cache plus edge propagation, so it takes effect within about two minutes on MCP, the console and the REST API.</dd><dt><strong>Can an identity provider's log show what an AI agent changed?</strong></dt><dd>Not by itself. The tool call travels from the AI client to the MCP server on an OAuth grant, so it never passes through the identity provider. The provider's log can show the sign-in and the directory change, but not which tool a model called or which connected account the call reached. That record has to come from the system serving the tools. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and records the account each call actually reached.</dd><dt><strong>What does an audit record for an AI tool call contain?</strong></dt><dd>In Elaichi, each record names the operation, the tool and the connected account the call actually reached. It also carries the call's classification, whether it was approved, how it ended, and an error code rather than error text. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. Actor kind is a stored field whose values include user, system, staff, scim, api_token and ai_assistant, which marks the Elaichi Agent.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>MCP endpoint per team, per person or per company?</title>
      <link>https://elaichi.ai/blog/one-endpoint-vs-per-team-endpoint/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/one-endpoint-vs-per-team-endpoint/</guid>
      <description>One endpoint per company usually beats an MCP endpoint per team or a server per person: each AI client needs one entry, and a leaver is one action.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A per-team MCP endpoint puts the team in the URL, and a server per member gives each person a server of their own, so setup and offboarding multiply by teams or by headcount across every AI client. Elaichi keeps one organization-wide endpoint, POST /mcp behind OAuth, where the grant varies rather than the address: an admin adds it once per client, each member signs in, and a departure is one membership action. A per-team address still fits teams that must be provably separate, and a server per member still fits ten people on one client.</aside>
<p>For most companies, one endpoint for everyone beats an MCP endpoint per team or a server per person. Each AI client then needs one entry, and a departure is one action instead of a hunt.</p>
<p>Support wants its ticketing system inside Claude, finance wants the ledger inside ChatGPT, and engineering already has Cursor open. That is 200 people across three AI clients. Each client has a field for a remote MCP connector, and the field takes one URL, called the endpoint. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Choosing an MCP endpoint per team, per person or per company is choosing what goes in that field. There is one more answer beside those two: a server for every member. The difference shows up in rollout, in what happens when somebody changes team or leaves, and in how many places you edit when access changes.</p>
<h2 id="what-does-an-mcp-endpoint-per-team-actually-decide">What does an MCP endpoint per team actually decide?</h2>
<p>It decides where identity lives. The team can sit in the URL, or each person can own a server. Otherwise one server serves everyone and identity moves into the sign-in. Those are the three models:</p>
<ul>
<li><strong>Per-team endpoint.</strong> Each team gets its own address, so the team is part of the URL.</li>
<li><strong>Server per member.</strong> Each person gets a server of their own, usually with their own connected accounts behind it and sometimes a token for scripts. The URL can still be shared: Zapier MCP gives every client the same URL and each member a server per client.</li>
<li><strong>One org-wide endpoint.</strong> One address for the whole company. The person signs in through OAuth, and the resulting grant (the authorization their client holds from then on) decides what they reach.</li>
</ul>
<table>
<thead>
<tr>
<th>Concern</th>
<th>Per-team endpoint</th>
<th>Server per member</th>
<th>One org-wide endpoint (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Setup at 200 people and three clients</td>
<td>15 console entries for five teams</td>
<td>200 servers, one per person</td>
<td>3 console entries, one per client</td>
</tr>
<tr>
<td>Someone changes team</td>
<td>Their clients move to the new team's URL</td>
<td>Their server keeps what they connected</td>
<td>A role or rule edit, in effect within about two minutes</td>
</tr>
<tr>
<td>Someone leaves</td>
<td>Check every team address they used</td>
<td>Find their server and any long-lived token</td>
<td>One membership action, and the next call is refused</td>
</tr>
<tr>
<td>Where the record lives</td>
<td>Ask whether every team address shares one trail</td>
<td>Ask whether one query spans every member's server</td>
<td>One trail for the whole organization</td>
</tr>
<tr>
<td>Reach of a bad rule</td>
<td>One team</td>
<td>One person</td>
<td>Everyone, until it is fixed</td>
</tr>
<tr>
<td>Best fit</td>
<td>Teams that must be provably separate</td>
<td>Ten people, one client, one or two apps</td>
<td>Several clients, and people who move between teams</td>
</tr>
</tbody>
</table>
<p>The choice sets your ongoing work. A URL is configuration inside somebody else's product, so a team address in three admin consoles means three edits whenever that team changes. A grant is state in one system, changed with one edit. Elaichi serves one organization-wide endpoint, POST /mcp: standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. No URL is issued per toolbox (a saved set of tools and accounts), and the address carries no token.</p>
<h2 id="what-do-the-three-shapes-cost-to-set-up-at-200-people">What do the three shapes cost to set up at 200 people?</h2>
<p>Per-team setup multiplies by teams times clients, per-member setup by headcount, and org-wide setup by clients alone. At 200 people in five teams, using Claude, ChatGPT and Cursor, the counts come out like this:</p>
<ul>
<li><strong>Per-team endpoint:</strong> fifteen console entries and five addresses, each with an owner and each able to drift.</li>
<li><strong>Server per member:</strong> at least 200 servers, up to 600 where the vendor creates one per client as Zapier MCP does, and up to 600 sign-ins, because each person signs in inside each client they use. Scripts add a token per server wherever the vendor issues one.</li>
<li><strong>One org-wide endpoint:</strong> three console entries and one address, with no token in it. Each member still connects it once per client and signs in.</li>
</ul>
<p>The sign-in count is similar in the last two. What differs is what a sign-in creates: a server that belongs to one person, or a grant against the address everyone shares. A fourth MCP client later is one more console entry, not a new rollout.</p>
<p>The counts are not the real cost. A per-member shape spreads decisions out, because each person picks which accounts to connect. The answer to "who can reach billing data" is then assembled from 200 local choices. In the org-wide shape it is one rule on a role, written once and readable in one place.</p>
<p>Joining is the other half. Elaichi has four onboarding paths: emailed single-use invite links with roles and teams pre-assigned, verified-domain auto-join with a default role, SCIM provisioning, and just-in-time SSO. SSO (single sign-on from your identity provider) runs over SAML or OIDC. SCIM v2 (the standard that syncs users and groups) brings the groups in, and each group maps to a role. A new hire in the finance group arrives with the finance persona and nothing else.</p>
<p>Copies differ too. The Elaichi address pasted anywhere still asks for a sign-in, so a copied URL is not a copied capability. For a team address, ask its issuer what a copy allows.</p>
<h2 id="which-vendors-split-the-address-by-team-or-the-server-by-member">Which vendors split the address by team, or the server by member?</h2>
<p>Composio documents the per-team shape, and Zapier MCP documents the per-member one. Both describe real governance, so the fork is where identity lives, not governance against none.</p>
<p>Composio's MCP Gateway page says each team gets its own MCP endpoint "carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked September 2026). The endpoints sit behind "one gateway, every server", with SAML or OIDC single sign-on and SCIM 2.0 provisioning.</p>
<p>Composio's enterprise page describes permissions "set administratively, per user and per role, down to the individual action" (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked September 2026). The same page says every tool call is logged with the user, team, tool, action and outcome, denied calls included. Self-hosting comes at the Enterprise tier.</p>
<p>Composio's homepage names end users who want an AI assistant to act in apps, and developers building agents (<a href="https://composio.dev">composio.dev</a>, checked September 2026). Composio Connect, an MCP server at connect.composio.dev/mcp, gives an agent access to 1000+ apps through 7 meta-tools (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026). A builder usually starts from one team and from code, and a per-team address is a natural unit for that reader. The <a href="/blog/elaichi-vs-composio/">side-by-side on Composio and Elaichi</a> covers the wider feature ground.</p>
<p>Zapier MCP documents the per-member shape in so many words. Every client connects to the same Zapier URL, and "Each MCP client gets its own MCP server: one for Cursor, one for Claude, one for ChatGPT." For token-based clients, Zapier adds: "give each user their own server and token rather than sharing one" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how Zapier MCP connections work</a>, checked October 2026). In an organization rollout, "each member still signs in and runs tool calls as themselves" (<a href="https://docs.zapier.com/mcp/manage/rollout/overview">Zapier MCP rollout docs</a>, checked October 2026). Admins can restrict members to a Zapier workspace, and app and action restrictions apply through MCP.</p>
<p>For most MCP clients, the member adds Zapier inside the client and signs in, and Zapier creates the server during that sign-in. Code you write, and clients not on Zapier's list, use a connection token instead. The token is long-lived, tied to one server, and grants whoever holds it the ability to run the server's tools. Zapier says to treat it like a password and never distribute it (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how Zapier MCP connections work</a>, <a href="https://docs.zapier.com/mcp/get-started/quickstart">quickstart</a>, checked October 2026). <a href="/blog/zapier-mcp-alternative/">A longer look at Zapier MCP against one endpoint</a> covers that model in full.</p>
<h2 id="what-moves-into-the-grant-when-the-address-stays-fixed">What moves into the grant when the address stays fixed?</h2>
<p>With one address, everything that would have varied the URL has to vary somewhere else. In Elaichi it varies across three layers, and keeping them distinct is how you predict what a person sees.</p>
<p>Roles hold permissions, which is RBAC (role-based access control): 58 action strings grouped into personas. A unique index keeps every member to exactly one role. Sharing works by grant: a resource can be shared with view, use or edit rights to one user, a team or the whole organization. A member's listing holds what they own and what someone shared with them, and nothing more, even for org owners and admins.</p>
<p>Restrictions are the governance layer, the rules that decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Inside each layer, allow rules combine, block rules combine, and a block always beats an allow. One resolver (the code that decides allow or deny) enforces all of it. It runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p>Frozen parameters sit under the same resolver. A frozen key is hidden from the schema the model is shown. Its value overrides whatever the caller sends, so sending the key does not unfreeze it.</p>
<h2 id="does-one-address-hand-the-model-every-tool-at-once">Does one address hand the model every tool at once?</h2>
<p>No. In Elaichi, connected tools are never listed one by one, however few there are. The model reaches them through <code>search_tools</code> and runs one with <code>execute_tool</code>. That second tool is only a naming indirection, and it passes the same gates as any other call.</p>
<p>The tool list itself is filtered by the caller's role and by the scopes on the grant. A restricted tool is withheld from the tool list and cannot be called, and search names it only as restricted, with no schema. So a tool someone expected and cannot run is likelier a permission gap than a typo. Control-plane operations stay listed individually, and <code>search_tools</code> never returns one.</p>
<h2 id="how-fast-does-a-team-change-take-effect">How fast does a team change take effect?</h2>
<p>In Elaichi, changing someone's role or a restriction takes effect within about two minutes. Both pass through a 60 second cache and then out to the edge, the same way on MCP, the console and REST. Grant revocation, member removal and suspension run on a faster clock. The OAuth grant is read fresh on every call, and removing or suspending a member revokes every live grant in the same transaction as the membership change. For those three, the next call already reflects the change.</p>
<p>A URL does not follow a person between teams. A per-team move means pointing that person's clients at another URL. A per-member server keeps whatever its owner connected, whichever team they now sit in. With one org-wide endpoint the move is a role edit, and no console changes.</p>
<h2 id="what-happens-the-hour-somebody-leaves">What happens the hour somebody leaves?</h2>
<p>With one org-wide endpoint, a departure is one action on the membership. In Elaichi the next call from any client that person signed in to is refused, because the grant is checked on every call.</p>
<p>Removal also runs a preflight. It lists every connection the departing member owns, private and shared alike. A private connection that a shared toolbox relies on blocks the removal until the admin transfers it to another active member; offboarding never hands a connection to the organization, to a team, or to the admin running the removal. A private connection nothing else depends on cannot be transferred and is deleted with the member. A shared connection a team still depends on is left untouched unless the admin deletes it, so transfer it to someone who is staying, which leaves every grant on it as it was.</p>
<p>In a per-member shape, you have to find each of the person's servers and, for code-based clients, a long-lived token. Ask any per-member vendor what becomes of a member's server when that member leaves. Zapier's MCP security page does not say (<a href="https://docs.zapier.com/mcp/manage/security">Zapier MCP security</a>, checked September 2026), so settle it during the trial rather than assume.</p>
<p>In a per-team shape, check that removing someone from your identity provider closes every team address they used. <a href="/blog/offboarding-when-the-agent-holds-access/">The full offboarding sequence when connections are still in use</a> gives the order to work in.</p>
<h2 id="which-shape-tells-you-which-account-the-agent-wrote-to">Which shape tells you which account the agent wrote to?</h2>
<p>The audit log (the record of who did what) answers it, and the address model decides how many logs you search. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and each entry names which account the call actually reached. For the fields a row needs and why, see <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit record has to capture</a>.</p>
<p>With one org-wide endpoint there is one audit trail per organization, so one query covers every team and every client. With several addresses, ask whoever runs them whether the records land in one queryable trail. Zapier MCP, for one, keeps user-level activity logs for tool calls in a History tab (<a href="https://docs.zapier.com/mcp/manage/security">Zapier MCP security page</a>, checked September 2026). The open question is whether one query spans every member's server.</p>
<h2 id="where-do-credentials-sit-when-everyone-shares-one-url">Where do credentials sit when everyone shares one URL?</h2>
<p>Not in the endpoint, and not in Elaichi. Connector secrets live in a separate credential service, one set per account, encrypted with AES-256-GCM at rest. That service owns refresh too, and a refresh that fails flags the connection <code>needs_reauth</code> instead of failing quietly.</p>
<p>A connect URL is not a credential either. It is a one-time session with no token in it, which is why Elaichi can return one over MCP. Reading an account's configuration back lists which paths are secret, as <code>secret_paths</code>, without their values.</p>
<p>The endpoint has its own gates. The <code>tool:execute</code> permission sits ahead of every scope. Without it, <code>tools/list</code> is empty and a call comes back with an in-band error that names the missing permission. Guest, Auditor and Billing Admin lack it. The OAuth scopes are <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>, and a tool classified <code>forbidden</code> is reachable under none of them.</p>
<h2 id="when-is-a-separate-address-per-team-or-per-member-the-better-fit">When is a separate address per team or per member the better fit?</h2>
<p>A separate address wins when the team or the person really is the unit you manage. A per-team address is the right call in four cases:</p>
<ul>
<li>An agency or holding company where each client team must be provably separate, including at the address level.</li>
<li>An address built into code one team ships, where a stable per-team URL is part of the build.</li>
<li>Teams that buy their own tools on their own budgets, with no central IT owner.</li>
<li>Two teams, no movement between them, and no plan to add another.</li>
</ul>
<p>In those cases the multiplication never happens, and a URL that carries team identity is a feature.</p>
<p>A server per member wins at small scale: ten people, one AI client, one or two apps, and automation already living in the same account. That group does not need a control plane, and buying one adds a seat line for a problem it does not have.</p>
<p>Usage points the same way. Zapier MCP has no separate billing (<a href="https://docs.zapier.com/mcp/features/usage">Zapier MCP usage</a>, checked September 2026). Each successful tool call through the server consumes two tasks, failed calls consume none, and tasks count toward the plan's allowance. If that fits a plan you already pay for, the per-member shape is cheaper in money and in attention.</p>
<p>Both shapes start to cost more than they save when three things are true at once. More than one AI client is in use. People join, move and leave every month. And somebody outside your team asks which account an agent wrote to.</p>
<h2 id="what-does-one-org-wide-address-not-fix">What does one org-wide address not fix?</h2>
<p>It concentrates risk rather than removing it. One address is one place to get wrong, and a mistake reaches everyone until somebody fixes it.</p>
<p>Two rule traps catch people early. First, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Second, block rules match on a tool's name or its pinned operation, while allow rules match on the pinned operation only. Whoever edits a connector's documentation can change a tool's advertised name, so governance binds the operation. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks match the name and allows match the operation</a> walks through it.</p>
<p>One address does not buy prompt-injection protection. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server is never shown the user's prompt, so a gate there would have nothing to read. The endpoint still enforces RBAC per operation, the <code>forbidden</code> classification, output redaction and scope limits, and it logs every call that reaches execution.</p>
<p>Residency follows the region chosen at creation. Elaichi has three regions, EU, US and APAC. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region. Deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name.</p>
<p>Seats are the last cost. Gold's USD list price is $15 per user a month, or $120 per user a year. <a href="/pricing/">The pricing page</a> shows the regional price some countries see. Suspended members and the free roles (Guest, Billing Admin and Auditor) are not billed. Per-seat pricing is predictable at 200 people and indifferent to how heavily anyone uses it, which cuts both ways.</p>
<h2 id="when-is-it-too-early-to-choose-any-of-the-three">When is it too early to choose any of the three?</h2>
<p>If one team uses one app through one client, and nobody has asked who did what, you do not need any of these shapes yet. Connect the app in the client, write down who has it, and revisit when a second team asks. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The argument for skipping a gateway for now</a> is real, and a control plane for three people is overhead you feel every month.</p>
<h2 id="how-do-you-pick-an-address-model-and-roll-it-out">How do you pick an address model and roll it out?</h2>
<p>Decide with four checks, in order. If team identity must show in a URL, for isolation or for code a team ships, a per-team address fits. If you are ten people on one client with one or two apps, a server per member is cheaper. Otherwise, multiply teams or people by clients and decide whether you want to own that number while people move. Last, look at where the connectors come from. Elaichi serves the <a href="/connectors/">600+ connectors</a> in its own catalog, authoring most of them and publishing vendors' own MCP servers for the rest.</p>
<p>For one org-wide endpoint, set it up in this order, because each step narrows the one after it:</p>
<ol>
<li>Create the organization and pick its region, which is set at creation.</li>
<li>Turn on SSO and SCIM, and map identity provider groups to roles, so joining is not a manual step at 200 people.</li>
<li>Connect the accounts each team needs before anyone points a client anywhere.</li>
<li>Write restrictions against roles first, and add user rules only to narrow one person.</li>
<li>Add the endpoint in Claude, ChatGPT and Cursor wherever the client lets an admin do it, then have each member connect it and sign in.</li>
<li>Give whoever reviews access an Auditor seat. It is free and read-only.</li>
<li>Remove a test member and watch the preflight, so the first real departure is not the rehearsal.</li>
</ol>
<p>If the servers are yours, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the self-hosted cost breakdown</a> covers who runs them. <a href="/blog/what-is-an-mcp-gateway/">What an MCP gateway is</a> maps the wider category, and the <a href="/use-cases/">team rollout pages</a> start from the systems each team already runs.</p>
<h2>FAQ</h2><dl><dt><strong>Does a per-team MCP endpoint give stronger isolation than one org-wide endpoint?</strong></dt><dd>Not by itself. A separate address makes team identity visible in configuration, which helps when a team must be provably separate or when the URL is built into code that team ships. On one address, isolation comes from the grant instead. In Elaichi each member holds exactly one role, resources are shared with view, use or edit, and restrictions on a role or a user decide what each person reaches, checked at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. The trade-off is where the work happens: in admin consoles, or in one access model.</dd><dt><strong>How many admin console entries does each MCP address model need?</strong></dt><dd>An org-wide endpoint needs one entry per AI client, so Claude, ChatGPT and Cursor make three. A per-team address needs one entry per team per client, so five teams across those three clients make fifteen. A server per member moves the work to people: at 200 people there are 200 servers, and each person signs in inside every client they use. Elaichi is the org-wide shape, and each member still connects it once per client and signs in to get their own grant.</dd><dt><strong>What is the difference between a per-user MCP server and a shared MCP endpoint?</strong></dt><dd>In a per-user shape, each member gets their own MCP server, with their own connected accounts behind it, so configuration and offboarding happen person by person. The URL itself may be shared, as it is on Zapier MCP. A shared endpoint is one address for the whole company, and the OAuth grant varies per person instead. Elaichi uses the shared shape: one endpoint at POST /mcp, standard MCP over Streamable HTTP and JSON-RPC 2.0, stateless and behind OAuth, with no URL or token issued per person or per team.</dd><dt><strong>How quickly does AI access change when somebody changes team or leaves?</strong></dt><dd>In Elaichi a role change or a restriction change takes effect within about two minutes, on MCP, the console and the REST API alike. Leaving is faster. The OAuth grant is re-read on every call, and removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next call is refused. Removal also runs a preflight that lists every connection the person owns, private and shared alike. A private connection that a shared toolbox relies on blocks the removal until the admin transfers it to another active member.</dd><dt><strong>When is a separate MCP address per team or per member the better choice?</strong></dt><dd>A per-team address fits when the team is the unit of procurement or isolation: agency client teams that must be provably separate, a URL built into code one team ships, or teams that buy their own tools with no central IT owner. A server per member fits a small company with one AI client, one or two apps and an automation account it already pays for. Both start to cost more than they save once several clients are in use, people join and leave every month, and someone asks which account an agent wrote to.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>The MCP context window problem, and a fix</title>
      <link>https://elaichi.ai/blog/context-window-problem-mcp-tools/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/context-window-problem-mcp-tools/</guid>
      <description>The MCP context window problem: each listed tool sits in the model&apos;s prompt on every turn. Elaichi lists no connected tools; the model searches for them.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Every tool an MCP server lists reaches the model as a name, a description and an argument schema, and that text takes room in the context window on every turn. Elaichi fixes the MCP context window problem at the source: connected tools are never listed one by one, however few there are. The model looks a tool up with search_tools and calls it through execute_tool, which passes the same permission, scope and restriction checks as any other call. The trade is a lean prompt for a search that can come back empty.</aside>
<h2 id="why-does-a-long-tool-list-fill-the-mcp-context-window">Why does a long tool list fill the MCP context window?</h2>
<p>Every tool an MCP server lists takes room in the model's context window before the user types a word. That is the MCP context window problem, and it grows with every account a company connects. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. When a client connects, it asks the server for its tools with <code>tools/list</code>. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> gives each entry a name, a description and an <code>inputSchema</code>, a JSON Schema for every argument the tool accepts. The client hands those definitions to the model. OpenAI's <a href="https://developers.openai.com/api/docs/guides/function-calling">function-calling guide</a> is plain about the cost: tool definitions "count against the model's context limit and are billed as input tokens".</p>
<p>The numbers get large quickly. <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">Anthropic's documentation</a> puts a typical setup of five MCP servers at about 55,000 tokens of tool definitions "before Claude does any work".</p>
<p>Two costs follow, and they differ in kind. The first is budget: context spent on tool definitions is context not spent on the ticket, the thread or the contract under review. The second is selection. Anthropic names tool selection accuracy as the second problem that grows with a tool library, and OpenAI advises keeping the number of initially available functions small "for higher accuracy". Duplicates make it worse. The specification warns that a client aggregating several servers may "encounter naming collisions" and suggests prefixing tool names with a server identifier. A prefix tells two Notion workspaces apart by label. Nothing in it says which one holds the customer contracts.</p>
<h2 id="why-does-elaichi-never-list-connected-tools-however-few">Why does Elaichi never list connected tools, however few?</h2>
<p>Because the list would grow with every account a company connects, and one endpoint for a whole company connects a lot of them. Elaichi serves a single organization-wide endpoint, <code>POST /mcp</code>, with two kinds of tool behind it. Control-plane operations are named <code>elaichi__{resource}__{operation}</code> and manage connections, members, restrictions and the audit trail. A member's connected third-party tools are named <code>{account}__{tool}</code>.</p>
<p>In Elaichi, connected tools are never listed one by one, however few there are. There is no threshold where listing switches on. The model looks a tool up with <code>search_tools</code> and calls what it found through <code>execute_tool</code>, and those two are the only way in. The list the model reads therefore does not grow with the number of connected accounts, whether a company connects three of the 600+ connectors or forty.</p>
<h2 id="what-does-the-model-see-in-the-tool-list">What does the model see in the tool list?</h2>
<p>Two meta-tools, <code>search_tools</code> and <code>execute_tool</code>, plus the control-plane operations, which stay listed individually. A list holding nothing but <code>elaichi__</code> operations does not mean nothing is connected. Search covers connected tools only and never returns a control-plane operation.</p>
<p>Administration stays in plain view because it is a fixed set that does not grow with connections. A search step in front of it would add a round trip to the most common requests.</p>
<p>The working loop changes shape. Instead of scanning a flat list, the model writes a query, reads back a short ranked set and calls one tool. It pays the schema cost only for what the search returned.</p>
<p>Results share the same window, so Elaichi caps them too: 32,000 characters per string, 200 items per array, 200 keys per object and a nesting depth of 8. A cut sets <code>elaichi_truncated</code>, so the model knows the answer was trimmed rather than complete.</p>
<h2 id="how-does-search-rank-connected-tools">How does search rank connected tools?</h2>
<p>By matching words, not meaning. Ranking is purely lexical over three fields: the tool name, the description and the connector label. An exact name match scores 5, a name prefix in either direction 3, the connector label 2 and the description 1.</p>
<p>A relevance floor sits on top. It is a minimum share of the query that a tool must match before search returns it at all. A tool must account for at least half of the query's own weight, measured with inverse document frequency (IDF), which counts rare words for more than common ones. Without a floor, a search always returns something, and a tool from an app the user never mentioned is worse than nothing, because the model calls it. <a href="/blog/search-tools-ranking-floor-idf/">The Cal.com search that returned a Notion tool</a> is the failure that produced the rule.</p>
<p>Two smaller rules matter too. The words <code>set</code>, <code>connection</code>, <code>frozen</code> and <code>more</code> are dropped from description scoring, because they sit on every merged or frozen tool. Before that, a query containing "connection" scored every merged tool the same and handed the model an arbitrary account. Ties break on codepoint order, never locale collation, so a server's language settings cannot decide which tools make the cut.</p>
<p>Account labels stay scorable on purpose. Name two Notion accounts <code>notion-legal</code> and <code>notion-marketing</code>, and a query mentioning legal ranks the right one first. Name them <code>notion</code> and <code>notion-2</code>, and the ambiguity has moved out of the model and into your naming.</p>
<h2 id="does-the-search-step-open-a-second-path-into-your-systems">Does the search step open a second path into your systems?</h2>
<p>No. The <code>execute_tool</code> wrapper is only a naming indirection. It unwraps to the same tool name and the same arguments and falls through the identical gates. There is no separate execution path and no privilege in the wrapper.</p>
<p>The <code>tool:execute</code> permission gates the whole endpoint ahead of every scope. Without it, <code>tools/list</code> comes back empty and a call returns an in-band error naming the permission. Guest, Auditor and Billing Admin do not hold it. OAuth, the sign-in standard that issues a scoped grant instead of a shared password, adds a second ladder: <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>. A tool classified <code>forbidden</code> is reachable under no scope, and a connected tool whose method is a delete still needs <code>mcp:destructive</code>. Restrictions are then checked by one resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p>One limit, stated plainly. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. On the endpoint itself, what holds is role-based access control (RBAC) per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits and audit logging of each call that reaches execution.</p>
<h2 id="can-restrictions-keep-tools-out-of-the-context-window">Can restrictions keep tools out of the context window?</h2>
<p>Yes. A restriction decides which connectors and which individual tools a target may reach, and a tool it withholds stays out of the tool list and cannot be called. Search names it, flagged restricted, with no description or schema, so it spends a name and not a schema.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, allow rules combine, block rules combine, and a block always beats an allow. One trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. <a href="/blog/block-matches-name-allow-matches-operation/">Blocks and allows also match a tool differently</a>, which matters before your first allowlist.</p>
<p>Frozen parameters trim the schema rather than the list. A frozen key is removed from the schema the model reads, so it costs no context. Its value is merged over whatever the caller sends, so passing the key cannot un-freeze it.</p>
<p>A restriction or role change takes effect within about two minutes. Grant revocation, member removal and suspension take effect on the next call.</p>
<h2 id="what-does-the-audit-trail-record-for-a-searched-call">What does the audit trail record for a searched call?</h2>
<p>The execution, not the wrapper. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the account the call actually reached, taken from the execution rather than the intent, so a reviewer never has to unwrap <code>execute_tool</code> to see what ran.</p>
<p>That answers the first question after an unexpected change, which is which of two Notion workspaces the agent wrote to. The entry also carries the operation, its classification, whether it was approved, how it ended and, for a failure, an error code only. It logs the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<h2 id="what-do-you-give-up-when-tools-sit-behind-search">What do you give up when tools sit behind search?</h2>
<p>Discovery becomes a search problem, and search can miss. Ranking is lexical, so a query phrased in words that appear in none of the tool name, the description or the connector label will not match. The relevance floor makes the honest outcome an empty result rather than a confident wrong one. Empty is the better failure, and the user still notices it.</p>
<p>There is also a round trip. Search, then execute, is two calls where a flat list needed one. A model working through a long task pays that latency each time it reaches for a new kind of action.</p>
<p>When a tool seems to be missing, Elaichi gives the model a fixed order of checks:</p>
<ol>
<li>Does the connection exist?</li>
<li>Is its status <code>active</code>? If not, reconnect it.</li>
<li>Is the tool in the connection's tool list? If not, check whether a restriction covers the connector.</li>
<li>Is <code>mcp:tools</code> on the OAuth grant?</li>
<li>Connected tools are never in the list, so call <code>search_tools</code> for the name.</li>
</ol>
<p>Most misses are permission gaps rather than typos. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">specification</a> lets the tool set "vary by the authorization presented on the request", and Elaichi filters what a caller can see by role and by the grant's scopes. A connection that is <code>pending</code> or <code>needs_reauth</code> contributes no tools at all. It is absent, not present and failing.</p>
<h2 id="when-is-a-flat-tool-list-still-the-right-answer">When is a flat tool list still the right answer?</h2>
<p>When the server is small and has one job. A single-purpose MCP server with six tools and one user can list everything, and search would add a round trip that buys nothing. <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">Anthropic's guidance</a> draws the same line. It calls standard tool calling without search "a better fit when you have fewer than 10 tools", and says the same when every tool is used in every request. If that is your situation, wait. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The case against adding a gateway yet</a> makes the argument.</p>
<p>Search starts to earn its round trip once a second team, a second account or a second client shows up. At that point the question stops being how many tools the model can hold. It becomes which tools this person should have been offered at all. Search does not answer that. Roles and restrictions do.</p>
<p>To see the shape of a governed endpoint, read <a href="/product/">how the control plane fits together</a>, browse the <a href="/connectors/">connector catalog</a>, or look at <a href="/use-cases/">what each team does with it</a>. More on the protocol itself sits in <a href="/blog/category/how-mcp-works/">How MCP works</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Why do MCP tools use up the context window?</strong></dt><dd>Because an AI client passes every listed tool's name, description and argument schema to the model as part of the prompt, and that text counts as input on every request. A long list spends context before any work starts, and it gives the model more near-identical names to choose between. Searching for a tool instead of listing every one keeps the prompt small however many apps are connected.</dd><dt><strong>Does Elaichi ever list connected tools one by one?</strong></dt><dd>No. In Elaichi, connected tools are never listed one by one, however few there are. There is no threshold at which listing switches on. The model looks a tool up with search_tools and calls it through execute_tool. Control-plane operations are the exception: they stay listed individually, and search_tools never returns one.</dd><dt><strong>Does execute_tool bypass permissions, scopes or restrictions?</strong></dt><dd>No. In Elaichi, execute_tool is only a naming indirection. It unwraps to the same tool name and the same arguments and passes the same gates: the tool:execute permission, the OAuth scopes, the forbidden classification, and restriction checks at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. There is no separate execution path and no privilege in the wrapper.</dd><dt><strong>Do restricted or frozen tools still use context window space?</strong></dt><dd>No. A tool withheld by a restriction in Elaichi stays out of the tool list, so it costs no schema. Search names it, flagged restricted, with no description or schema. Frozen parameters shrink the schema instead: a frozen key is removed from the schema the model reads, and its value is merged over the caller's arguments at execution, so passing the key cannot un-freeze it.</dd><dt><strong>What happens when tool search cannot find a tool?</strong></dt><dd>Elaichi returns an empty result rather than a weak match from another app, and gives the model a fixed order of checks: whether the connection exists, whether it is active, whether the tool is in the connection's tool list or restricted, and whether mcp:tools is on the OAuth grant. A missing tool is more often a permission gap than a typo, because what a caller can see is filtered by role and by the grant's scopes.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Designing roles for AI agents: one role each</title>
      <link>https://elaichi.ai/blog/designing-roles-for-ai-agents/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/designing-roles-for-ai-agents/</guid>
      <description>Design roles for AI agents as one complete job per person: Elaichi gives each member exactly one role and leaves which tools they reach to restrictions.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi gives each member exactly one role, enforced by a unique index, so every role has to describe a whole job rather than add one capability. The six system roles form a strict chain from Guest to Org Owner, with Billing Admin and Auditor beside it. Guest, Billing Admin and Auditor lack tool:execute, so they cannot call a tool at all, and a role or restriction change takes effect within about two minutes.</aside>
<h2 id="how-should-you-design-roles-for-ai-agents">How should you design roles for AI agents?</h2>
<p>Give each person one role that describes their whole job, and let restrictions decide which tools that job may reach. Elaichi enforces the first half: every member holds exactly one role, so each role has to be a complete persona rather than an add-on. Designing roles for AI agents starts one layer earlier than most access tickets assume. The thing being governed is a tool call, not a screen.</p>
<p>Support asks for Claude against Zendesk. Finance wants ChatGPT near Xero. Both tickets arrive in the same week, and IT has to answer them with one access model. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>The roles inside each SaaS app do not carry over. A Zendesk light agent and an accounts payable clerk describe what a person may click in one product. An AI client crosses products inside a single session, through one address. The real question is which tools a member may reach through that address, across every account the company has connected.</p>
<p>Elaichi splits the answer into three layers, and keeping them apart is most of the work. Permissions (RBAC, role-based access control) say which actions a member may perform. Resource sharing says what a member can see at all, through a grant that lets someone view, use or edit one resource. Restrictions decide which connectors and which individual tools a target may reach. Roles are the first layer only, and rollouts get muddled when one role is asked to carry all three.</p>
<h2 id="why-does-elaichi-allow-only-one-role-per-member">Why does Elaichi allow only one role per member?</h2>
<p>Because one role per member keeps the answer to "what can this person do?" short. Elaichi enforces it with a unique index. You cannot stack Auditor onto Member, and you cannot bolt a small admin capability onto a support seat as an extra.</p>
<p>That is a deliberate departure from the textbook model. <a href="https://csrc.nist.gov/projects/role-based-access-control">NIST's overview of role-based access control</a> assigns each user one or more roles, and each role one or more privileges. Where one person can hold three roles, working out what they can do means reading a union nobody has reviewed end to end. In Elaichi, the answer is one role plus the grants that person holds. When somebody asks what a departed contractor could reach, the answer is short.</p>
<p>The cost is real. If your identity provider thinks in additive entitlements, one role per member feels narrow at first. Two teams that differ by one action cannot express that as an extra role on one of them. You express it with a restriction or with sharing instead. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<p>Underneath, permissions are plain action strings, 58 of them, such as <code>tool:execute</code>, <code>restriction:manage</code>, <code>audit:view</code> and <code>connector:create</code>. A role is a named set of those strings and nothing more exotic.</p>
<h2 id="which-system-role-fits-which-job">Which system role fits which job?</h2>
<p>The six system roles in Elaichi form a strict chain: Guest, Member, Team Admin, People Admin, Org Admin and Org Owner. Each tier is built from the one below it and holds everything that tier holds. The relationship holds by construction, not by convention. Promoting somebody never quietly removes an ability they had.</p>
<p>The mapping to real jobs is direct:</p>
<ul>
<li><strong>Guest.</strong> An outside contractor or a reviewer who needs to see one shared thing. Free seat.</li>
<li><strong>Member.</strong> The support agent, the account executive, the analyst, the engineer. This is the working seat, and most people hold it.</li>
<li><strong>Team Admin.</strong> A department lead who runs a team's shared connections and toolboxes. A toolbox is a saved set of connected accounts and their tools.</li>
<li><strong>People Admin.</strong> Whoever runs joiners and leavers, usually IT ops or HR ops.</li>
<li><strong>Org Admin.</strong> The platform owner who configures shared connections and custom connectors. It holds every permission except <code>billing:manage</code> and <code>org:delete</code>.</li>
<li><strong>Org Owner.</strong> The only role holding <code>org:delete</code>.</li>
</ul>
<p>That last exclusion is deliberate. Deleting the workspace is Owner-only, so an attacker who lands an admin account cannot delete the evidence along with the workspace.</p>
<p>Two roles sit beside the chain rather than on it. Billing Admin belongs to whoever owns the card in finance and has no business inside tool calls. Auditor is read-only and free, so a compliance reviewer can read the audit log, the append-only record of what happened, without taking a license.</p>
<p>That split follows a familiar control. NIST SP 800-53's separation-of-duties control, <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AC-5</a>, divides duties among different people or roles. It also keeps those who administer access control from administering audit functions. An Auditor seat fits that pattern: the reviewer reads the record and holds none of the access administration. Org Owner, Org Admin, People Admin, Team Admin and Member are the billable seats, and the two plans are on the <a href="/pricing/">pricing page</a>.</p>
<h2 id="which-roles-can-call-a-tool-at-all">Which roles can call a tool at all?</h2>
<p>Among the system roles, only the five billable ones can. In Elaichi, <code>tool:execute</code> gates the whole MCP endpoint, ahead of every other check, and Guest, Billing Admin and Auditor do not hold it. Without it, <code>tools/list</code> comes back empty and every call fails with an in-band error that names the missing permission. The failure is legible rather than silent.</p>
<p>This is the cleanest line in the model. Three of the eight system roles cannot cause an action in a third-party account, by role, before a single restriction is evaluated. Those three are also the free seats, so cost and capability line up. The people who only review or only pay cannot act, and do not cost a license.</p>
<p>After that gate come the OAuth scopes. OAuth is the standard for delegated sign-in without handing over a password, and a scope is a permission the client receives when it signs in. There are four: <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>. No scope reaches a tool classified <code>forbidden</code>. The <code>mcp:tools</code> scope does not replace the other three: a connected tool whose method is a delete still needs <code>mcp:destructive</code> as well. Access to a shared toolbox changes none of this, because the role gate is evaluated first either way.</p>
<p>One limitation belongs here rather than in a footnote. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees a user prompt, so it cannot apply that gate. On the endpoint, the protections are per-operation RBAC, the <code>forbidden</code> classification, output redaction, scope limits and an audit row for each call that reaches execution.</p>
<h2 id="what-mistakes-do-teams-make-when-designing-agent-roles">What mistakes do teams make when designing agent roles?</h2>
<p>Three mistakes recur, and all three come from asking one layer to do another layer's job.</p>
<p>The first is expecting a role to widen what somebody can see. It does not. Members see what they own and what someone explicitly shared with them, and no org-level permission widens that, even for org owners and admins. If an Org Admin cannot see a team's connection, the fix is a grant, not a promotion.</p>
<p>The second is saving an allow rule that names nothing. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is the strictest rule you can express, and it is what you get by saving a new allow rule before filling it in.</p>
<p>The third is expecting a user-level restriction to loosen the role's rules. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A member is governed by the role's rules and by rules aimed at them, and a tool is reachable only when both admit it. Within each layer, allow rules add up, block rules add up, and blocks always beat allows. To let one person past a role rule, they file an access request and an admin approves it. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks match tool names but allows don't</a> explains how the two rule types match a tool.</p>
<p>One permission needs separate thought when you assign roles: <code>connector:create</code>. It is flagged high trust, because a custom connector can be aimed at any address you give it. Treat it like production deploy rights, not like a convenience.</p>
<h2 id="when-does-a-role-change-take-effect">When does a role change take effect?</h2>
<p>A role change takes effect within about two minutes. Elaichi resolves role membership and restrictions through a short cache, and the change lands on every surface: MCP, the console and the REST API alike. Grant revocation, member removal and suspension work differently. Elaichi re-reads those from the org store on every call, so they take effect on the next call.</p>
<p>That difference decides what you do during an incident. If an agent is writing to the wrong Salesforce account right now, suspend the member or revoke the grant. Do not downgrade the role and watch the clock. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>Removal also runs a preflight. It lists every connection the departing member owns. A private connection that a shared toolbox relies on blocks the removal until you transfer it to another active member or delete it. A transfer goes to one member, never to a team, the organization or the admin running the removal. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. A shared connection stays in place unless you name an action for it. The contractor case is worked through in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding a member who holds agent access</a>.</p>
<h2 id="what-does-a-sales-engineering-and-hr-split-look-like">What does a sales, engineering and HR split look like?</h2>
<p>Each department maps to one role, because a member in Elaichi holds exactly one role. Each role's approved apps are its allow rules, written against connectors in the catalog.</p>
<table>
<thead>
<tr>
<th>Department</th>
<th>Role</th>
<th>Allow rules name these connectors whole</th>
<th>Blocks on top</th>
<th>Exceptions</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sales</td>
<td>A custom Sales role</td>
<td>salesforce, hubspot, gmail, slack</td>
<td>The CRM delete tools</td>
<td>An access request, approved by an admin as a grant</td>
</tr>
<tr>
<td>Engineering</td>
<td>A custom Engineering role</td>
<td>jira, confluence, sentry, pagerduty, slack</td>
<td>Delete tools the team never needs</td>
<td>An access request, approved by an admin as a grant</td>
</tr>
<tr>
<td>HR</td>
<td>A custom HR role</td>
<td>bamboohr, greenhouse, slack</td>
<td>Pay tools for anyone who should not see pay</td>
<td>An access request, approved by an admin as a grant</td>
</tr>
</tbody>
</table>
<p>Allow rules on one role union, so one allow rule per app is fine. An allow rule is also that role's whole allowlist. A department loses any app its rules do not name, so name every app the role uses. Blocks always beat allows, which is why the blocks column holds the delete tools. Custom roles are a Gold feature.</p>
<p>Someone who works across two departments gets the role for their whole job, plus access requests for the rest. A user-targeted rule cannot add access, because it only narrows what the role allows. Map each identity-provider group to its role, since a SCIM group mapping can confer at most one role. A role or restriction change takes effect within about two minutes. For curating the app list itself with templates, see <a href="/blog/approved-ai-tools-per-team/">approved AI tools per team</a>.</p>
<h2 id="how-do-you-set-up-roles-for-a-first-rollout">How do you set up roles for a first rollout?</h2>
<p>Start with the system roles and change nothing for two weeks. You may need fewer custom roles than you expect, and the audit log will show which ones are missing.</p>
<ol>
<li>List everybody who will point a client at the endpoint. Claude, ChatGPT and Cursor all use the same organization-wide address. On Claude Team or Enterprise, an owner adds it once under Organization settings > Connectors. Each member then connects and signs in (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's steps</a>). For ChatGPT, follow <a href="/blog/connect-elaichi-to-chatgpt/">the ChatGPT setup</a>.</li>
<li>Assign Member to everybody who will act, and Auditor to everybody who only reviews. Auditor costs nothing.</li>
<li>Give People Admin to the two or three people who run joiners and leavers, and Billing Admin to finance.</li>
<li>Write restrictions against roles first, starting with blocks on destructive tools, use user-level rules only to narrow one person, and send exceptions through an access request.</li>
<li>Connect the accounts and read the audit log for a week. A call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</li>
<li>Create a custom role only when the log shows a persona that no system role fits.</li>
</ol>
<p>That order is least privilege in practice. NIST SP 800-53 states the principle in control <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AC-6</a>: allow only the access needed for assigned tasks. It applies to users and to the processes acting on their behalf. An AI client acting for a member falls under it. One of the control's enhancements asks for a periodic review of the privileges assigned to roles. A week of reading the audit log gives that review its first evidence.</p>
<p>If your identity provider is the system of record, map groups to roles through SCIM. SCIM is automatic user and group provisioning from your directory, so joiners arrive with the right role already set. SCIM itself leaves the meaning of a group to you. <a href="https://www.rfc-editor.org/rfc/rfc7643.html#section-4.2">RFC 7643</a> says groups can express role-based access control models, but it defines no authorization model. What membership grants is left to the service provider. In Elaichi, the group-to-role mapping is where you make that decision. Emailed invites with the role preset, just-in-time SSO sign-in and verified-domain auto-join with a default role are the other three paths in.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page puts the credential model, sharing and per-person attribution in one place, written for the reviewer who signs off.</p><a href="/security/" class="cta-button">See the security page</a></aside>
<h2 id="when-is-a-role-design-more-than-you-need">When is a role design more than you need?</h2>
<p>If eight people all need the same access to the same two apps, skip the design exercise. Put everybody on Member, keep the destructive tools restricted at the role level, and revisit it when a second team or a contractor arrives. A role model with one role in it is a spreadsheet with extra steps.</p>
<p>The same honesty applies a layer up. If nobody has connected an AI client to a company system yet, read <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you do not need an MCP gateway yet</a> before buying anything. If you would rather run the servers yourself, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">running your own MCP servers</a> works through the real cost.</p>
<p>Role design earns its keep at the second and third team. That is when one person's access has to differ from another's, and somebody will be asked to explain why. For one team worked end to end, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">how a sales team gets governed Salesforce access</a>. The twelve teams Elaichi models are on <a href="/use-cases/">use cases</a>, and the 600+ connectors in the <a href="/connectors/">catalog</a> are what your restrictions will name.</p>
<h2>FAQ</h2><dl><dt><strong>Can a member have more than one role in Elaichi?</strong></dt><dd>No. Elaichi gives each member exactly one role, enforced by a unique index, so roles cannot be stacked or combined. That forces every role to be a complete persona rather than a capability added on top of another role. Where two people need slightly different access under the same role, express the difference with restrictions on which tools they may reach, or with a grant of view, use or edit on a specific resource.</dd><dt><strong>Which Elaichi roles cannot call MCP tools?</strong></dt><dd>Guest, Billing Admin and Auditor lack the tool:execute permission, which gates the whole MCP endpoint ahead of every other check. For those roles the tool list comes back empty, and any call returns an in-band error naming the missing permission. Those three are also the free seats in Elaichi, so a compliance reviewer or a finance owner costs no license and cannot act in a connected account.</dd><dt><strong>How long does an Elaichi role change take to apply?</strong></dt><dd>It takes about two minutes. Role membership and restriction changes resolve through a short cache and land on every surface: MCP, the console and REST alike. Grant revocation, member removal and member suspension are different: Elaichi re-reads them on every call, so they take effect on the next call. During an incident, suspend the member or revoke the grant rather than downgrading the role.</dd><dt><strong>Does an Org Admin see every connection in the organization?</strong></dt><dd>No. In Elaichi, members see only what they own and what was explicitly shared with them through a view, use or edit grant, and that holds for org admins and org owners too. No org-level permission silently widens a listing. If an admin needs to see a team's connection, the fix is a grant on that resource, not a higher role.</dd><dt><strong>What is the difference between a role and a restriction in Elaichi?</strong></dt><dd>A role is a set of permission strings that says which actions a member may perform, such as tool:execute or audit:view, and each member holds exactly one. A restriction decides which connectors and which individual tools a target may reach, and it targets a role or a single user. Roles decide capability; restrictions decide reach.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>AI agents and PHI: four questions for your BAA</title>
      <link>https://elaichi.ai/blog/hipaa-ai-agents-baa-reviewer-questions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/hipaa-ai-agents-baa-reviewer-questions/</guid>
      <description>AI agents and PHI raise four BAA questions, all about access: minimum necessary, audit controls, workforce clearance and what happens when someone leaves.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A BAA reviewer looking at AI agents and PHI asks four access questions: minimum necessary, audit controls, workforce clearance and termination. Elaichi answers three of them directly, with role and user restrictions, frozen arguments, one role per member and an offboarding preflight. On audit controls it writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), keeping the one path argument that names the object, as the target id, and nothing else about the arguments, so what an agent typed into a patient record has to be read in that system. Elaichi states it is HIPAA compliant, as its Trust Center, linked from /security/, does. Take any compliance statement from that page.</aside>
<h2 id="what-does-a-baa-review-ask-about-ai-agents-and-phi">What does a BAA review ask about AI agents and PHI?</h2>
<p>AI agents and PHI meet in an access review, not in a new kind of review. A business associate agreement (BAA) reviewer asks the same four things about an AI client as about any other path to protected health information (PHI). Access has to be held to the minimum necessary, activity has to be recorded, the person has to be cleared, and access has to end when they leave.</p>
<p>The file usually opens with a request. A support lead wants Claude pointed at the help desk, and that help desk holds patient names, appointment dates and claim numbers. The questions come from the contract. A covered entity may let a business associate handle electronic PHI only after obtaining satisfactory assurances that it will be safeguarded (<a href="https://www.ecfr.gov/current/title-45/section-164.308">eCFR, 45 CFR 164.308</a>). The contract then has to commit the business associate to the Security Rule's safeguards, to reporting security incidents, and to binding its own subcontractors (<a href="https://www.ecfr.gov/current/title-45/section-164.314">eCFR, 45 CFR 164.314</a>).</p>
<p>Some vocabulary first, because the rest depends on it. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps (<a href="https://modelcontextprotocol.io/specification/2026-07-28">MCP specification</a>). Elaichi is a governed MCP control plane: each SaaS account is connected once, and its tools are served through one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth. OAuth here means each member signs in from the client and holds a grant, so no per-user server address or pasted token sits in a client config.</p>
<p>Settle one thing before the four questions. Elaichi states it is HIPAA compliant, as its Trust Center, linked from <a href="/security/">/security/</a>, does. Anything you carry into your own compliance file should be attributed to that page. A Business Associate Agreement is not offered by default. Signing a BAA with every vendor in the path is still your work. For the reviewer's side of the file, NIST's HIPAA Security Rule guide offers practical guidance for regulated entities of every size (<a href="https://csrc.nist.gov/pubs/sp/800/66/r2/final">NIST SP 800-66 Rev. 2</a>).</p>
<h2 id="question-one-is-the-agent-held-to-the-minimum-necessary">Question one: is the agent held to the minimum necessary?</h2>
<p>It can be, once the rules are written, and in Elaichi they live in two places: restrictions and frozen parameters. Both are enforced on the server, so neither depends on the model choosing to behave.</p>
<p>Two standards meet here. The Privacy Rule asks for reasonable efforts to limit PHI to the minimum necessary for the purpose (<a href="https://www.ecfr.gov/current/title-45/section-164.502">eCFR, 45 CFR 164.502</a>). The Security Rule's access-control standard allows access only to persons or software programs that have been granted access rights (<a href="https://www.ecfr.gov/current/title-45/section-164.312">eCFR, 45 CFR 164.312</a>). A reviewer will read an AI client as one of those software programs.</p>
<p>Restrictions govern which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. So "we have not written a rule yet" is a real state with a real meaning for a reviewer: everything is open.</p>
<p>A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, allow rules combine, block rules combine, and a block always beats an allow. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is the strictest thing you can express, and it does not look strict on the screen.</p>
<p>Blocks match the tool's name or the operation recorded when the rule was written. Allows match that operation only, because a tool's advertised name is a label whoever edits the connector controls. Governance binds the operation, never the label, and <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a> works through the reasoning.</p>
<p>Frozen parameters are the narrower instrument. A frozen key is removed from the schema the model is shown. Its value is laid over whatever the caller sends at execution, so naming the key in a call cannot undo the pin. In a PHI setting, that is how you hold a call to one clinic, one queue or one record type, out of the prompt's reach.</p>
<p>Enforcement runs against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<h2 id="question-two-does-the-record-satisfy-45-cfr-164312b">Question two: does the record satisfy 45 CFR 164.312(b)?</h2>
<p>Elaichi records each call that reaches execution, but not what an agent wrote, and the difference matters here. The audit-controls standard asks for mechanisms that record and examine activity in systems that contain or use electronic PHI (<a href="https://www.ecfr.gov/current/title-45/section-164.312">eCFR, 45 CFR 164.312</a>). Elaichi answers the recording half directly, with one limit a reviewer should hear from you rather than find alone.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The account on that entry is the one the call landed in, read from the execution rather than from the request. So "which of our two workspaces did the agent write to" has an answer in the record. Who acted is a stored field, <code>actor_kind</code>, rather than a guess made later. Its values include <code>user</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from Claude or ChatGPT is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</p>
<p>Beside the account, each entry carries the operation and tool, the classification, the approval decision, the result, and for a failure an error code only. Of the arguments, it keeps the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p>That cuts both ways, and it is the sentence to put in the file. A reviewer asking whether PHI can leak out through the log pipe gets a clean answer. A reviewer asking what the agent typed into a patient note gets nothing from Elaichi, and has to read the downstream system's own record.</p>
<p>Failed calls get the same care. Two error strings exist for each one. The string returned to the caller comes from the third party's response and is never written anywhere else. The string in the audit trail is never derived from the request or the response, because audit records are visible across the organization, readable by the in-product assistant, and can be forwarded outside Elaichi.</p>
<p>The trail is append-only, newest-first and filterable by free text, category, actor, action kind and time. One organization's audit history is kept apart from every other organization's, enforced in the type system rather than by a WHERE clause. The trail is eventually consistent, so a row may take a moment to appear. It is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon; Splunk HEC and Microsoft Sentinel are accepted as destinations, but Elaichi delivers events only to Datadog.</p>
<p>The Security Rule also asks for regular review of activity records such as audit logs (<a href="https://www.ecfr.gov/current/title-45/section-164.308">eCFR, 45 CFR 164.308</a>). That review needs no paid seat, because Auditor is a free read-only role.</p>
<h2 id="question-three-who-cleared-this-person-for-the-system">Question three: who cleared this person for the system?</h2>
<p>Three layers carry the answer in Elaichi: a role, sharing and restrictions. Workforce clearance under 45 CFR 164.308(a)(3)(ii)(B) asks for procedures that determine a workforce member's access to electronic PHI is appropriate (<a href="https://www.ecfr.gov/current/title-45/section-164.308">eCFR, 45 CFR 164.308</a>). Keeping the three layers distinct is what makes the answer defensible.</p>
<p>Permissions come from exactly one role per member, enforced by a unique index. Every role is a complete persona, so there is no stack of additive grants for a reviewer to reconstruct. Guest, Auditor and Billing Admin lack <code>tool:execute</code>, the permission that gates the whole endpoint ahead of every scope. Without it, the tool list is empty and a call returns an error naming the missing permission.</p>
<p>Sharing is the second layer, and it is deliberately separate. A member sees only what they own or what was explicitly shared with them, as a grant of view, use or edit to a user, a team or the organization. No organization-level permission silently widens a listing, owners and admins included.</p>
<p>Restrictions are the third layer. They answer what a cleared person may reach, rather than who that person is.</p>
<p>Clearance has an upstream too. SAML and OIDC SSO are built in-house, with SCIM v2 for users and groups and group-to-role mapping. A member's role can therefore follow the identity-provider group that already governs the PHI system. Sign-in also supports TOTP MFA with single-use recovery codes, and passkeys. One permission deserves its own line in the file: <code>connector:create</code> is flagged high trust, because a custom connector can be pointed at any destination.</p>
<p>One correction for the write-up: a role change or a restriction change takes effect within about two minutes. Removal and suspension hold from the next call.</p>
<h2 id="question-four-what-happens-on-the-day-someone-leaves">Question four: what happens on the day someone leaves?</h2>
<p>For removal and suspension, access ends on the next call, and a preflight settles what happens to the person's connections. Termination procedures under 45 CFR 164.308(a)(3)(ii)(C) ask how access to electronic PHI ends when employment or another arrangement ends. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read from the organization store on every single call.</p>
<p>The offboarding preflight is the part to describe to a reviewer. It lists every connection the departing member owns. A private connection that a shared toolbox relies on blocks the removal until an admin transfers it to one other active member or deletes it. A transfer never goes to the organization, to a team, or to the admin running the removal. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them.</p>
<p>A shared connection a team still depends on is deleted only if the admin explicitly asks. Otherwise the admin transfers it to a member who is staying, which leaves every grant on it exactly as it was. Delegated toolbox entries surface as a non-blocking warning, and re-pinning the entry is the fix rather than a decision about credentials.</p>
<p>Contractors deserve their own pass, since their accounts tend to outlive the engagement. There is a working sequence in <a href="/blog/offboarding-when-the-agent-holds-access/">what to do about contractor AI access today</a>.</p>
<p>One honest line for the BAA response. Deleting an organization tears down the workspace and deletes every connector credential. Three stores keep residue, and the deletion names them: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written. Describe it that way, as deletion with three documented residues, and never as total erasure.</p>
<h2 id="where-do-the-credentials-sit-and-who-holds-the-key">Where do the credentials sit, and who holds the key?</h2>
<p>Not in Elaichi. Connector credentials live in a separate credential service that holds per-account secrets, AES-256-GCM at rest, and owns refresh. Connections created since 2026-10-05 have their credentials placed in the organization's region, by best-effort placement for APAC. Older connections stay where they were until reconnected, which copies them into the region. A failed refresh marks the connection <code>needs_reauth</code> rather than failing silently.</p>
<p>A connect URL is not a credential. It is a one-time session that carries no token, which is why it is safe to return over MCP. Reading back an account's configuration returns public values plus <code>secret_paths</code>, the list of dot-paths that were encrypted, with none of their values. Editing one is refused, and the refusal text is identical whichever side produced it, so a caller cannot tell which side refused.</p>
<p>Two options a reviewer usually asks for by name. BYOK means per-organization envelope encryption under a key you hold. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. BYOA lets an organization supply its own OAuth app per connector. It is gated on <code>connector:manage</code> rather than <code>connection:manage</code>, so the right to delete a connection never quietly includes the right to repoint the organization's OAuth app.</p>
<h2 id="which-questions-will-elaichi-not-answer-for-you">Which questions will Elaichi not answer for you?</h2>
<p>Three, and a reviewer will find all of them eventually.</p>
<p>Prompt injection is the first. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees the user's prompt. What does hold at the endpoint: a permission check per operation, the <code>forbidden</code> classification that no OAuth scope reaches, output redaction, limits across the <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code> scopes, and an audit row for each call that reaches execution. A connected tool whose method is a delete needs <code>mcp:destructive</code> as well as <code>mcp:tools</code>.</p>
<p>The content of a write is the second. Elaichi stores no argument values beyond the target id, so it cannot show a reviewer the text an agent sent.</p>
<p>Certification evidence is the third. Any statement you make about a certification comes from the Trust Center linked from <a href="/security/">/security/</a>, attributed to that page.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>For a security review, the security page covers how credentials are held, how access is shared, and how each action is attributed to a person.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="when-should-you-leave-the-phi-system-unconnected">When should you leave the PHI system unconnected?</h2>
<p>When the use is occasional, when nobody is pointing AI clients at company data yet, or when reaching the system would take a custom connector nobody has reviewed. Some reviews should end with no connector, and saying so early saves a quarter. If the only reason an agent would touch the PHI system is one person's convenience once a month, a control plane is one more vendor in a regulated path for very little return. Keep the export or the read-only report you already have.</p>
<p>If nobody is pointing AI clients at company data yet, the problem is policy and monitoring first. That case is laid out in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the post on not needing an MCP gateway yet</a>.</p>
<p>If the PHI system is not in the catalog and somebody proposes a custom connector to reach it, treat that as its own review item. The permission behind it, <code>connector:create</code>, is high trust for a reason, and a custom connector pointed at a clinical system changes your PHI map.</p>
<p>Where the review ends in a yes, the next two decisions are who runs the server and which team goes first. On the first, see <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the comparison of self-hosted MCP servers and a managed control plane</a>. On the second, Compliance is one of the twelve teams on <a href="/use-cases/">/use-cases/</a>, and <a href="/connectors/">/connectors/</a> lists the 600+ connectors you could govern.</p>
<h2>FAQ</h2><dl><dt><strong>Is Elaichi HIPAA compliant, and will it sign a BAA?</strong></dt><dd>Elaichi states it is HIPAA compliant, as its Trust Center, linked from /security/, does. Take any statement for your compliance file from that page. A Business Associate Agreement is not offered by default: per the Terms, PHI may be submitted only where an Order Form expressly permits it and a BAA has been executed. What can be described directly: an append-only audit trail, stored in one EU log instance for every region; three regions (eu, us and apac), where EU and US pin the organization's data store and the execution of its org-scoped requests and tool calls to that jurisdiction and APAC uses best-effort placement that is not a residency guarantee; encryption at rest; SSO with SCIM provisioning; and a free read-only Auditor role.</dd><dt><strong>Does the audit log show what an AI agent wrote into a record holding PHI?</strong></dt><dd>No. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), with the tool, the account the call actually reached, the classification, the approval decision and the result. It keeps the one path argument that names the object, as the target id, and nothing else about the arguments. That keeps third-party payloads out of the log pipe, and it means the text an agent wrote has to be read in the downstream system's own record.</dd><dt><strong>How fast does removing someone's AI access to a PHI system take effect?</strong></dt><dd>It depends on the change. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call, so removal and suspension hold from the next call. A role change or a restriction change resolves through a 60-second cache plus edge propagation, so it takes effect within about two minutes.</dd><dt><strong>Can one restriction cover every member at once?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. To narrow everyone, write the rule on each role, since every member holds exactly one. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows.</dd><dt><strong>Does Elaichi stop prompt injection when an agent calls a tool?</strong></dt><dd>No, and it cannot. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees the user's prompt. What holds at the endpoint is a permission check per operation, a forbidden classification that no OAuth scope can reach, output redaction, scope limits and an audit row for each call that reaches execution.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Let IT post to one Slack channel from Claude</title>
      <link>https://elaichi.ai/blog/it-team-claude-slack-messaging/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/it-team-claude-slack-messaging/</guid>
      <description>IT can post to one Slack channel from Claude when Elaichi freezes the channel argument. Channel reads stay open, and opening DMs is restricted for the role.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi serves Slack to Claude through one organization-wide MCP endpoint, so an IT team can read channels and post to a single Slack channel. An allow rule names the reads and the send-message tool, a frozen parameter on the toolbox IT is given fixes that tool's channel, and block rules keep opening DMs and editing or deleting messages out of reach. The catalog's Slack connector has no tool that deactivates a user, and a rule change takes about two minutes to take effect.</aside>
<h2 id="can-it-post-to-just-one-slack-channel-from-claude">Can IT post to just one Slack channel from Claude?</h2>
<p>Yes. IT can read Slack and post to exactly one Slack channel from Claude, once Elaichi freezes the channel on the send-message tool. Your IT team answers most tickets in Slack threads: a laptop will not enroll, a screenshot follows, and the thread becomes the record. With Claude connected, an agent reads the thread and posts a summary to the help desk channel, and nowhere else.</p>
<p>Before anyone connects an account, decide three things: which reads are allowed, where the agent may post, and which Slack tools nobody's agent should call at all. Elaichi's <a href="/connectors/slack/">Slack connector</a> lists every tool those rules can name.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves Slack's tools from one organization-wide endpoint, <code>POST /mcp</code>, standard MCP over Streamable HTTP behind OAuth (the authorization framework the client signs in through). In Claude Team and Enterprise, an owner adds that address once under Organization settings > Connectors. Each member then connects it under Customize > Connectors and signs in with their own grant. On Pro and Max, each person adds it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Claude's help center</a>, as of October 2026). The address is the same for everyone; the grant, the role and the rules are what vary.</p>
<h2 id="which-slack-tools-should-it-allow-first">Which Slack tools should IT allow first?</h2>
<p>The reads the team needs plus one write, and nothing else. For a help desk, the reads are <code>list_all_slack_conversations</code>, <code>list_all_slack_conversation_history</code>, <code>list_all_slack_conversation_replies</code> and <code>list_all_slack_search</code>. The write is <code>create_a_slack_chat</code>, which sends a message.</p>
<p>A restriction in Elaichi is a rule about which connectors and which individual tools a target may reach. Put these tools in an allow rule on the IT role. Once that role holds an allow rule, every connector no allow rule on the role names is denied for the role, not only Slack's other tools. Allow rules on the same role add up, so give the role an allow rule for each other app it uses, naming the whole connector where that is enough, or the team loses those apps. The catch: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is the strictest rule you can express, and it is easy to create by accident while drafting one.</p>
<p>Allow rules match on the pinned operation only. When you write a rule against a connector and tool, Elaichi pins the canonical resource and method against the catalog at write time. Whoever edits the connector documentation controls the advertised tool name, but not the operation pinned underneath it. Governance binds the operation, never the label.</p>
<p>Elaichi marks reads with MCP's read-only hint and deletes with the destructive hint, and gives a plain write, such as editing a message, neither. The MCP specification tells clients to treat annotations as untrusted unless they come from a trusted server (<a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a>). A hint tells a client what a tool does. The rule decides whether IT can call it.</p>
<h2 id="how-does-a-frozen-channel-stop-claude-posting-elsewhere">How does a frozen channel stop Claude posting elsewhere?</h2>
<p>It removes the choice. Freeze the <code>channel</code> argument on <code>create_a_slack_chat</code>, and Claude can post to that channel and no other. A frozen parameter is a fixed argument value attached to a toolbox entry, where a toolbox entry is one tool tied to one connected account.</p>
<p>Freezing has two effects, and both matter here. The frozen key is removed from the schema Claude is shown, so there is no channel for the model to fill in. The frozen value is then merged over the caller's arguments at execution, so passing the key anyway cannot un-freeze it. The order runs entry defaults, then caller and model arguments, then frozen parameters.</p>
<p>That is what makes a pinned channel hold up against an instruction pasted into a ticket. The model is not being asked to respect a channel policy; it has no channel argument to change. It also closes the direct-message route through the send tool. A DM is a conversation with its own channel ID, and the frozen value replaces whatever ID the model tries to pass.</p>
<p>The lock belongs to the toolbox entry, so it holds only for calls made through that entry. Put the reads and the send tool in one toolbox, share it with IT, and leave the Slack connection itself unshared. A member with <code>use</code> on the connection could reach the unfrozen <code>create_a_slack_chat</code> directly. Every post through the toolbox goes out as the connection owner's Slack account. Slack shows that account, and Elaichi's audit trail records which member made the call.</p>
<h2 id="how-do-you-keep-claude-from-dming-everyone-or-deactivating-users">How do you keep Claude from DMing everyone or deactivating users?</h2>
<p>Block the DM tool, and know that deactivation is not on the Slack connector at all. Elaichi's Slack connector opens direct messages with <code>create_a_slack_conversations_open</code>, which opens or resumes a direct message or a group DM. It has no tool that deactivates a Slack user.</p>
<p>Write a block rule on the IT role for <code>create_a_slack_conversations_open</code>, and add <code>update_a_slack_chat_by_id</code> and <code>delete_a_slack_chat_by_id</code>, which edit and delete messages. The allow rule already leaves all three out. The blocks are the backstop: within each layer, blocks always beat allows, so they hold even if someone later widens the allow rule. A block also matches on the tool name or the pinned operation, so it survives a rename. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">how block and allow rules match differently</a>.</p>
<p>Deactivation usually lives in the identity provider. If IT also connects <a href="/connectors/okta/">Okta</a>, <code>okta_users_deactivate</code> and <code>okta_users_suspend</code> are the tools to block on the same IT role. OAuth scopes limit the blast radius as well. They ladder from <code>mcp:read</code> through <code>mcp:write</code> to <code>mcp:destructive</code>, and a tool classified <code>forbidden</code> is reachable under no scope at all. The block rule is what keeps a named tool out of one team's hands.</p>
<p>Bulk direct messaging is a different risk and gets the same treatment. Nothing about it is destructive, so the scope ladder will not stop it. A block rule will.</p>
<p>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. On the endpoint itself, the controls are RBAC per operation, the <code>forbidden</code> classification, redacted output, the scopes on the OAuth grant, and the audit trail. Plan the Slack rollout on the assumption that the rules are the control, not on the endpoint reasoning about intent.</p>
<h2 id="should-the-slack-rule-sit-on-the-it-role-or-on-a-person">Should the Slack rule sit on the IT role or on a person?</h2>
<p>On the role. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. An unrestricted Slack connection is therefore open to everyone it is shared with who can execute tools.</p>
<p>A role keeps the policy attached to the persona rather than to a list of names, and every member carries exactly one role, enforced by a unique index. Use a user-targeted rule only to narrow one person. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. If a senior engineer needs one extra tool, they file an access request and an admin approves it in the console. The approval creates a grant for that one person, and the role rules stay as they were.</p>
<p>Timing matters mid-rollout. A role or restriction change takes effect within about two minutes. Grant revocation, member removal and suspension are effective on the next call. If somebody has to lose Slack access now, revoke the grant or suspend the member rather than editing a rule and watching.</p>
<p>Elaichi checks the rule at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A restricted Slack tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema.</p>
<h2 id="do-multi-step-incident-tools-get-the-same-checks">Do multi-step incident tools get the same checks?</h2>
<p>Yes. An incident summary is rarely one call: read the channel, pull the Jira ticket, post the write-up. A synthetic tool packages that as a directed acyclic graph of steps, each calling a connected account's tool with templated arguments over inputs and prior outputs. Cycles are rejected at save, and independent steps run in parallel.</p>
<p>Nothing is skipped. Every step goes through the same restriction check as any other call, evaluated for the person running the tool. A synthetic tool that reaches for a restricted tool meets the restriction at that check. The audit trail holds one row for the whole run, with counts only. The individual step calls are not written as separate rows.</p>
<h2 id="what-does-the-audit-trail-show-after-claude-posts">What does the audit trail show after Claude posts?</h2>
<p>One entry for each call that reaches execution, whatever happened there. A call refused earlier, such as one for a tool the role withholds, writes none. The trail records one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection on every entry is the account the call reached, not the one the caller intended. With two Slack workspaces connected, the log says which one got the message.</p>
<p>Each record carries the operation and tool, the connection, the classification and whether the call was approved, along with its outcome and an error code when it failed. The <code>actor_kind</code> field is recorded, not inferred later from a user agent, and <code>ai_assistant</code> marks only the Elaichi Agent. A call from Claude is recorded under the member who signed in, with surface <code>mcp</code> and the OAuth client named, and Claude is marked verified. So "whose Claude posted that" is answered by the record itself.</p>
<p>Here is the trade-off to plan around. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. It will not show the message text or the channel ID passed in. That is why the channel belongs in a frozen parameter rather than in a convention the team agrees to follow. The configuration proves the destination, and the log proves the call ran against a named Slack account.</p>
<p>The trail is newest-first, cursor-paginated and filterable by free text, category, actor, action kind and time. It is eventually consistent, so a row may take a moment to appear. A departed member shows as "Former member" rather than vanishing. Audit events and application logs share one record shape, so one query answers "what happened" without correlating two systems by eye. Error text from a Slack response goes back to the caller and is never written to the trail. The trail inside Elaichi is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog.</p>
<p>Give the person who reviews all of this an Auditor seat. Auditor is read-only, sits off the role chain and is free, so a compliance reviewer does not use a license. Auditor also lacks <code>tool:execute</code>, which gates the whole endpoint ahead of every scope, so an Auditor cannot call a Slack tool while reading about one.</p>
<h2 id="why-not-use-slacks-own-mcp-server-for-it">Why not use Slack's own MCP server for IT?</h2>
<p>Slack's own server is the shorter path if Slack is the only app IT's agent touches. With it, "your integrated apps can search channels, send messages, and perform other Slack actions through MCP clients" (<a href="https://docs.slack.dev/ai/slack-mcp-server/">Slack's MCP docs</a>). The same page, checked October 2026, says "Workspace admins can approve and manage all MCP client integrations". Its endpoint is <code>https://mcp.slack.com/mcp</code>, and "MCP clients must be backed by a registered Slack app". Slack's server runs under Slack's own permission model and admin approval, with no second vendor.</p>
<p>Elaichi's case rests on what spans apps. One address serves Slack, <a href="/connectors/jira/">Jira</a> and Okta, in Claude, ChatGPT and Cursor alike. One set of rules on the IT role covers all three, and a frozen argument holds a send to one channel. Slack's page lists what its tools can do but does not describe fixing a tool's channel. One audit trail spans every connected app, and one removal ends a leaver's access through Elaichi to all of them at once. Their Slack, Jira and Okta accounts are a separate step.</p>
<h2 id="what-happens-when-the-engineer-who-connected-slack-leaves">What happens when the engineer who connected Slack leaves?</h2>
<p>Their access ends on the next call, and the connections they own are resolved before the removal completes. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's revoked timestamp is re-read from the organization store on every call, with no cache.</p>
<p>Offboarding then runs a preflight that lists every connection the departing member owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until you transfer it to an active member. A private connection nothing else depends on cannot be transferred and is deleted with the member. A shared Slack connection the team still depends on is left untouched unless the admin deletes it; transfer it to a member who is staying, which leaves every grant on it exactly as it was. A connection is never handed to the organization, to a team, or to the admin running the removal. Contractors make this routine, and the short version for them is in <a href="/blog/offboarding-when-the-agent-holds-access/">what to do about contractor AI access today</a>.</p>
<h2 id="when-is-this-more-setup-than-it-needs">When is this more setup than IT needs?</h2>
<p>If three people use Claude, all three are admins, and the only Slack account connected is a bot with read scopes, restrictions are overhead. The honest version of that argument, including the signals that you have crossed over, is in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway yet</a>.</p>
<p>The crossover usually arrives with the first non-admin. Once a contractor or a junior analyst holds a grant, allow-all stops being a decision and becomes a default nobody made.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The Slack connector page lists every Slack tool Elaichi serves, with the setup for Claude, ChatGPT and Cursor.</p><a href="/connectors/slack/" class="cta-button">See the Slack connector</a></aside>
<h2 id="in-what-order-should-it-set-this-up">In what order should IT set this up?</h2>
<p>Connect the Slack account first, write the allow rule second, build the toolbox with the channel frozen third, add the blocks fourth, and share the toolbox, not the connection, last. Then make one deliberate test post and read its entry in the audit trail. Sharing before the rules exist leaves a window where allow-all applies to a live account.</p>
<p>A sales version of the same sequence, run against Salesforce in ChatGPT, is in <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the Salesforce rollout playbook</a>. For what else IT can reach from the same address, browse the <a href="/connectors/">connector catalog</a>, and for how other functions set this up, see <a href="/use-cases/">the use-cases directory</a>. More posts in this series sit under <a href="/blog/category/team-playbooks/">team playbooks</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can Elaichi limit Claude to posting in one Slack channel?</strong></dt><dd>Yes, with a frozen parameter. Freeze the channel argument of the send-message tool, create_a_slack_chat, on its toolbox entry, which is one tool tied to one connected account. The key is removed from the schema the AI client sees, so the model is never offered a channel to choose. At execution the frozen value is merged over any caller arguments, so passing the key anyway cannot override it. Share that toolbox with IT rather than the Slack connection itself, so the frozen entry is the only way to post.</dd><dt><strong>Can Claude deactivate a Slack user through Elaichi?</strong></dt><dd>No. The catalog's Slack connector has no tool that deactivates a user. Its writes send, edit and delete messages, join channels, open direct messages and upload files. Deactivation usually lives in the identity provider, so if IT also connects Okta, block its deactivate and suspend tools on the same IT role.</dd><dt><strong>Why not connect Claude to Slack's own MCP server?</strong></dt><dd>It is the shorter path if Slack is the only app IT's agent touches. Slack's server, at mcp.slack.com/mcp, runs under Slack's own permissions, and workspace admins approve and manage the MCP clients that use it. Elaichi adds one address across Slack and IT's other apps, one set of role rules and one audit trail across all of them, a channel frozen on the send tool, and one removal that ends access through Elaichi to all of them.</dd><dt><strong>How long does a Slack restriction change take to take effect in Elaichi?</strong></dt><dd>It takes about two minutes. Role membership and restriction changes pass through a short cache before reaching every surface, including MCP, the console and the REST API. Grant revocation, member removal and member suspension are effective on the next call. If somebody must lose access right now, revoke the grant or suspend the member rather than editing a restriction rule.</dd><dt><strong>Does the Elaichi audit log show which Slack channel a message went to?</strong></dt><dd>No. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments, so the channel ID and the message text do not appear in the record. Each entry does name the operation, the connection actually reached, the classification, whether the call was approved and the outcome. To prove a destination, pin the channel with a frozen parameter, so the configuration, not the log, is the evidence.</dd><dt><strong>What happens to a Slack connection when the IT member who set it up leaves?</strong></dt><dd>Removing the member ends their access on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Offboarding also runs a preflight that lists every connection the departing member owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until you transfer it to an active member. A private connection nothing else depends on cannot be transferred and is deleted with the member. A shared connection the team still depends on is left untouched unless the admin deletes it; transfer it to someone who is staying, which leaves every grant on it as it was. A connection is never handed to the organization, to a team, or to the admin running the removal.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>What an AI agent audit log must capture</title>
      <link>https://elaichi.ai/blog/what-an-ai-audit-log-must-capture/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/what-an-ai-audit-log-must-capture/</guid>
      <description>An AI agent audit log must capture who acted, which client called, which account was reached, what was tried and how it ended. Argument contents stay out.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account the call actually reached rather than the one intended. An AI agent audit log needs the actor, the surface and client, the connection, the operation and tool, the classification, the approval decision, how the call ended, and an error code on failure. Elaichi records the one path argument that names the object, as the target id, and nothing else about the arguments, because the trail is visible across the organization and readable by the in-product assistant.</aside>
<h2 id="what-must-an-ai-agent-audit-log-capture">What must an AI agent audit log capture?</h2>
<p>An AI agent audit log must capture who acted, and which client the call came through. It must also capture which account the call actually reached, what was attempted, whether it was allowed, and how it ended. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the operation and tool, the connection, the classification and the approval decision, then the result, with an error code when the call fails. It logs the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p>The test is a Friday afternoon. A Salesforce opportunity changes owner, and nobody says they did it. Three people had an AI assistant connected to that CRM that week, and two of them hold two Salesforce accounts each. A useful log closes that question in one read.</p>
<p>The standards ask for the same shape. <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">NIST SP 800-53 control AU-3</a> lists what an audit record should establish. That is the type of event, when and where it occurred, its source, its outcome, and the identity of anyone or anything associated with it. <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html">OWASP's Logging Cheat Sheet</a> frames it as when, where, who and what, with a result status saying whether the action succeeded.</p>
<p>What is being logged here is MCP traffic. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification's tools page</a> asks clients to log tool usage for audit purposes. Elaichi keeps the record at the organization-wide endpoint every client calls, so it does not depend on which client a person used. Audit events and application logs share one record shape, so one query answers "what happened" without anyone correlating two systems by eye.</p>
<h2 id="who-acted-and-which-client-did-the-call-come-through">Who acted, and which client did the call come through?</h2>
<p>The row carries the actor, the surface and the client. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named, and those three clients are marked verified. A client that signs in through a loopback address, such as Claude Code, shows the name it registered with, marked unverified. The <code>actor_kind</code> values include <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, and <code>ai_assistant</code> marks the Elaichi Agent only. All of it is written at the point of action. None of it is guessed afterwards from a user agent string.</p>
<p>That distinction is the point. A value parsed out of headers is an opinion formed at read time, and it breaks the moment a client changes its user agent. A recorded field is evidence. Six months later a reviewer reads the surface and the client on each row, with no heuristic in the middle. OWASP's cheat sheet leaves room for exactly this, describing the who of an event as a human or machine user.</p>
<p>Actor names resolve server-side. A member who has since left renders as "Former member" rather than dropping out of the trail, so a departure cannot quietly edit history.</p>
<p>Elaichi staff impersonation is recorded and attributed in the customer's own audit log. Support appears as staff, not as the customer, which keeps the chain of custody intact when somebody steps in to reproduce a problem.</p>
<h2 id="which-account-did-the-call-actually-reach">Which account did the call actually reach?</h2>
<p>The connection field names the account the call reached, taken from the execution rather than from the intent. Calls that run and calls that fail at execution both carry it.</p>
<p>This is the field people underestimate until they need it. A person may hold a personal Notion workspace and a corporate one. "Which of my two Notion workspaces did the agent write to?" is the first question after an unexpected change, and an intent-derived value cannot answer it. The caller asked for Notion, and the call landed on one connection. If those two ever differ, only the execution-derived value is true.</p>
<p>The same field separates a personal connection from one shared with a team or the whole organization. A write through the shared finance account is a different incident from the same write through somebody's personal login, and the row says which without a follow-up.</p>
<h2 id="what-was-attempted-and-was-it-a-read-a-write-or-a-delete">What was attempted, and was it a read, a write or a delete?</h2>
<p>The row records the operation and the tool, plus the classification of that operation as a read, a write or a delete. The classification is what a reviewer scans first, because it separates an afternoon of reads from the three calls that changed something.</p>
<p>Tool names are labels. Whoever edits a connector's documentation can change a tool's advertised name, so when a governance rule is written, Elaichi records the tool's underlying operation from the catalog. Governance binds the operation, never the label, and the record reflects that binding. The reasoning is in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name but an allow matches the operation</a>.</p>
<p>Two kinds of call look as if they might escape the row, and neither does. In Elaichi, connected tools are never listed one by one, however few there are, so a model reaches them through <code>search_tools</code> and <code>execute_tool</code>. The <code>execute_tool</code> call is only a naming indirection. It unwraps to the same name and arguments and passes the same gates, so the row names the real tool rather than the wrapper. Synthetic tools, which chain steps over other tools, send every step through the same restriction checks as any other call. A run is audited as one row with the tool's name, status, duration and counts of steps, calls and retries. It holds no step results, and the step calls are not separate rows.</p>
<h2 id="was-the-call-allowed-and-how-did-it-end">Was the call allowed, and how did it end?</h2>
<p>The row records whether the call was approved and how it ended. A call refused at execution is still a row. A call refused earlier is not. <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html">OWASP's cheat sheet</a> lists authorization failures among the events to log, so know where Elaichi's trail stops.</p>
<p>Elaichi writes one row for each connected-tool call that reaches execution and then runs, fails or is refused there. One example is a call for an account Elaichi cannot match. Another is a call after a restriction changed once the tool was listed. A call refused before that point writes no row. A call to a tool a restriction withholds is refused before execution. A missing MCP scope, an unknown tool name or a rate limit stops a call first. A call that waits for a person's approval writes no row until it runs. A connected tool reached through the toolbox execute operation is recorded as a toolbox execution row instead.</p>
<p>Timing matters when you tighten a rule. A change to a role or a restriction takes effect within about two minutes, through a short cache. A call that succeeds shortly after you tighten a rule is expected, not a bug.</p>
<p>Grant revocation is different, because its flag is re-read on every call with no cache. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. For removal, suspension and revocation, the next call is the accurate answer. The <a href="/blog/offboarding-when-the-agent-holds-access/">contractor offboarding walkthrough</a> covers the connection preflight that runs alongside it.</p>
<h2 id="why-does-the-log-leave-out-argument-contents">Why does the log leave out argument contents?</h2>
<p>Because the trail travels further than the call did. Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. So a row says which object the call acted on, when it names one, as the target id, and not what the call wrote to it. That is a real loss. You cannot replay a call from the trail, and "what exactly did it write" needs the third-party application's own record of the change.</p>
<p>The reason is where the trail goes. Audit records are visible to the organization, readable by the in-product assistant, and built to be forwarded to a SIEM. Argument contents are the part of a call most likely to carry customer data, credentials pasted by a user, or the text of a contract. A field copied to three places should not hold the payload. The target id is enough to scope an incident, and cheap to expose. Argument contents are neither.</p>
<p>NIST makes the same trade explicit. The discussion under AU-3 warns that audit records can reveal personally identifiable information, especially when the trail records inputs. Its enhancement <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AU-3(3)</a> limits that information to the elements a privacy risk assessment names. OWASP's <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html">list of data to keep out of logs</a> covers the same ground: access tokens, passwords, connection strings, encryption keys and sensitive personal data.</p>
<h2 id="which-error-message-gets-written-down">Which error message gets written down?</h2>
<p>A failed call produces two error strings, and only one of them is ever written to the trail. The row carries an error code. The caller receives a message derived from the third party's response body, and that message is never written anywhere else.</p>
<p>The audit-side text is never derived from the request or the response. A remote error body in a record that the whole organization and the in-product assistant can read would be third-party payload leaving the system through the log pipe. It is the same leak as logging argument values, wearing a different hat.</p>
<p>Promoted metadata follows the same instinct. It is a fixed allowlist, not a flattening of whatever keys arrive. Metadata keys can be influenced by users, and unbounded flattening would let one organization's traffic grow the field namespace for a whole tenant. In practice, your ingestion schema stays predictable when somebody adds a field in a third-party application.</p>
<h2 id="where-does-the-log-live-and-who-can-read-it">Where does the log live, and who can read it?</h2>
<p>Each organization's audit history is scoped in the type system rather than by a WHERE clause in a query. The failure modes are not symmetric. A dropped WHERE clause leaks, and a wrong scope returns nothing. Customer-visible audit records and internal application logs sit apart, which matters more than usual because the in-product assistant can read the audit log.</p>
<p>Elaichi has three regions, EU, US and APAC, chosen when the organization is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. Every organization's audit trail, whatever its region, is stored in one log instance in the EU. The <a href="/security/">security page</a> carries the rest of the data-handling detail.</p>
<p>NIST's <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AU-9</a> asks for audit information to be protected from unauthorized modification and deletion, and Elaichi's trail is append-only. It reads newest-first, cursor-paginated, and filterable by free text, category, actor, action kind and time. The Auditor role is read-only and a free seat, so a compliance reviewer does not consume a license. Auditor also lacks <code>tool:execute</code>, the permission that gates the whole MCP endpoint, so a reviewer can read the trail and cannot make calls. Seat classes sit on the <a href="/pricing/">plans page</a>.</p>
<h2 id="can-you-send-the-log-to-a-siem">Can you send the log to a SIEM?</h2>
<p>Not on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. A SIEM is the system that gathers security logs from across a company, so forwarding puts agent activity next to everything else your security team already watches.</p>
<p>Splunk HEC and Microsoft Sentinel destinations are accepted as destinations, but Elaichi delivers events only to Datadog. Forwarding is filterable by log type, where an absent filter forwards everything and an empty list forwards nothing. The audit trail inside Elaichi is on Gold.</p>
<h2 id="what-can-the-log-not-tell-you">What can the log not tell you?</h2>
<p>Three limits, stated plainly.</p>
<p>The trail is eventually consistent. A row can take a moment to appear, so an empty screen one second after a call is not proof that nothing happened.</p>
<p>The log cannot show what the user typed. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees the user's prompt, so on <code>POST /mcp</code> there is nothing for that gate to inspect. What does hold there: role-based permissions per operation, the forbidden classification, output redaction, OAuth scope limits and the audit record itself.</p>
<p>Deleting an organization deletes its credentials and tears down the workspace, but it leaves three stores behind: the audit history (each record ages out under the log server's 90-day retention, counted from when it was written), analytics events and the credential service's connector configuration rows. The deletion returns that residue by name rather than reporting a clean sweep. If your retention policy needs proof that log data is gone, have that conversation before you sign.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>For a security review, the security page covers how credentials are held, how access is shared, and how each action is attributed to a person.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="when-do-you-not-need-a-log-this-detailed">When do you not need a log this detailed?</h2>
<p>If one person uses one assistant against one application with read-only access, that application's own activity history probably answers every question you will ask. Salesforce, Notion and Jira each keep some record of who changed what. Adding a control plane to observe a single user is overhead with no reader.</p>
<p>A detailed row starts to pay when three things are true at once: several people, several accounts of the same application, and at least one write. That is the point where the intended account and the reached account can differ, and where "who did this" stops having an obvious answer. The case for waiting is made at more length in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when an MCP gateway is premature</a>.</p>
<p>How this record maps onto an audit is in <a href="/blog/soc2-evidence-ai-agents-cc-controls/">SOC 2 evidence for AI agents</a>, and more on deciding what agents may reach sits in the <a href="/blog/category/governance/">governance posts</a>. The applications these rows get written about are in the <a href="/connectors/">connector catalog</a>, and the team-by-team rollouts are on <a href="/use-cases/">use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What should an AI agent audit log include?</strong></dt><dd>At minimum: the actor, the surface and client, the account the call actually reached, the operation and tool attempted, its classification as a read, write or delete, whether the call was approved, how it ended, and an error code on failure. Elaichi's audit log covers these, because it writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none).</dd><dt><strong>Does Elaichi log the arguments an AI agent sent to a tool?</strong></dt><dd>Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. The trade-off is that you cannot rebuild a payload from the audit trail, and have to consult the third-party application's own record for that. The reason is exposure: audit records are visible across the organization, readable by the in-product assistant and built to be forwarded to a SIEM, so values are the wrong thing to copy into them.</dd><dt><strong>What is actor_kind in an audit log?</strong></dt><dd>The actor_kind field records what sort of actor performed an action, with values including user, system, staff, scim, api_token and ai_assistant, which marks the Elaichi Agent. In Elaichi it is written at the point of action rather than inferred afterwards from a user agent string. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface mcp and the OAuth client named.</dd><dt><strong>How quickly does a restriction change show up in the audit log?</strong></dt><dd>A role or restriction change in Elaichi takes effect within about two minutes, because it resolves through a short cache and edge propagation. Calls made in that window still follow the old rule and are logged as such. Grant revocation, member removal and suspension are different: they are effective on the next call, since the revocation flag is re-read on every call with no cache.</dd><dt><strong>Can Elaichi send audit logs to a SIEM?</strong></dt><dd>Not on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. A Splunk HEC or Microsoft Sentinel destination is accepted but does not deliver events. Forwarding is filterable by log type: an absent filter forwards everything, and an empty list forwards nothing.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Is Composio secure enough for enterprise use?</title>
      <link>https://elaichi.ai/blog/is-composio-secure-enough-for-enterprise-use/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/is-composio-secure-enough-for-enterprise-use/</guid>
      <description>The answer to &quot;is Composio secure enough for enterprise use&quot; sits in architecture more than controls: its own pages list SSO, role permissions and call logs.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Composio's own pages describe per-user and per-role permissions, per-call logging, SSO and self-hosting at the Enterprise tier, so the control list is rarely what fails a security review. What a review still has to settle is architecture: who authors the connectors, where credentials sit, how many addresses your AI clients point at, and what the audit record ties an action to. Elaichi answers those by authoring most of its connectors and serving them through one organization-wide MCP endpoint behind OAuth, with role and user restrictions, an append-only audit trail and three regions. The EU and US regions pin the data store and the execution of org-scoped requests and tool calls to that jurisdiction.</aside>
<h2 id="is-composio-secure-enough-for-enterprise-use">Is Composio secure enough for enterprise use?</h2>
<p>Composio's own pages answer most of the controls half of that question. They describe permissions per user and per role, down to the individual action, and logging of every tool call, denied ones included. They also list SSO over SAML and OIDC, and self-hosting at the Enterprise tier (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked October 2026). The other half is architecture: who authors the connectors, where credentials sit, how many addresses your AI clients point at, and what the audit record ties an action to. No vendor page settles that half for you, and it is where a security review should spend its time.</p>
<p>The question usually arrives as a questionnaire. An engineer has already built something on Composio, and security has to sign it off before an agent touches production data.</p>
<p>SSO means sign-in through your identity provider rather than a second password. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps (<a href="https://modelcontextprotocol.io/specification/2026-07-28">MCP specification</a>), and an endpoint is the one address a client connects to. The rest of this post walks the mechanics underneath a control list, using Elaichi as the worked example.</p>
<h2 id="what-does-a-soc-2-report-actually-tell-you">What does a SOC 2 report actually tell you?</h2>
<p>That an auditor examined the vendor's own description of its system and the controls in it. AICPA's guide frames a SOC 2 engagement as an examination of a service organization's description of its system and its controls relevant to security, availability, processing integrity, confidentiality or privacy (<a href="https://www.aicpa-cima.com/cpe-learning/publication/soc-2-reporting-on-an-examination-of-controls-at-a-service-organization-relevant-to-security-availability-processing-integrity-confidentiality-or-privacy">AICPA SOC 2 guide</a>). A Type II report adds testing over a stated period. Neither tells you the scope covered the product you are about to buy.</p>
<p>Read four things: the period end date, the exceptions, the systems named in scope, and the carve-outs for subservice organizations, meaning the cloud and logging vendors underneath.</p>
<p>A certification belongs to the vendor that holds it. Composio's MCP Gateway page states SOC 2 Type II and ISO 27001 certification (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked October 2026). That is Composio's claim to substantiate, so ask for the current report and read it under NDA. Do not take a certification claim from a blog post, including this one. Elaichi's own certification status is published on its Trust Center, linked from the <a href="/security/">security page</a>, and that page is the authority rather than this paragraph.</p>
<p>What a report cannot settle is whether the shape of the system matches your org chart. Five mechanics decide that: who authors the connectors, where credentials live, how many addresses your clients point at, what the audit record ties an action to, and what happens when a person leaves.</p>
<h2 id="who-authors-the-connectors-you-are-trusting">Who authors the connectors you are trusting?</h2>
<p>This is the first mechanic, and it moves the others. Composio Connect is an MCP server at <code>connect.composio.dev/mcp</code> that gives an agent access to 1000+ apps through 7 meta-tools (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026). The first time an agent needs an app, Composio generates an OAuth link to approve in the browser. OAuth is delegated sign-in: the app receives a scoped token instead of a password.</p>
<p>Elaichi serves 600+ connectors and authors, maintains and runs most of them on its own infrastructure. The rest are native MCP connectors, where the app's vendor builds and runs the MCP server and Elaichi governs every call to it. Companies do not run MCP servers to use either kind. In a review, that turns one question into one answer: who ships the code that dials Salesforce, and how a change to it reaches you.</p>
<p>Custom connectors are authored from JSON config and can be forked from a public connector. Pulling upstream changes goes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default. The permission to create a connector is flagged high trust, because a custom connector can be pointed at any destination.</p>
<h2 id="where-do-credentials-live-and-how-are-they-encrypted">Where do credentials live, and how are they encrypted?</h2>
<p>In a separate credential service, not in Elaichi itself. That service holds per-account secrets, AES-256-GCM at rest, and owns refresh. Connections created since 2026-10-05 have their credentials placed in the organization's region, by best-effort placement for APAC. Older connections stay where they were until reconnected, which copies them into the region. A failed refresh marks the connection <code>needs_reauth</code> rather than failing quietly at 3am.</p>
<p>Two details security teams tend to probe. A connect URL is not a credential: it is a one-time session carrying no token, which is why it is safe to return over MCP. Read-back of an account's configuration returns public values plus <code>secret_paths</code>, the list of dot-paths that were encrypted, carrying none of their values. Editing one is refused, and the refusal text is identical whichever side produced it, so a caller cannot work out which side said no.</p>
<p>An organization can supply its own OAuth app per connector. The accepted body is <code>client_id</code>, <code>client_secret</code> and scopes, so anything shaped like an endpoint cannot be expressed. It is gated on connector management rather than connection management, so the right to delete a connection never quietly includes repointing the org's OAuth app. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. Composio's pricing page lists customer-managed keys at the Enterprise tier (<a href="https://composio.dev/pricing">composio.dev/pricing</a>, checked October 2026); for key rotation detail, put the question to Composio in writing.</p>
<h2 id="how-many-addresses-do-your-clients-point-at">How many addresses do your clients point at?</h2>
<p>One, in the Elaichi model. Every connected account is served through a single organization-wide endpoint, <code>POST /mcp</code>: standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. There are no per-toolbox URLs and no embedded tokens.</p>
<p>An admin adds that address once wherever the client allows it, and each member then connects and signs in with their own grant. On Claude Team and Enterprise, an owner adds it under Organization settings > Connectors and members connect it themselves (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's connector guide</a>). Cursor's admin MCP allowlist is Enterprise only and does not push a server to anyone's machine (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor's enterprise docs</a>). ChatGPT's full MCP support, write actions included, is a beta on Business, Enterprise and Edu (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help article</a>, as of October 2026). On those plans an admin creates and publishes the app. Pro users get read and fetch only, in developer mode. The steps are in <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>.</p>
<p>What varies per person is the grant, meaning the authorization a member holds after signing in, not the URL they were handed. Nothing sensitive is pasted into a client config, so nothing sensitive can be forwarded to a contractor in Slack.</p>
<p>Composio's MCP Gateway page describes one managed MCP endpoint for all your tools and agents (<a href="https://composio.dev/mcp-gateway">composio.dev/mcp-gateway</a>, checked October 2026). The same page says each team gets its own MCP endpoint, carrying only the tools it is permitted to use. The question to put to any per-team address model is operational rather than moral. Ask how many addresses IT publishes at forty teams, who rotates them, and what happens to a team's address when two teams merge.</p>
<h2 id="how-does-sign-in-line-up-with-your-directory">How does sign-in line up with your directory?</h2>
<p>Through the identity provider you already run, in both products. Elaichi builds SAML and OIDC SSO in house, with no third-party auth vendor, plus SCIM v2 for users and groups and group-to-role mapping. Sign-in also supports Google, GitHub and Microsoft, email codes, TOTP MFA with single-use recovery codes, and passkeys.</p>
<p>Onboarding has four paths: emailed single-use invite links with roles and teams pre-assigned, verified-domain auto-join with a configurable default role, SCIM provisioning, and just-in-time SSO. Domains are verified by DNS TXT record. Composio's pricing page lists SSO and SCIM at the Enterprise tier (<a href="https://composio.dev/pricing">composio.dev/pricing</a>, checked October 2026), so directory sync is a tier question there rather than a missing one.</p>
<h2 id="which-governance-mechanics-hold-up-under-questioning">Which governance mechanics hold up under questioning?</h2>
<p>Three layers, kept separate on purpose. Roles are 58 action strings grouped into personas, with exactly one role per member, enforced by a unique index. Sharing is one building block: a grant of view, use or edit on a resource to a user, a team or the whole org. A member sees only what they own or what was shared with them, and no org-level permission silently widens that listing, owners and admins included. Restrictions decide which connectors and which individual tools a target may reach.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. First rollouts often hit one trap. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>One mechanic belongs in the review file word for word. A block matches the tool's advertised name or the operation recorded when the rule was written; an allow matches that operation only. A tool name can be edited by whoever maintains the connector's documentation, so governance binds the operation and never the label. The reasoning is set out in <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a>. Enforcement runs against the same resolver at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. The <code>tool:execute</code> permission gates the whole endpoint ahead of every scope, so without it the tool list is empty. Guest, Auditor and Billing Admin lack it.</p>
<p>Freshness is the fact most reviews get wrong. A role change or a restriction change takes effect within about two minutes, through a 60-second cache plus edge propagation, on every surface. Member removal and suspension hold from the next call, because the grant is re-read on every single call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<h2 id="what-does-the-model-actually-see">What does the model actually see?</h2>
<p>Less than the full catalog, by default. In Elaichi, connected tools are never listed one by one, however few there are. The model reaches them through two meta-tools: <code>search_tools</code> looks a tool up, and <code>execute_tool</code> calls it. A restricted tool is left out of the tool list and cannot be called. Search names it, flagged restricted, with no schema. And <code>execute_tool</code> is only a naming indirection: it unwraps to the same name and arguments and falls through the identical gates.</p>
<p>Frozen parameters narrow the surface further. A frozen key is dropped from the schema the model is offered. Its value overrides whatever the caller passes at execution, so supplying the key anyway changes nothing. How the search side ranks what is left, and why it returns nothing for a query it cannot match, is worked through in <a href="/blog/search-tools-ranking-floor-idf/">the relevance floor behind search_tools</a>.</p>
<h2 id="what-does-the-audit-trail-tie-an-action-to">What does the audit trail tie an action to?</h2>
<p>An account, an operation and an actor kind. Elaichi writes one record shape for audit events and application logs both, so a single query answers what happened instead of two systems being correlated by eye. The <code>actor_kind</code> field is recorded rather than inferred, and its values include <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from Claude or ChatGPT is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the account the call reached, taken from the execution rather than from the intent. Which of two Notion workspaces the agent wrote to is the first question after an unexpected change. For arguments, the record holds the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<p>Two structural details matter to a reviewer. Each organization's audit history is kept apart from every other organization's, enforced in the type system, because a dropped filter leaks while a wrong scope returns nothing. And two error strings exist per failed call. The one returned to the caller is derived from the third party's response body. The one in the audit trail carries an error code and text never derived from the request or the response. Audit records are org-visible, readable by the in-product assistant and can be forwarded outside Elaichi. A remote error body reaching one would be third-party payload leaving through the log pipe.</p>
<p>The trail inside Elaichi is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog. A free read-only Auditor seat means a compliance reviewer costs no license.</p>
<h2 id="what-happens-when-somebody-leaves">What happens when somebody leaves?</h2>
<p>Removal runs a preflight, and the person's access ends on the next call. The preflight lists every connection the departing member owns. A private connection that a shared toolbox relies on blocks the removal until an admin transfers it to one other active member, never to the admin running the removal, or deletes it. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. A shared connection a team still depends on is deleted only if the admin explicitly asks, so the usual move is transferring it to a member who is staying, which leaves every grant on it as it was. Delegated toolbox entries surface as a non-blocking warning, and re-pinning is the fix rather than a credential decision.</p>
<p>Once the removal goes through, access ends in every client at once. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The case for people who were never employees is covered in <a href="/blog/offboarding-when-the-agent-holds-access/">what to do about contractor access today</a>.</p>
<h2 id="what-does-elaichi-not-claim">What does Elaichi not claim?</h2>
<p>Two things, stated plainly, because a review will find them anyway.</p>
<p>The first is a prompt-injection gate on tool calls. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees a user prompt, so no gate of that kind can sit on the endpoint. What does hold there is role checks per operation, the forbidden classification that no OAuth scope can reach, output redaction, scope limits and an audit row for each call that reaches execution.</p>
<p>The second is total erasure. Deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name. It never claims everything is gone.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page puts the credential model, sharing and per-person attribution in one place, written for the reviewer who signs off.</p><a href="/security/" class="cta-button">See the security page</a></aside>
<h2 id="where-is-composio-the-better-fit-and-where-do-you-need-neither">Where is Composio the better fit, and where do you need neither?</h2>
<p>Composio's homepage names end users who want an AI assistant to act in their apps, and developers building agents (<a href="https://composio.dev">composio.dev</a>, checked October 2026). Its docs describe SDK sessions created for each of your users, tying together that user's toolkits, auth and connected accounts (<a href="https://docs.composio.dev/docs/sessions-vs-direct-execution">Composio's sessions docs</a>, checked October 2026). If you are shipping an agent product and each of your customers' users needs their own auth session, that is the reader those docs were written for. A control plane built around your employees is the wrong tool for that job.</p>
<p>There is also the case where the answer is neither. Eight people, one connected app, one AI client and a named owner do not need a governance layer yet. That case is argued in full in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when a gateway is premature</a>.</p>
<p>If you are running the two vendors side by side, the feature-level view sits in <a href="/blog/elaichi-vs-composio/">Elaichi vs Composio for company-wide MCP access</a>. To check which of your systems already have a native connector, browse the <a href="/connectors/">connector catalog</a>. If the rollout is one department at a time, start from the <a href="/use-cases/">team use cases</a>. Gold lists at $15 per user per month in USD, or $120 per user per year, with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. <a href="/pricing/">Pricing</a> shows the local price where one applies.</p>
<h2>FAQ</h2><dl><dt><strong>Does Composio support SSO, role-based permissions and audit logging?</strong></dt><dd>Yes, by its own description. Composio's enterprise page describes permissions set administratively per user and per role down to the individual action, every tool call logged with the user, team, tool, action and outcome including denied calls, SSO over SAML and OIDC, and self-hosting at the Enterprise tier (composio.dev/enterprise, checked October 2026). Its certifications are Composio's own claims, so request the reports from Composio and read their scope and period.</dd><dt><strong>What should a security review read in a SOC 2 Type II report?</strong></dt><dd>Read the period end date, the exceptions the auditor noted, the systems named in scope, and the carve-outs for subservice organizations such as cloud and logging vendors. A SOC 2 examination covers the service organization's own description of its system and the controls in it, so it does not confirm that the product you are buying was inside that scope. Scope and exceptions matter more than the badge.</dd><dt><strong>Where does Elaichi store connector credentials?</strong></dt><dd>Not in Elaichi. A separate credential service holds per-account secrets encrypted with AES-256-GCM at rest and owns token refresh, and a failed refresh marks the connection needs_reauth rather than failing silently. An organization can supply its own OAuth app per connector using only a client ID, client secret and scopes. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon.</dd><dt><strong>How quickly does a permission change take effect in Elaichi?</strong></dt><dd>A role change or a restriction change takes effect within about two minutes, because both resolve through a 60-second cache plus edge propagation on every surface. Member removal and suspension hold from the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call.</dd><dt><strong>Can an Elaichi restriction apply to every member at once?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything, so a company-wide limit is written as a rule on every role. Within each layer blocks always beat allows. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>MintMCP alternative when you run no MCP servers</title>
      <link>https://elaichi.ai/blog/mintmcp-alternative/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mintmcp-alternative/</guid>
      <description>If you run no MCP servers, Elaichi is a MintMCP alternative that writes and hosts its own connectors and serves them through one MCP endpoint.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> If your company runs no MCP servers, the MintMCP alternative to weigh is one that is the server itself rather than a gateway in front of servers. Elaichi serves 600+ connectors, most of them its own, through one organization-wide MCP endpoint that Claude, ChatGPT and Cursor can each be pointed at. A hosted gateway over a large server catalog fits a team that wants breadth quickly, or has MCP servers of its own to host. Choose by who your users are and how many addresses your rollout produces.</aside>
<h2 id="what-is-the-mintmcp-alternative-if-you-run-no-mcp-servers">What is the MintMCP alternative if you run no MCP servers?</h2>
<p>If you run no MCP servers, the MintMCP alternative to weigh is one that is the server itself, not only a gateway in front of servers. Elaichi is that shape: it writes, hosts and serves most of its connectors, and governs vendors' own MCP servers for the rest. Every AI client reaches them through one organization-wide MCP endpoint, so your team has nothing to run.</p>
<p>Someone in support pointed Claude at a work tool last week and it worked. Now finance wants the same thing, and you have to decide what the company buys. Two different products sit behind the word gateway. One is a hosted gateway over a catalog of MCP servers the vendor lists. The other is a control plane whose connectors the vendor writes and runs itself. That fork decides more than the headline catalog number does.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>MintMCP's gateway page describes a hosted MCP gateway with a large catalog of servers, and it quotes a customer who needed one that "hosts our MCPs and manages credentials" (<a href="https://www.mintmcp.com/mcp-gateway">mintmcp.com/mcp-gateway</a>, checked October 2026). Elaichi's endpoint, by contrast, is a single network address a client signs in to, with connectors Elaichi maintains on its own infrastructure behind it. Both shapes are real. They fit different readers.</p>
<table>
<thead>
<tr>
<th>Axis</th>
<th>MintMCP</th>
<th>Elaichi</th>
</tr>
</thead>
<tbody>
<tr>
<td>What you run</td>
<td>A gateway fronting MCP servers, MintMCP-hosted or your own (<a href="https://www.mintmcp.com/mcp-gateway">mintmcp.com/mcp-gateway</a>, checked October 2026)</td>
<td>Nothing; Elaichi is the MCP server itself</td>
</tr>
<tr>
<td>Connector authorship</td>
<td>A catalog of MCP servers hosted or listed by MintMCP</td>
<td>Elaichi serves 600+ connectors, authoring most itself and governing vendors' own MCP servers for the rest</td>
</tr>
<tr>
<td>Per-org audit</td>
<td>Ask MintMCP what one record holds</td>
<td>Audit history kept apart for each organization; <code>actor_kind</code> on every entry; export to your Datadog with the Black plan, launching soon</td>
</tr>
<tr>
<td>Tool-list unification</td>
<td>Many servers behind one gateway; ask how many endpoints a rollout produces</td>
<td>One <code>POST /mcp</code> endpoint for every connected account</td>
</tr>
<tr>
<td>Offboarding</td>
<td>Ask MintMCP what happens on a member's last day</td>
<td>Grants revoked on the next call; a preflight lists every connection the member owns; a shared one can be transferred to another active member, and a private one nothing depends on is deleted with the member</td>
</tr>
<tr>
<td>Pricing model</td>
<td>Ask MintMCP for the billing unit</td>
<td>Per seat: Gold lists at $15 per user per month in USD, with a 14-day trial</td>
</tr>
</tbody>
</table>
<h2 id="why-does-it-matter-who-authors-the-connector">Why does it matter who authors the connector?</h2>
<p>Authorship decides who you call when a tool breaks, and what a governance rule is allowed to bind to. A catalog of servers other people run is also a catalog of other people's release schedules.</p>
<p>Elaichi ships 600+ connectors, and most are its own. The rest are native MCP connectors, vendors' own servers that Elaichi staff publish one at a time rather than pulling in a registry. Companies do not run MCP servers to use either kind. Custom connectors are authored from JSON config. They can be forked from a public connector. A fork can pull upstream changes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default, so nobody accepts a deletion by clicking through. A connector cannot be deleted while connections still use it.</p>
<p>The trade-off is plain. An authored connector makes the tool surface one party's responsibility: the tool names, the argument schemas and the operation each tool maps to. The cost is reach. The catalog grows only as fast as one vendor writes connectors, and an app outside it means building a custom one.</p>
<h2 id="when-is-mintmcp-the-better-buy">When is MintMCP the better buy?</h2>
<p>MintMCP is the better buy when breadth of servers matters more than who wrote them. MintMCP's gateway page describes hosted connectors, a large server catalog, and a customer who wanted a gateway that "hosts our MCPs and manages credentials" (<a href="https://www.mintmcp.com/mcp-gateway">mintmcp.com/mcp-gateway</a>, checked October 2026). Two readers should weigh that seriously.</p>
<ul>
<li>The team that needs one unusual server this month. A large server catalog is the likelier place to find it. Elaichi's catalog of 600+ connectors either has the app or it does not.</li>
<li>The platform team that has written MCP servers of its own and wants them hosted, with the credentials managed for it. Elaichi does not host servers a company wrote. It is the server for the connectors it authors and any your team builds from JSON config, and a company server added as a remote MCP connector still runs on your side.</li>
</ul>
<p>If the app you need is niche and you need it next week, breadth wins. If your problem is that nobody can say what the agent may call, authorship wins.</p>
<p>A different reader wants a door rather than a catalog. Two internal servers and a handful of vendor servers need one address in front of them. The governance question is per server rather than per tool. For that reader a gateway is the right object to buy, and several products are built for it.</p>
<p>Lunar.dev describes MCPX as a self-hosted enterprise MCP gateway sitting between agents and the MCP servers, APIs and LLM providers they use. It has an open-source version on GitHub (<a href="https://www.lunar.dev/">lunar.dev</a>, checked October 2026). Tyk describes an MCP Gateway that proxies and governs remote MCP servers (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">tyk.io</a>, checked October 2026). Zuplo describes an MCP Gateway that federates MCP servers behind one OAuth-protected gateway (<a href="https://zuplo.com/mcp-gateway">zuplo.com</a>, checked October 2026). OAuth here is the sign-in flow that hands a client a revocable grant instead of a password.</p>
<p>If your users are platform engineers, that shape reads naturally. If they sit in finance and legal, it reads like a project. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">What running MCP servers yourself really costs</a> works through that estate. <a href="/blog/best-mcp-gateways/">A wider comparison of MCP gateways</a> sets the other products side by side.</p>
<h2 id="who-is-elaichi-built-for">Who is Elaichi built for?</h2>
<p>The IT or operations lead whose users sit in support, finance, sales and legal. The job is pointing three different AI clients at the same company data. A MintMCP alternative of this shape is judged on the address model and on who maintains the connector, not on server count.</p>
<p>Elaichi serves one organization-wide endpoint: <code>POST /mcp</code>, standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. Claude, ChatGPT and Cursor all point at that one address. An admin adds it once where the client allows, and each member then connects and signs in with their own grant. Any other MCP client uses the same address. There are no per-toolbox URLs and no embedded tokens. A toolbox is a saved set of tools with the accounts behind them, and it does not get its own URL. The twelve teams on the <a href="/use-cases/">use cases page</a> are the same list of readers.</p>
<h2 id="how-many-addresses-does-the-rollout-produce">How many addresses does the rollout produce?</h2>
<p>With Elaichi, one. Clients point at the single endpoint and each person signs in as themselves. There is no MCP server to create, list or revoke per user, because the address is fixed and the grant is what varies. Adding a fourth client later is the same piece of work as the first three.</p>
<p>Other shapes multiply what sits behind the address. On Zapier MCP every client shares one URL, but "Each MCP client gets its own MCP server", so each member holds a server per client (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">docs.zapier.com</a>, checked October 2026). That is the per-member shape covered in <a href="/blog/zapier-mcp-alternative/">one organization server, not one per member</a>. Composio's MCP Gateway page says "each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">composio.dev</a>, checked October 2026). The <a href="/blog/elaichi-vs-composio/">side-by-side on company-wide access</a> works through what that means day to day.</p>
<p>Count the addresses and servers a 200-person rollout produces before you count the connectors. One number changes your support load and the other does not.</p>
<h2 id="can-renaming-a-tool-get-around-a-rule">Can renaming a tool get around a rule?</h2>
<p>No. In Elaichi, a rule binds to an operation, not to a label a vendor controls. Three layers stay separate. Permissions are 58 action strings grouped into roles, with exactly one role per member, so each role is a complete persona. Resource sharing is a grant of view, use or edit on a resource to a person, a team or the whole organization. A member sees only what they own or what was shared with them. Restrictions decide which connectors and which individual tools a target may reach.</p>
<p>By design, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. Note that the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything.</p>
<p>A block catches a tool by its name or by the operation behind it. An allow counts only the operation, because whoever edits the connector's documentation can change a tool's displayed name. That asymmetry has its own post: <a href="/blog/block-matches-name-allow-matches-operation/">why block matches the name and allow matches the operation</a>. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A role or restriction change takes effect within about two minutes. Grant revocation, member removal and suspension are effective on the next call, and so are revoking a share and disconnecting an account.</p>
<h2 id="can-you-freeze-an-argument-the-model-should-never-set">Can you freeze an argument the model should never set?</h2>
<p>Yes. Frozen parameters are a per-entry map over a tool's flattened argument space, and they work in two directions at once. Frozen keys are removed from the schema the model is shown, so it has no argument to set. Frozen values are merged over caller arguments at execution, so passing the key cannot unfreeze it.</p>
<p>The full precedence is entry defaults, then caller or model arguments, then frozen parameters. Because Elaichi authors the execution path, the same mechanism applies to every connector rather than to the subset that happens to support it.</p>
<h2 id="how-does-the-model-find-a-connected-tool">How does the model find a connected tool?</h2>
<p>In Elaichi, connected tools are never listed one by one, however few there are. A model reaches one by searching with <code>search_tools</code>, then calling it through <code>execute_tool</code>.</p>
<p>Control-plane operations stay listed individually, and <code>search_tools</code> never returns one. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. Running a tool through <code>execute_tool</code> adds no privilege: it unwraps to the same name and arguments and falls through the identical gates. Ranking is lexical, with a relevance floor that keeps a vague query from returning a tool from the app you did not ask about. The reasoning is set out in <a href="/blog/search-tools-ranking-floor-idf/">how the search ranking floor works</a>.</p>
<h2 id="what-counts-as-a-credential-and-where-does-it-live">What counts as a credential, and where does it live?</h2>
<p>In Elaichi, the URL is not a credential. <code>POST /mcp</code> is a single address behind OAuth with no token embedded in it, so knowing it grants nothing. The MCP authorization spec rules out the alternative for any server: access tokens "MUST NOT be included in the URI query string" (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization</a>). A connect URL is not a credential either. It is a one-time session that carries no token, which is why it is safe to return over MCP.</p>
<p>Connector credentials never live in Elaichi. A separate credential service holds per-account secrets, encrypted with AES-256-GCM at rest, and owns refresh. Connections created since 2026-10-05 have their credentials placed in the organization's region: inside the EU or US jurisdiction for those regions, and by best-effort placement for APAC. Older connections stay where they were until reconnected, which copies them into the region. A failed refresh marks the connection <code>needs_reauth</code> rather than failing silently. Reading back an account's configuration returns public values plus <code>secret_paths</code>, the list of dot-paths that were encrypted, carrying none of their values.</p>
<p>An organization can supply its own OAuth app per connector. That right is gated on <code>connector:manage</code>, not <code>connection:manage</code>. Otherwise everyone who can delete a connection would also gain the power to repoint the organization's OAuth app. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon, as the <a href="/pricing/">pricing page</a> shows.</p>
<h2 id="what-happens-to-a-members-access-on-their-last-day">What happens to a member's access on their last day?</h2>
<p>On Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Before the removal goes through, a preflight checks the connections that member owns.</p>
<p>The preflight lists every connection they own, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until the admin transfers it to an active member. A private connection nothing else depends on cannot be transferred and is deleted with the member. A connection is never handed to the organization, to a team, or to the admin running the removal. Delegated toolbox entries surface as a non-blocking warning, and re-pinning the entry is the fix.</p>
<p>A shared connection a team still depends on is left untouched unless the admin deletes it. The admin transfers it to a member who is staying, which leaves every grant on the connection exactly as it was.</p>
<h2 id="what-does-the-audit-trail-record">What does the audit trail record?</h2>
<p>What one MintMCP record holds, and whether it names the account a call reached, is a question to put to MintMCP. On Elaichi's side, the useful test is the first question after an unexpected change: which of two Notion workspaces did the agent write to?</p>
<p>Elaichi's audit log keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the account the call actually reached, not the one it was aimed at. A field called <code>actor_kind</code> records who acted, instead of leaving it to be guessed from a user agent. A call from Claude or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. Each organization's audit history is kept apart, and a compliance reviewer costs nothing, because the read-only Auditor role is a free seat. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> covers the fields in full.</p>
<h2 id="questions-to-put-to-mintmcp-before-you-sign">Questions to put to MintMCP before you sign</h2>
<p>Seven questions settle most of this comparison, and MintMCP should answer them in writing. A comparison page, this one included, is no substitute for the vendor's own answer.</p>
<ul>
<li>Which servers in the catalog do you author, which are third party, and who fixes one when its upstream API changes?</li>
<li>How many gateway URLs exist once 200 members are onboarded, and who can revoke one?</li>
<li>Where are connector secrets held, who can read them back, and can we bring our own OAuth app?</li>
<li>What happens to a member's access on the day they leave our directory?</li>
<li>What does one audit record hold, and does it name the account a call reached?</li>
<li>What is the billing unit: seats, tool calls or servers?</li>
<li>Which region holds the data, and what exactly does the region cover?</li>
</ul>
<p>Elaichi's answer to the last one is three regions, EU, US and APAC, chosen when the organization is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. The audit trail is stored in one EU log instance for every region. More of the security detail sits on the <a href="/security/">security page</a>.</p>
<h2 id="when-does-neither-shape-earn-the-spend-yet">When does neither shape earn the spend yet?</h2>
<p>If four people each use one app with their own account, and you can still name every tool call from memory, buy nothing. Write the list down, turn on the AI client's own admin controls, and revisit when a second team asks. Buy one of the two shapes when you cannot answer who reached what, or when removing somebody takes more than one action. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The threshold test for a gateway</a> lists the other signals.</p>
<p>One limit applies before you shop at all. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on the endpoint is permission checks per operation and the <code>forbidden</code> classification, which no OAuth scope can reach. Output redaction, scope limits and an audit row for each call that reaches execution hold too. Ask any vendor that claims prompt-injection protection exactly what it inspects, and where.</p>
<p>If the shape fits, the next two pages are the <a href="/connectors/">connector catalog</a> and <a href="/pricing/">plan pricing</a>. Elaichi has two plans, Gold and Black. Gold lists at $15 per user per month in USD, and the pricing page shows the price for your region. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two.</p>
<h2>FAQ</h2><dl><dt><strong>What is a MintMCP alternative for a company that does not run its own MCP servers?</strong></dt><dd>Elaichi is the shape built for that case. MintMCP's gateway page describes a hosted MCP gateway with a large catalog of servers, and quotes a customer who needed one that "hosts our MCPs and manages credentials" (https://www.mintmcp.com/mcp-gateway, checked October 2026). Elaichi instead serves 600+ connectors, authoring and maintaining most on its own infrastructure, and exposes them through one organization-wide MCP endpoint at POST /mcp. Claude, ChatGPT and Cursor all point at that single address, with no per-toolbox URLs and no embedded tokens. Each member connects once and signs in with their own OAuth grant.</dd><dt><strong>When is MintMCP a better buy than Elaichi?</strong></dt><dd>When breadth of servers matters more than who authors them. MintMCP's gateway page describes hosted connectors, a large server catalog, and a customer who wanted a gateway that "hosts our MCPs and manages credentials" (https://www.mintmcp.com/mcp-gateway, checked October 2026). A team that needs one unusual server this month, or that has written MCP servers of its own and wants them hosted, is that reader. Elaichi authors most of its 600+ connectors itself and does not host servers a company runs. An app outside its catalog means building a custom connector from JSON config, or adding the app's remote MCP server as the organization's own connector.</dd><dt><strong>Does Elaichi sit in front of MCP servers we already run?</strong></dt><dd>Not as its main job. Elaichi is the MCP server for the connectors it authors, and it governs vendors' own MCP servers in its catalog. On Gold, or on Black once it launches, an Org Owner or Org Admin can add a server the company runs as its own remote MCP connector, if it is reachable over public HTTPS. If the requirement is a door in front of internal servers your engineers built, a self-hosted or federating gateway is the right shape to evaluate, and the trade-offs are covered at https://elaichi.ai/blog/self-hosted-mcp-servers-vs-control-plane/.</dd><dt><strong>How quickly does a permission or restriction change take effect in Elaichi?</strong></dt><dd>A role change or a restriction change takes effect within about two minutes, because both resolve through a 60-second cache plus edge propagation on every surface. Grant revocation, member removal and suspension are faster and take effect on the next call, and so do revoking a share and disconnecting an account. The revocation flag is re-read from the organization store on every single call, and removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Is a private connection transferred when a member is offboarded from Elaichi?</strong></dt><dd>It can be. Offboarding runs a preflight that lists every connection the departing member owns, private and shared alike. A private connection that a shared toolbox still relies on blocks the removal until the admin transfers it to another active member. A private connection nothing else depends on cannot be transferred and is deleted with the member. A connection is never handed to the organization, to a team, or to the admin running the removal. A shared connection a team depends on is left untouched unless the admin deletes it; the admin transfers it to a member who is staying, which leaves every grant on it as it was. Delegated toolbox entries surface as a non-blocking warning.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>HR can read Rippling in Claude, not run payroll</title>
      <link>https://elaichi.ai/blog/hr-team-claude-rippling-employees/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/hr-team-claude-rippling-employees/</guid>
      <description>HR can read Rippling in Claude through Elaichi: workers, teams and departments. The connector has no payroll-run tool, and one rule keeps HR to reads.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi gives an HR team Rippling in Claude through one organization-wide MCP endpoint. The catalog's Rippling connector has no tool that runs payroll or terminates a worker, and an allow rule on the HR role limits the team to reads, so every write, and any tool the connector gains later, stays out of reach. The audit trail records one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and a rule change takes about two minutes to take effect.</aside>
<h2 id="what-can-hr-do-with-rippling-in-claude">What can HR do with Rippling in Claude?</h2>
<p>HR can read Rippling in Claude through Elaichi, and cannot run payroll from it. The questions HR asks are lookups: who reports to whom, which department and work location a person sits in, which employment type a contractor is on. Elaichi's <a href="/connectors/rippling/">Rippling connector</a> answers them with read tools such as <code>list_all_rippling_workers</code>. It has no tool that runs payroll or terminates a worker, so neither can happen through it, whatever a prompt says.</p>
<p>The writes the connector does carry are narrower. They create, change and delete custom objects and their records, add and remove business partners, and change supergroup membership. One allow rule on the HR role keeps all of them out of reach. Rippling sits in the <a href="/connectors/category/hris/">HRIS category</a> with the other HR systems Elaichi connects.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves Rippling's tools from one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth (the sign-in flow that gives a client a scoped grant instead of a password). In Claude Team and Enterprise, an owner adds that address once under Organization settings > Connectors. Each HR member then connects it under Customize > Connectors and signs in with their own grant. On Pro and Max, each person adds it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Claude's help center</a>, as of October 2026). Rippling is a connector Elaichi authors, maintains and serves from its own infrastructure, one of 600+ in its catalog.</p>
<h2 id="how-do-you-set-up-rippling-in-claude-for-an-hr-team">How do you set up Rippling in Claude for an HR team?</h2>
<p>Connect Rippling privately, check the HR role, write the rule, pin the reads into a toolbox, and only then share the toolbox. Sharing comes last because, until a rule exists, the default is allow-all.</p>
<ol>
<li>Connect the Rippling account and keep the connection private. Calls through a shared connection run on its owner's Rippling account, so Rippling sees and logs that one user for the whole team. Connect it with an account whose Rippling permissions fit everyone it serves, and who will stay. Credentials never live in Elaichi. A separate credential service holds per-account secrets, AES-256-GCM at rest, and owns refresh. A failed refresh marks the connection <code>needs_reauth</code> rather than failing quietly.</li>
<li>Check the role. Every member carries exactly one role, enforced by a unique index, so the HR role is a complete persona rather than an add-on. It needs <code>tool:execute</code>, which gates the whole endpoint ahead of every other check. Without it, <code>tools/list</code> comes back empty and a call returns an in-band error naming the permission.</li>
<li>Write the rule. A restriction is a rule about which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</li>
<li>Pin the reads into a toolbox, freezing any argument the model should not choose.</li>
<li>Share the toolbox with the HR team, with <code>use</code>. Sharing is one building block: a grant of <code>view</code>, <code>use</code> or <code>edit</code>, given to one user, one team or everyone in the organization. A member sees only what they own or what was shared with them, and no organization-level permission widens that, owners and admins included.</li>
<li>Add the endpoint in Claude and have the HR team sign in.</li>
</ol>
<p>If the HR group already lives in your identity provider, SCIM v2 can provision its members and map the group to the HR role.</p>
<p>One caution on step 3. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A rule for one HR manager can narrow what the HR role allows and cannot add to it. To let one person past a role rule, they file an access request and an admin approves it.</p>
<h2 id="should-hr-allow-ripplings-reads-or-block-its-writes">Should HR allow Rippling's reads or block its writes?</h2>
<p>Allow the reads. An allow rule naming the people reads, such as <code>list_all_rippling_workers</code>, <code>list_all_rippling_departments</code> and <code>list_all_rippling_teams</code>, shuts out everything it does not name. That covers every write on the connector. Any tool the connector gains later also stays closed for HR until someone adds it on purpose, which is the property a promise about payroll needs.</p>
<p>One caveat before you save it. Once the HR role holds an allow rule, every connector that no allow rule on that role names is denied for the role, not only Rippling's other tools. Allow rules on the same role add up, so give the HR role an allow rule for each other app it uses, naming the whole connector where that is enough, or the team loses those apps.</p>
<p>The cost is upkeep, plus one sharp edge. Each new read HR wants is one more entry in the rule. And the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. After saving, ask Claude to find one of the reads to confirm it is still there.</p>
<p>Know what a read returns, too. The <code>list_all_rippling_workers</code> tool returns each worker's compensation and termination details along with title and manager. Share the toolbox only with the people who may see pay. Rippling sees every call as the connection owner's account, so choose an owner whose Rippling permissions fit the whole team. Elaichi's rules narrow what HR reaches; they never widen it past what the Rippling account behind the connection allows.</p>
<p>A block list is the other shape. Block the writes by name and leave every read open, including reads the connector gains later. The mirror-image cost is that a write added later stays open until someone blocks it. Blocks still help as a backstop: they always beat allows within a layer, so a block holds even if someone later widens the allow rule.</p>
<p>The two rule types also match differently. A block matches on the tool name or on the pinned operation, the canonical action under the name, while an allow matches on the pinned operation only. Whoever edits the connector's documentation can change a tool's advertised name, so the name is a token the governed party controls. The <a href="/blog/block-matches-name-allow-matches-operation/">reasoning behind that split</a> matters most for long rule sets.</p>
<p>OAuth scopes add a second layer. A delete such as <code>delete_a_rippling_custom_object_record_by_id</code> also needs <code>mcp:destructive</code> on the grant, and a tool classified <code>forbidden</code> is reachable under no scope.</p>
<h2 id="can-hr-see-the-withheld-rippling-tools-in-claude">Can HR see the withheld Rippling tools in Claude?</h2>
<p>Only by name. Elaichi checks the rule at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A tool the HR rule withholds is left out of the tool list and cannot be called. If Claude searches for it, Claude sees the name, flagged restricted, with no schema. The model cannot be talked into running it.</p>
<p>In MCP, a client learns what a server offers by sending a <code>tools/list</code> request. The specification lets that list vary with the authorization on the request (<a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a>). In Elaichi, connected tools are never listed one by one, however few there are. Claude looks a Rippling tool up with <code>search_tools</code> and calls it through <code>execute_tool</code>, and a withheld tool comes back from that search only by name, flagged restricted.</p>
<p>Search has a relevance floor, so a weak match returns nothing rather than a tool from an app you did not ask about. The <a href="/blog/search-tools-ranking-floor-idf/">reasoning behind the floor</a> is written up separately.</p>
<h2 id="which-rippling-arguments-should-hr-freeze">Which Rippling arguments should HR freeze?</h2>
<p>Freeze any argument whose value should be settled before the model sees the tool. Frozen parameters are a per-entry map over a tool's flattened argument space, set on a toolbox entry (one tool tied to one connected account). A frozen key is removed from the schema Claude is shown, so there is nothing for the model to fill in. A frozen value is merged over the caller's arguments at execution, so passing the key anyway cannot un-freeze it. The order runs entry defaults, then caller and model arguments, then frozen parameters, and the frozen value wins.</p>
<p>Custom objects are the clearest HR case. If you keep HR data in a Rippling custom object, allow <code>list_all_rippling_custom_object_records</code> and freeze its <code>custom_object_api_name</code> to that one object. HR then reads that object's records, and no question can widen the read to every custom object in the account.</p>
<p>The lock belongs to the toolbox entry, so it holds only for calls made through that entry. If HR also has <code>use</code> on the Rippling connection itself, the unfrozen tool is reachable directly. That is why the Rippling connection stays private and only the toolbox goes to HR.</p>
<h2 id="how-do-you-prove-no-ai-client-changed-anything-in-rippling">How do you prove no AI client changed anything in Rippling?</h2>
<p>Filter the audit trail. It holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection on every entry is the account the call reached, read from what executed rather than from what was requested. That matters the day an unexpected change shows up and you run two Rippling environments.</p>
<p>Each entry carries the operation and tool, the connection, the classification and whether the call was approved, with its outcome and an error code when it failed. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments, so a worker's details passed into a call stay out of it.</p>
<p>The <code>actor_kind</code> field is recorded, not inferred. Its values include <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks only the Elaichi Agent. A call from Claude is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named, and Claude is marked verified. "Did Claude change a record" then has an answer in the entry rather than an argument.</p>
<p>To produce the evidence, filter by connection, action kind and time range. The trail is append-only, newest-first and cursor-paginated, and it also filters by free text, category and actor. A departed member shows as "Former member" rather than vanishing. It is eventually consistent, so pull the report after the fact rather than mid-call. Give the reviewer the Auditor role, a free read-only seat that lacks <code>tool:execute</code>, so no tool call is possible from it. The trail inside Elaichi is on Gold. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon.</p>
<h2 id="does-the-employee-data-stay-in-the-eu">Does the employee data stay in the EU?</h2>
<p>Partly. Elaichi has three regions, <code>eu</code>, <code>us</code> and <code>apac</code>. For an <code>eu</code> organization, the data store and the execution of its org-scoped requests and tool calls are pinned to the EU. User accounts, sign-in sessions, API tokens, SSO settings and MCP OAuth token records are kept globally. Every organization's audit trail, whatever its region, is stored in one log instance in the EU, and files stored from tool results go to one private EU bucket. Connections created since 2026-10-05 have their credentials placed in the organization's region. Older connections stay where they were until reconnected.</p>
<p>Pick the region when you create the organization, because it cannot change later. Where Rippling keeps its own records is Rippling's setting, not Elaichi's.</p>
<h2 id="why-not-use-ripplings-own-mcp-server">Why not use Rippling's own MCP server?</h2>
<p>If Rippling is the only app HR will reach from an AI client, Rippling's own server may be the simpler choice. Rippling calls it "a first-party Model Context Protocol (MCP) connection" (<a href="https://developer.rippling.com/documentation/rippling-platform/rippling-mcp/overview">Rippling's MCP overview</a>, checked October 2026). It works "while strictly enforcing your company's security policies and role-based permissions". The server is hosted by Rippling and exposes "curated, approved tools". Its MCP Gateway is "the admin control panel for who can connect to the Rippling MCP and which tools they receive access to". That is Rippling's own permission model, with no second vendor to review.</p>
<p>Elaichi earns a place once HR works in more than one app. One address serves Rippling, <a href="/connectors/greenhouse/">Greenhouse</a> and Slack, in Claude, ChatGPT and Cursor alike. A single set of rules on the HR role covers all of them, and a frozen argument can pin any tool's input. The audit trail spans every connected app, and removing a person ends their access through Elaichi to every one of those apps at once. Their accounts inside each app are a separate step. Rippling's overview does not describe those cross-app pieces, and they are what a second vendor has to justify.</p>
<h2 id="what-does-this-setup-not-prove">What does this setup not prove?</h2>
<p>It governs the MCP path and nothing else. Someone who signs into Rippling's own web app and runs payroll there leaves a record in Rippling, not in Elaichi. If your control objective is "nobody ran payroll", you need both trails. If it is "no AI client ran payroll", the Elaichi trail answers it on its own.</p>
<p>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What the endpoint does enforce is narrower: permission checks per operation, the <code>forbidden</code> classification, redaction of output, limits set by OAuth scopes, and an audit row for each call that reaches execution.</p>
<p>Timing is the fact most often stated wrongly. A role or restriction change takes effect within about two minutes, on MCP, console and REST alike. Grant revocation, member removal and suspension are effective on the next call. Tell the HR lead two minutes.</p>
<h2 id="when-is-a-control-plane-too-much-for-hr">When is a control plane too much for HR?</h2>
<p>If one HR person uses one Rippling login and no other app is connected, none of this earns its upkeep. Rippling's own server, or no AI client at all, is a smaller problem than a control plane nobody owns. The same holds when the assistant only needs a read-only handbook and touches nothing that can change state.</p>
<p>The case for <a href="/blog/when-you-dont-need-an-mcp-gateway/">holding off on a gateway</a> is real, and it reads best before a rollout rather than after one. Governance starts paying when a second system joins, when more than one person holds the credential, or when someone outside HR has to answer what the assistant did.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>To check a tool's exact name before you write a rule, the Rippling connector page lists them all.</p><a href="/connectors/rippling/" class="cta-button">Open the Rippling connector</a></aside>
<h2 id="what-happens-when-someone-leaves-the-hr-team">What happens when someone leaves the HR team?</h2>
<p>Their access ends on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's <code>revoked_at</code> flag is re-read from the organization store on every call, so a removed or suspended member's next call fails.</p>
<p>Removal also runs a preflight. It lists every connection the departing member owns. A private connection a shared toolbox relies on blocks the removal until an admin transfers it to one other active member, never to the admin running the removal, or deletes it. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. A shared connection the HR team still depends on is deleted only if the admin explicitly asks, so transfer it to someone who is staying, which leaves every grant on it as it was.</p>
<p>A move sideways, from HR into a narrower role, is a role change. Budget about two minutes for it rather than the next call.</p>
<p>For the same setup on the revenue side, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">how a sales team gets scoped Salesforce access in ChatGPT</a>. For the harder version of the leaver question, read the <a href="/blog/offboarding-when-the-agent-holds-access/">contractor access walkthrough</a>. The full catalog is at <a href="/connectors/">/connectors/</a>, and the other eleven teams are mapped at <a href="/use-cases/">/use-cases/</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Can HR read Rippling in Claude without being able to run payroll?</strong></dt><dd>Yes. Elaichi's Rippling connector has no tool that runs payroll or terminates a worker, so neither can be called through it. Its writes change custom objects, business partners and supergroup membership. An allow rule on the HR role that names only the reads keeps those writes out of reach, and a withheld tool cannot be called.</dd><dt><strong>Should HR use Rippling's own MCP server instead of Elaichi?</strong></dt><dd>It can, if Rippling is the only app HR reaches from an AI client. Rippling hosts its own MCP server, which enforces Rippling's role-based permissions, and its MCP Gateway lets admins choose who connects and which tools each person gets. Elaichi adds one address across Rippling and the other apps HR uses, one set of role rules and one audit trail across all of them, frozen arguments, and one removal that ends access through Elaichi to all of them.</dd><dt><strong>How long does a restriction or role change take to apply?</strong></dt><dd>It takes about two minutes. Role membership and restrictions in Elaichi pass through a 60-second cache before they reach every surface, MCP, console and REST alike. Grant revocation, member removal and suspension take effect on the next call, and so do revoking a share and disconnecting an account, because the revocation flag is re-read from the organization store on every single call.</dd><dt><strong>Can a restriction target a whole team?</strong></dt><dd>No. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. So scoping is done by writing rules against roles and then, where needed, against individual users. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</dd><dt><strong>Does the audit log show which Rippling account an AI client reached?</strong></dt><dd>Yes. The trail holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and the connection on each entry is the account the call actually reached, read from the execution rather than the request. Entries also carry the operation and tool, the classification, whether the call was approved, its outcome, an error code, an actor_kind field, and the surface and OAuth client the call came through. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments.</dd><dt><strong>Does a compliance reviewer need a paid seat to read the audit trail?</strong></dt><dd>No. The Auditor role in Elaichi is a free, read-only seat and is excluded from the billable seat count, along with Guest and Billing Admin. Auditor lacks the tool:execute permission, so the MCP tool list comes back empty for that member and no tool call is possible from the seat.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Restrict one AI tool or the whole app? Six cases</title>
      <link>https://elaichi.ai/blog/per-tool-vs-per-app-restrictions/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/per-tool-vs-per-app-restrictions/</guid>
      <description>Restrict one AI tool when a role needs part of an app, and block the whole app when it needs none of it. Six cases, and what new tools do to each rule.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, a restriction can name a whole connector or individual tools, for a role or for one user. Blocking the whole app also covers tools added later. A rule that restricts one AI tool keeps the rest of the app working, but it is a list someone has to maintain as the connector changes. Block the app when the role has no business in it, and name tools when the role needs a narrow slice of a broad app.</aside>
<h2 id="when-should-you-restrict-one-ai-tool-instead-of-the-whole-app">When should you restrict one AI tool instead of the whole app?</h2>
<p>Restrict one AI tool when a role needs part of an app and not all of it. Block the whole app when the role has no business there, or when the app gains tools faster than anyone reviews them. The question usually arrives with a helpdesk. Support needs to read tickets and post comments, and nobody wants the Support role bulk-deleting saved views.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A restriction in Elaichi decides which connectors and which individual tools a target may reach. It can name a whole connector, meaning one connected app, or individual tools inside it. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Inside each layer, allow rules add up, block rules add up, and a block always beats an allow.</p>
<p><a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP's entry on excessive agency</a> in LLM applications lists the two moves as separate mitigations. One limits the extensions an agent may call. The other limits the functions inside each extension. A rule on the whole connector is the first move, and a rule on named tools is the second.</p>
<p>Both serve one principle. <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">NIST SP 800-53 control AC-6</a>, least privilege, allows only the access that users, or processes acting for them, need for their assigned tasks. An AI agent calling tools for a support lead is exactly such a process. The six cases below are about which shape of rule gets there with the least upkeep.</p>
<h2 id="when-is-blocking-the-whole-app-the-wrong-rule">When is blocking the whole app the wrong rule?</h2>
<p>When the role has a narrow, legitimate need inside the app. The block removes the need along with the risk, and the work reappears somewhere you cannot see.</p>
<p><strong>The role needs one read out of a broad app.</strong> The <a href="/connectors/xero/">Xero</a> connector carries well over a hundred tools, and a support agent may need exactly one of them: the status of an invoice. Block Xero for the Support role and the lookup does not stop. It moves to a chat message to finance, or to an invoice PDF pasted into a personal assistant account. Allow that read, or block the writes and deletes, and the lookup stays on the governed path.</p>
<p><strong>Only the destructive part is the problem.</strong> Deletes are the part of an app you can list. Elaichi marks deletes with MCP's destructive hint and reads with its read-only hint. A plain write carries no annotation, since neither hint would describe an edit honestly. If your objection to the connector is three delete operations, write three block rules. OWASP's guidance makes the same cut with a mailbox: an extension that summarizes email needs to read it, not to delete or send it. A whole-app block is a far larger claim than the one you meant to make.</p>
<p><strong>Two roles need different slices of the same app.</strong> Finance reads billing records in <a href="/connectors/salesforce/">Salesforce</a>. Sales updates contact details in the same Salesforce org. One rule on the whole connector cannot describe both jobs. Restrictions target roles and users, so you write two sets of tool rules, one per role. The alternative is one blunt rule that is wrong for one of the two teams.</p>
<p>The cost of all three is the same. A set of tool rules is a list you now own, and every tool added to that connector later arrives outside it.</p>
<h2 id="when-is-naming-individual-tools-the-wrong-rule">When is naming individual tools the wrong rule?</h2>
<p>When the list you write today is not the list that will exist next quarter, or when the role should not be in the app at all.</p>
<p><strong>The role has no business in the app.</strong> A recruiting system and the Support role is the clean example. A tool-by-tool block list against <a href="/connectors/ashby/">Ashby</a> has to be complete on the day you write it, and stay complete. One rule on the whole connector is complete by construction. It also reads correctly to an auditor, who sees the intent without rebuilding it from twelve tool names.</p>
<p><strong>The connector's tool list changes.</strong> Custom connectors are authored from JSON config, can be forked from a public connector, and can pull upstream changes through a review screen. That screen separates new tools, safe updates, config diffs, conflicts and upstream removals. New tools are a normal result of a pull. A block list written in March does not name the tool that arrives in June, and the absence of a rule means allow. A rule on the whole connector covers the June tool without anyone remembering it exists.</p>
<p><strong>Somebody forked the connector.</strong> The <code>connector:create</code> permission is flagged high trust, because a custom connector can be pointed at any destination. A fork's identity includes its declared lineage, walked back to the root. Lineage counts for block rules only, and it fails closed if the chain is broken or circular. So a block on the parent connector also reaches the fork. The host a connector calls is deliberately not part of its identity, so do not plan rules around hostnames.</p>
<p>The cost here is bluntness. A whole-app block generates requests for exceptions. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule, so a rule on one user cannot be the exception. The person files an access request for the connector, because a request for one tool on a blocked connector is refused. An admin approves it in the console. The grant lifts that connector for that one person only, and every other role rule keeps applying.</p>
<h2 id="how-does-one-intent-look-as-a-block-list-and-as-an-allowlist">How does one intent look as a block list and as an allowlist?</h2>
<p>Take one intent: the Support role may read and comment on tickets in <a href="/connectors/zendesk/">Zendesk</a>, and may delete nothing there. Written as a block list, the intent fails open as tools are added. Written as an allowlist, it fails closed.</p>
<p>As a block list, you block the Zendesk delete operations for the Support role. Reads and plain writes stay, and a tool added next quarter is reachable the day it lands.</p>
<p>As an allowlist, you allow the ticket read and comment operations for the Support role. Everything else on that connector is denied, including tools that do not exist yet. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That empty rule is the strictest one the system can express, and the one that looks least strict in a console list.</p>
<p>Pick the allowlist when the boundary is narrow and the app is broad, such as a rule that lets a team create tasks in <a href="/connectors/asana/">Asana</a> and reach nothing else there. Pick the block list when the role needs most of the app and you are removing a handful of operations.</p>
<h2 id="why-does-a-block-match-a-tools-name-but-an-allow-only-its-operation">Why does a block match a tool's name, but an allow only its operation?</h2>
<p>Because a name is a label that someone else can edit. A rule is written against a connector and a tool, and Elaichi records the tool's underlying operation from the catalog when the rule is saved. A block then matches the tool name or that operation. An allow matches the operation only.</p>
<p>A tool's advertised name can be changed by whoever edits the connector's documentation, so the name is something the governed party controls. Governance binds the operation, never the label. The MCP schema takes a similar line on the descriptive parts of a tool definition: its <a href="https://modelcontextprotocol.io/specification/2026-07-28/schema#toolannotations">annotations are hints</a>, not a guaranteed description of what the tool does. The cases where the difference changes an outcome are in <a href="/blog/block-matches-name-allow-matches-operation/">name and operation matching</a>.</p>
<h2 id="what-if-the-tool-is-fine-but-the-account-it-points-at-is-not">What if the tool is fine but the account it points at is not?</h2>
<p>Then freeze the argument instead of writing a restriction. Two Notion workspaces, one of which is the board's. One production ledger and one sandbox. The tool is fine, and the target is not.</p>
<p>A toolbox is a saved set of tools, and each entry in it pairs one tool with one connected account. A frozen argument is set on the entry. Elaichi drops a frozen key from the schema it shows the model, then writes the frozen value over the caller's arguments at execution. Passing the key cannot undo it. Entry defaults apply first, the caller's or model's arguments next, and frozen values last.</p>
<p>A restriction decides which tool the agent may call. A frozen argument decides what that call may point at. One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A payment case is worked through in <a href="/blog/frozen-parameters-wire-transfer-receiver/">freezing the receiver on a wire transfer</a>.</p>
<h2 id="which-rule-fits-how-much-of-the-app-a-role-needs">Which rule fits how much of the app a role needs?</h2>
<p>Two questions decide it: how much of the connector the role legitimately needs, and how often the connector's tool list changes.</p>
<table>
<thead>
<tr>
<th>What the role needs</th>
<th>How the tool list behaves</th>
<th>Rule to write</th>
</tr>
</thead>
<tbody>
<tr>
<td>Most of the app</td>
<td>Stable</td>
<td>Block the handful of destructive tools</td>
</tr>
<tr>
<td>A narrow slice</td>
<td>Stable or changing</td>
<td>Allow the operations the role uses; new tools stay out until someone adds them</td>
</tr>
<tr>
<td>None of it</td>
<td>Either</td>
<td>One block on the whole connector, which also reaches its forks</td>
</tr>
<tr>
<td>Most of the app</td>
<td>Changing</td>
<td>Block the destructive tools, then review every upstream pull</td>
</tr>
</tbody>
</table>
<p>The last row is the honest one. Breadth plus churn is a review problem dressed as a permissions problem, and more rules will not change that. NIST's least-privilege control has an enhancement for this case, <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">AC-6(7)</a>, which asks for the privileges assigned to roles to be reviewed on a set schedule. Put the connector's pull review on the same schedule.</p>
<h2 id="what-happens-after-you-save-a-rule">What happens after you save a rule?</h2>
<p>A saved restriction takes effect within about two minutes on every surface: MCP, the console and REST. Role membership changes resolve the same way. Grant revocation is the exception, because the grant is re-read on every call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>Elaichi applies the rule at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file. A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification's tools page</a> allows for that, since the tools a server lists may vary with the authorization on the request. Calling a withheld tool through <code>execute_tool</code> gains nothing either. It is only a naming indirection, and it meets the same gates.</p>
<p>Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). A call for a tool the rule withholds is refused before execution, so it writes no row. What a record holds is the subject of <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI agent audit log must capture</a>.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page puts the credential model, sharing and per-person attribution in one place, written for the reviewer who signs off.</p><a href="/security/" class="cta-button">See the security page</a></aside>
<h2 id="when-do-you-not-need-either-rule">When do you not need either rule?</h2>
<p>When there is nothing to split. If one team uses one connector, and everyone on it has the same trust and the same job, the role assignment and the audit trail already answer the question. Restrictions divide an app between people who should see different parts of it. With nothing to divide, they add review work and nothing else.</p>
<p>Three roles need no restriction at all. Guest, Auditor and Billing Admin lack <code>tool:execute</code>, which gates the whole endpoint ahead of every scope. For them <code>tools/list</code> is empty, and a call returns an in-band error naming the permission. A connector block written for the free read-only Auditor seat governs nothing that seat could reach.</p>
<p>Before writing a first rule, <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for waiting</a> sets out when none of this is needed yet. For one team set up end to end, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Salesforce access for a sales team</a>. Role design sits under <a href="/blog/category/governance/">governance</a>, the apps you can write rules for are in the <a href="/connectors/">connector catalog</a> of 600+ connectors, and per-team starting points are on the <a href="/use-cases/">use cases page</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Should I restrict one AI tool or block the whole app?</strong></dt><dd>Restrict individual tools when a role needs part of an app, such as reading tickets without deleting them. Block the whole app when the role has no business in it, or when the app gains new tools faster than anyone reviews them. In Elaichi both kinds of rule are written for a role or a user, and a block always beats an allow within each layer.</dd><dt><strong>Does blocking an app also cover tools added to it later?</strong></dt><dd>Yes. A block on the whole connector covers every tool that connector exposes, including tools added after the rule was written, because the rule names the connector rather than a list of tools. A per-tool block list does not. With no rule in place everything is allowed, so a new tool stays reachable until somebody adds it to the list.</dd><dt><strong>What happens if an allow rule names no tools?</strong></dt><dd>It denies everything on that target. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. That makes it the strictest rule the system can express. It is also the easiest one to write by accident, because an empty list does not look restrictive in a console.</dd><dt><strong>How long does a restriction change take to apply?</strong></dt><dd>In Elaichi it takes about two minutes. Restrictions and role membership are cached for 60 seconds and then spread across the edge, and that holds on MCP, the console and REST alike. Member removal is the exception. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the removed person's next call fails.</dd><dt><strong>Can one restriction cover everybody in the company?</strong></dt><dd>Not as a single target. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. To cover everyone, write the rule for each role people hold. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Proving AI actions in access review evidence</title>
      <link>https://elaichi.ai/blog/shadow-ai-security-lead-access-review-evidence/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/shadow-ai-security-lead-access-review-evidence/</guid>
      <description>To prove AI actions in access review evidence, record the person and the client behind each call as it happens. SaaS logs name the account, not the client.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Access reviews stall on rows where a SaaS application recorded a credential but nobody can name who drove the call. Elaichi records the actor at the point of action. A call from Claude or ChatGPT is recorded under the person who signed in, with the client named, so AI actions in access review evidence carry a person and a client instead of a guess. Audit events and application logs share one record shape, and the fields promoted from event metadata come from a fixed list, so the evidence pack keeps the same columns quarter after quarter.</aside>
<p>To prove AI actions in access review evidence, you need a record of who and which client made each call, written when the call happens. The SaaS application's own log cannot supply that. It names the account that called it, and an assistant acting for an employee uses that employee's account. The layer where the tool call is authorized and issued has to write the actor down.</p>
<p>The quarterly access review shows the gap. One row will not close: on March 14 at 02:14, an opportunity in Salesforce moved to Closed Won. Salesforce names the account that made the change. The person who owns that account was asleep, and says so. The owner column stays blank.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. It sits one layer above the application that wrote that row, which is why the row cannot say an assistant was involved.</p>
<h2 id="what-changes-when-an-agent-acts-for-a-person">What changes when an agent acts for a person?</h2>
<p>The actor stops being obvious. An access review checks that the identities holding access should hold it, and it samples past actions as evidence. In <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">NIST SP 800-53</a>, both duties sit in the account management control, AC-2. It asks organizations to monitor the use of accounts and to review them at a frequency they define.</p>
<p>For years the two kinds of actor were easy to tell apart. A person clicked a button. A scheduled job ran under a service account. The split held up in an audit because it held up in the logs.</p>
<p>An assistant acting for a person is neither. It runs inside that person's session, against that person's connected account, and it picks the call itself. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> calls tools model-controlled: the model can discover and invoke them on its own, based on the conversation and the user's prompts. Naming the human on the row is true and incomplete. The human did not write the request.</p>
<h2 id="why-do-ai-actions-in-access-review-evidence-come-back-blank">Why do AI actions in access review evidence come back blank?</h2>
<p>Because attribution gets rebuilt afterwards from fields that were never meant to carry it. Each SaaS application records the credential that called it. MCP's own <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">authorization model</a> has the client make requests on behalf of a resource owner, meaning the person who signed in. Downstream, the credential Salesforce sees is usually that person's own connected account.</p>
<p>Sometimes it is a shared service account somebody created for automation two years ago. The discussion under AC-2 lists shared accounts among the types organizations may want to prohibit because of the added risk. Either way the row looks like ordinary API traffic.</p>
<p>Reviewers then guess from the hour of day, the call rate or the user agent string. Each is a heuristic. An access review resting on one comes apart at the first follow-up question in a customer security questionnaire.</p>
<p>The blank row is not a logging failure in the destination application. Salesforce recorded exactly what reached it. The missing fact belongs to the place where the tool call was authorized and issued.</p>
<h2 id="can-a-user-agent-string-tell-you-an-agent-was-involved">Can a user agent string tell you an agent was involved?</h2>
<p>Not reliably. A user agent is a string the caller sets, so it says what the caller chose to say about itself. A script on a laptop and an assistant acting for the same person can send the same header, because both use a library rather than a browser. Vendors set the header inconsistently, and a proxy in the path can rewrite it before it lands.</p>
<p>Reading it later has a second problem. The header identifies the software that opened the connection. It does not say whether a person asked for the action, read the result, or approved it. Two calls with identical headers can be a nightly sync and someone typing a request into Cursor.</p>
<p>A user agent is evidence of a client. An access review asks for the actor.</p>
<h2 id="how-does-elaichi-record-that-an-ai-client-made-the-call">How does Elaichi record that an AI client made the call?</h2>
<p>As fields written at the point of action. In Elaichi, a call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. Those three clients are marked verified. The <code>actor_kind</code> field has values including <code>user</code>, <code>system</code>, <code>staff</code>, <code>scim</code>, <code>api_token</code> and <code>ai_assistant</code>, and <code>ai_assistant</code> marks the Elaichi Agent only. Nothing downstream has to infer it. A reviewer reads the person and the client on the same row.</p>
<p>The surface shows how the call arrived: <code>mcp</code> for an AI client such as Claude, ChatGPT or Cursor, and <code>console</code> for a person in the console. The client name is checked against the app's registered redirect addresses. A user agent differs, because the client sets it itself.</p>
<p>That works because of where the call passes. Each SaaS account the company uses is connected once, and its tools are served from one organization-wide address, <code>POST /mcp</code>. That address runs standard MCP on the Streamable HTTP transport, with OAuth in front. OAuth is the sign-in flow that issues a scoped grant instead of handing over a password. No member has a URL of their own, and no client config carries a token. Every grant belongs to a named member, so the member and the client both land on the record.</p>
<p>Elaichi does not hold connector credentials. They live in a separate credential service, encrypted at rest, which also refreshes tokens. If a refresh fails, the connection's status becomes <code>needs_reauth</code>, so the failure is on the record rather than silent.</p>
<p>Actor names resolve on the server when the trail is read. A member who has left shows as "Former member" rather than dropping out of the list. In a quarter where somebody resigned, that is the difference between a gap and an answer.</p>
<h2 id="what-does-one-audited-tool-call-record">What does one audited tool call record?</h2>
<p>Enough to close the row. Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each names the account the call actually reached, read from the execution rather than the request. That lets the pack say which of two Notion workspaces an agent wrote to. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an AI audit log should hold</a> lists the rest, with the question each one answers.</p>
<p>Each entry keeps the one path argument that names the object, as the target id, and nothing else about the arguments. You can show which object a delete acted on, not what was written to it. <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf">NIST's AU-3</a> asks an audit record to establish the type of event, when and where it happened, its source, its outcome and the identity of anyone or anything involved. Its discussion also notes that a trail recording inputs can expose personal information, which is the case for leaving argument contents out.</p>
<h2 id="do-you-have-to-line-up-two-exports-by-timestamp">Do you have to line up two exports by timestamp?</h2>
<p>No. Elaichi writes audit events and application logs in one record shape, so one query covers both. The trail is append-only and newest-first, pages by cursor, and can be filtered by time, actor, action kind, category or free text.</p>
<p>The type system scopes each organization's audit history, not a WHERE clause. A dropped WHERE clause leaks; a wrong scope returns nothing. That failure direction matters more than usual, because the in-product assistant can read the audit log. Customer-visible audit records and internal application logs sit apart, and the customer read path queries only the audit records.</p>
<p>One trade-off to plan around: the trail is eventually consistent, so a new row can lag the call by a moment. Pull evidence after the review period has closed, and do not build an alarm on the absence of a row.</p>
<h2 id="why-does-the-trail-keep-an-error-code-and-not-the-vendors-message">Why does the trail keep an error code and not the vendor's message?</h2>
<p>To keep third-party payload out of places it should not reach. A failed call produces two error strings in Elaichi. The caller gets one built from what the third party sent back, and that one is never stored anywhere else. The audit trail gets a different string, built without reference to the request or the response.</p>
<p>Audit records are visible to the whole organization, and the in-product assistant can read them. Forwarding them to a customer's SIEM, the log platform a security team searches, is part of the design. A remote error body reaching any of those would be third-party payload leaving through the log pipe.</p>
<p>The cost to a reviewer is real. You get a code, the operation and the account, not the vendor's explanation of why the call failed. State that trade in the evidence pack rather than discovering it during an audit call.</p>
<h2 id="will-next-quarters-evidence-have-the-same-columns">Will next quarter's evidence have the same columns?</h2>
<p>Yes. In Elaichi, the metadata promoted into fields of its own comes from a fixed allowlist, not from a rule that flattens whatever arrives on the event. Metadata keys can be influenced by users and are unbounded in practice. Flattening all of them would let one organization's traffic grow the field namespace for its whole tenant.</p>
<p>For an access review, that constraint helps. The fields in this quarter's extract are the fields in next quarter's. A new column is a request with a review behind it, not something that appears because an agent sent an unusual payload.</p>
<h2 id="how-do-you-prove-a-fix-took-effect-after-the-review">How do you prove a fix took effect after the review?</h2>
<p>Record when the change applied, and know which of two timings it falls under. Mixing them up is how an evidence pack becomes wrong.</p>
<p>Grant revocation, member removal and member suspension land on the next call, because revocation state is read fresh from the organization store every time. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.</p>
<p>Changes to roles and restrictions take effect within about two minutes, on MCP, the console and REST alike. Record the time the change applied, not the time someone asked for it.</p>
<p>Each control then gets one line. Every member holds exactly one role, which a unique index enforces, so each role is a complete persona. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.</p>
<h2 id="when-is-a-manual-review-still-enough">When is a manual review still enough?</h2>
<p>When one team uses one assistant against read-only connections. Export the assistant's workspace logs, export the target application's logs, line up the timestamps, and ask the four people who had access. At that size a control plane such as Elaichi is overhead that buys nothing, and <a href="/blog/when-you-dont-need-an-mcp-gateway/">holding off is a defensible call</a>.</p>
<p>The point where the method stops working is usually visible in advance. A second client appears, so Claude, ChatGPT and Cursor are all in scope. Connections start doing writes and deletes rather than reads. Contractors get access. Or a customer asks, in writing, how you tell an agent action from a human one. From there, manual correlation produces a paragraph of reasoning where the reviewer wanted a field.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>Before a team relies on this, the security page sets out how Elaichi holds credentials, shares access and attributes each call that runs to a person.</p><a href="/security/" class="cta-button">Open the security overview</a></aside>
<h2 id="what-goes-in-the-evidence-pack-for-the-next-review">What goes in the evidence pack for the next review?</h2>
<p>Start from the row you could not close. Decide which columns the reviewer needs, then confirm each one is a recorded field rather than something a person reconstructs.</p>
<p>If the review feeds a SOC 2 report, the auditor works from the AICPA's <a href="https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022">Trust Services Criteria</a>. The AICPA publishes them as control criteria for evaluating controls over security, availability, processing integrity, confidentiality and privacy. <a href="/blog/soc2-evidence-ai-agents-cc-controls/">Mapping CC6 and CC7 to AI agent evidence</a> lines each criterion up with the record that answers it.</p>
<p>Give the reviewer their own seat. The Elaichi Auditor role is free and read-only, so a compliance reviewer does not use a license. Auditor lacks <code>tool:execute</code>, the permission that gates the whole MCP endpoint ahead of every scope. That seat sees an empty <code>tools/list</code>, and any call comes back with an in-band error that names the missing permission.</p>
<p>If your team works in a log platform, plan the forwarding. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Splunk HEC and Microsoft Sentinel destinations are accepted as destinations, but Elaichi delivers events only to Datadog. Read the log type filter twice: absent means forward everything, and an empty list means forward nothing. Elaichi has three regions, EU, US and APAC, chosen when the organization is created. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. Every organization's audit trail, whatever its region, is stored in one log instance in the EU.</p>
<p>Two limits belong in the pack rather than in a footnote. The trail does not contain the prompt, because an MCP server never sees one. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. Deleting an organization deletes its credentials, but it has no path to purge the audit history, analytics events or the credential service's connector configuration rows, and the product says so by naming that residue. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written. Neither limit is comfortable to write. Both are better written by you than found by an auditor.</p>
<p>The <a href="/product/">product overview</a> covers how one endpoint serves every connected account, and the <a href="/security/">security page</a> lists what is enforced in code. <a href="/blog/offboarding-when-the-agent-holds-access/">What to do when a contractor leaves</a> handles the offboarding half of the same problem. For scope, browse the <a href="/connectors/">connector catalog</a>, with 600+ connectors, or the <a href="/use-cases/">team use cases</a>.</p>
<h2>FAQ</h2><dl><dt><strong>How can an audit log show that an AI client made a call?</strong></dt><dd>By recording the surface and the client as fields when the action happens. In Elaichi, a call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface mcp and the OAuth client named. The actor_kind field has values including user, system, staff, scim, api_token and ai_assistant, which marks the Elaichi Agent. Both are written at the point of action rather than inferred later from a user agent string, so a reviewer reads the actor instead of reconstructing it.</dd><dt><strong>Can you tell whether an AI or a person made a change from SaaS application logs alone?</strong></dt><dd>Usually not. A SaaS application records the credential that called it, and an assistant acting for an employee commonly uses the same connected account that employee uses by hand. A user agent is a string the caller sets, so it identifies client software rather than the actor. The distinction has to be recorded one layer up, where the tool call was authorized and issued.</dd><dt><strong>Does Elaichi log the arguments an agent passed to a tool?</strong></dt><dd>Elaichi logs the one path argument that names the object, as the target id, and nothing else about the arguments. It keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the operation and tool, the connection actually reached, the classification, whether the call was approved, how it ended, and an error code rather than the vendor's message.</dd><dt><strong>Do you need a control plane to pass an access review with one AI client?</strong></dt><dd>No. If one team uses one assistant against read-only connections, exporting the assistant logs and the application logs and asking the handful of people involved is proportionate. The method stops scaling when a second client is added, when connections start performing writes and deletes, when contractors get access, or when a customer asks in writing how agent actions are distinguished from human ones.</dd><dt><strong>How quickly does revoking access take effect after an access review finds a problem?</strong></dt><dd>In Elaichi, grant revocation, member removal and member suspension take effect on the next call, because the revocation state is re-read from the organization store on every call. A role change or a restriction change takes effect within about two minutes, because roles and restrictions pass through a short cache and then edge propagation.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>Zendesk for support agents, minus bulk deletes</title>
      <link>https://elaichi.ai/blog/support-team-claude-zendesk-tickets/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/support-team-claude-zendesk-tickets/</guid>
      <description>Zendesk for support agents in Claude: let them read and update tickets, block deletes and bulk sends, and give the lead one exception.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, give the frontline support role Zendesk's reads and its one-ticket updates, then write two block rules on that role: one on ticket deletion and deletion schedules, one on bulk ticket updates and macro edits. The support lead gets the bulk tool through an access request that an admin approves, which lifts only that tool out of the lead's role rules. Frozen parameters on a toolbox shared with the team, not the Zendesk connection, keep new tickets in one brand and group, and a rule change takes about two minutes to apply.</aside>
<p>Zendesk for support agents, reached through Claude, should let the frontline read and update tickets and do nothing that can empty a queue. In Elaichi that comes down to two block rules on the frontline role: one on deleting tickets, one on changing many tickets at once. An access request gives the support lead the exception an outage needs. Frozen parameters on a toolbox shared with the team keep new tickets in the right brand and group.</p>
<p>The delete block matters more than it looks. The catalog's <a href="/connectors/zendesk/">Zendesk connector</a> has no bulk-delete tool, and it does not need one. Zendesk's <a href="https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/">Tickets API</a> lets its single-ticket delete run 400 times a minute. An assistant working down a search result is a bulk delete.</p>
<h2 id="which-zendesk-tools-should-a-frontline-agent-reach">Which Zendesk tools should a frontline agent reach?</h2>
<p>The reads, plus the writes that change one ticket at a time. In Zendesk's API a reply or an internal note is a comment added through a ticket update, so one update tool carries most of the writing.</p>
<table>
<thead>
<tr>
<th>What the agent asks Claude for</th>
<th>Tool that runs</th>
</tr>
</thead>
<tbody>
<tr>
<td>The customer's open tickets</td>
<td><code>list_all_zendesk_search</code></td>
</tr>
<tr>
<td>A ticket and its whole thread</td>
<td><code>get_single_zendesk_ticket_by_id</code>, <code>list_all_zendesk_ticket_comments</code></td>
</tr>
<tr>
<td>A public reply or internal note, a new status, priority or assignee</td>
<td><code>update_a_zendesk_ticket_by_id</code></td>
</tr>
<tr>
<td>A tag added or removed</td>
<td><code>zendesk_ticket_tags_add</code>, <code>zendesk_ticket_tags_remove</code></td>
</tr>
<tr>
<td>Who the requester is, and their company</td>
<td><code>get_single_zendesk_user_by_id</code>, <code>get_single_zendesk_organization_by_id</code></td>
</tr>
<tr>
<td>The help center article to quote</td>
<td><code>list_all_zendesk_help_center_articles</code>, <code>get_single_zendesk_help_center_article_by_id</code></td>
</tr>
<tr>
<td>A macro's wording, reused on one ticket</td>
<td><code>get_single_zendesk_macro_by_id</code></td>
</tr>
</tbody>
</table>
<p>The second list is shorter and matters more. A frontline agent's Claude should not reach these:</p>
<ul>
<li><code>delete_a_zendesk_ticket_by_id</code>, which deletes one ticket per call and can be called again and again.</li>
<li><code>create_a_zendesk_deletion_schedule</code> and <code>update_a_zendesk_deletion_schedule_by_id</code>. A deletion schedule tells Zendesk to delete data automatically once it meets the schedule's conditions, per Zendesk's <a href="https://developer.zendesk.com/api-reference/ticketing/business-rules/deletion_schedules/">deletion schedules reference</a>.</li>
<li><code>zendesk_tickets_update_many</code>, which changes up to 100 tickets in one call.</li>
<li><code>create_a_zendesk_macro</code> and <code>update_a_zendesk_macro_by_id</code>, which change what every agent sends.</li>
</ul>
<p>Most teams write the first list by instinct and never write the second one down. The second list is the configuration.</p>
<h2 id="how-do-you-set-up-zendesk-for-support-agents-in-claude">How do you set up Zendesk for support agents in Claude?</h2>
<p>Connect Zendesk once in Elaichi, put one address in Claude, and let each agent sign in as themselves. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Its <a href="https://modelcontextprotocol.io">own documentation</a> calls it an open-source standard for connecting AI applications to external systems. Elaichi serves its 600+ connectors through one organization-wide endpoint, <code>POST /mcp</code>, behind OAuth, the sign-in standard that gives a client a revocable grant instead of a password.</p>
<p>In a Claude Team or Enterprise organization, an owner adds the address once, under Organization settings, Connectors, Add, then Custom and Web. Each agent then opens Customize, Connectors, clicks Connect beside it and signs in. On Pro and Max, each person adds the address under Customize, Connectors (<a href="https://support.claude.com/en/articles/11175166">Anthropic's custom connector guide</a>). The address is the same for everyone. The grant differs per agent, and it is what you revoke when someone leaves.</p>
<p>Behind the address, four things decide what an agent's Claude can do. The role comes first. Each member holds exactly one, and it must carry <code>tool:execute</code>, the permission that gates the whole endpoint. Without it the tool list is empty, which is why Guest, Auditor and Billing Admin seats cannot run tools.</p>
<p>Sharing comes next. Pin the Zendesk tools the team needs into a toolbox, a saved set of tools you hand a team, and share the toolbox with the frontline team. Keep the Zendesk connection itself unshared, so every agent's call runs through the toolbox.</p>
<p>A restriction decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. The role's rules apply to toolbox entries too, so they still hold if the toolbox grows. Frozen parameters, last, fix an argument's value on one toolbox entry.</p>
<h2 id="which-two-blocks-stop-bulk-deletes-and-mass-macro-sends">Which two blocks stop bulk deletes and mass macro sends?</h2>
<p>One block on deleting tickets and one on changing many tickets at once, both targeted at the frontline role.</p>
<p>The delete block names <code>delete_a_zendesk_ticket_by_id</code> and the two deletion-schedule writes. Zendesk lets only admins create a deletion schedule, so that half matters most when the connected account is an admin.</p>
<p>The bulk block names <code>zendesk_tickets_update_many</code> and the two macro writes. Zendesk's <a href="https://developer.zendesk.com/api-reference/ticketing/business-rules/macros/">Macros API</a> returns the changes a macro would make, and says plainly that "It doesn't actually change a ticket." A ticket update does the writing. A mass macro send is therefore a bulk ticket update, and Zendesk's bulk endpoint takes up to 100 tickets per call. The macro writes belong in the same block because a shared macro is what every agent sends. The catalog's description of <code>update_a_zendesk_macro_by_id</code> also warns that an update clears the macro's other actions unless they are included.</p>
<p>The bulk block has one cost. The catalog describes <code>zendesk_tickets_update_many</code> as the tool that tag changes on closed tickets require, so that job moves to the lead.</p>
<p>Use blocks rather than an allow list, so the rest of the connector stays open while the pilot runs. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. A block also matches the tool's name or the operation Elaichi pinned at save time, so a renamed tool cannot slip past it. <a href="/blog/block-matches-name-allow-matches-operation/">Blocks and allows match differently</a>, and the difference is deliberate. Inside one rule set, blocks beat allows, so an allow added later that covers deletion does not reopen it.</p>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema (<a href="/blog/search-tools-ranking-floor-idf/">how restrictions shape tool search</a>).</p>
<h2 id="how-does-the-support-lead-get-the-one-exception-an-outage-needs">How does the support lead get the one exception an outage needs?</h2>
<p>Through an access request that an admin approves. Each member holds exactly one role, so roles cannot stack, and a personal rule cannot lift a role block. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule.</p>
<p>Take an outage. The lead needs to post one status update to every ticket it opened, and that is the bulk tool the frontline cannot reach. The lead files an access request for <code>zendesk_tickets_update_many</code>. An admin with <code>member:manage</code> approves it in the console, under Governance, then Access requests. Approval needs step-up sign-in, and nobody approves their own request. Neither an AI client nor the Elaichi Agent can approve or deny one.</p>
<p>Approval creates an access grant for the lead alone. The grant lifts exactly the approved tool out of the lead's role rules. The delete block and every other role rule keep applying to the lead. Nobody else changes, no rule is written, and the role is not edited. The grant lasts until the lead is removed or an admin approves a replacement. The bulk tool also needs an entry in the team's toolbox, where the role's block keeps it from everyone but the lead.</p>
<p>A separate role suits a different case. If five leads share the job, give them a Support lead role with its own rules, so the exception lives in one role rather than five grants. A personal rule still has a use: it can narrow one person, such as a new agent who should not update tickets yet.</p>
<h2 id="how-do-you-keep-the-assistant-inside-one-brand-and-one-group">How do you keep the assistant inside one brand and one group?</h2>
<p>Freeze <code>brand_id</code> and <code>group_id</code> on the toolbox entry for <code>create_a_zendesk_ticket</code>. In Zendesk's ticket object, the first names the brand a ticket belongs to and the second the group it is assigned to, per the <a href="https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/">Tickets API</a>. Copy the exact paths from the tool's schema in Elaichi before you freeze them, because a freeze written on the wrong path pins nothing.</p>
<p>A frozen field is removed from the tool's schema before Claude is handed it, so there is no brand for the model to choose. At execution the frozen value is written over the call's arguments, so sending the field anyway changes nothing. Every ticket the assistant opens lands in the support brand and the frontline group.</p>
<p>One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. An agent who also holds <code>use</code> on the Zendesk connection, directly or through a team or organization share, reaches <code>create_a_zendesk_ticket</code> unfrozen. A block on that tool does not close the gap, because restrictions apply to toolbox entries too and would withhold the frozen entry as well. Leaving the connection unshared closes it.</p>
<p>Updates are a judgment call. Freezing <code>group_id</code> on <code>update_a_zendesk_ticket_by_id</code> stops the assistant moving a ticket into another team's queue. A freeze rewrites a call rather than refusing it, though, so every ticket the assistant updates ends up in the pinned group. Freeze it there only where agents work their own group's tickets.</p>
<p>Restrictions decide which operations exist, and frozen values decide where they land, so the model never guesses a brand from a prompt.</p>
<h2 id="how-do-you-prove-the-blocks-held">How do you prove the blocks held?</h2>
<p>Wait about two minutes after saving, ask Claude to do what you blocked, and check the audit log. A role or restriction change takes about two minutes to reach every surface, and the <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding guide sets out why removals land faster</a>.</p>
<ol>
<li>Signed in as a frontline agent, ask Claude to delete a test ticket. It should find the delete tool only as restricted, and a call forced through <code>execute_tool</code> is refused.</li>
<li>Ask the same Claude to reword a shared macro. It should find the macro tools only as restricted.</li>
<li>As the lead, ask Claude to tag two closed test tickets in one request, which needs the bulk tool. It should go through.</li>
<li>Filter the audit log by the lead as actor, the time of the test, and the tool name in free text. The lead's bulk update has an entry that names the outcome and the account. The frontline agent's refused delete has none, because a call refused before execution writes no row.</li>
</ol>
<p>Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none) (<a href="/blog/what-an-ai-audit-log-must-capture/">what each entry holds</a>). It records the one path argument that names the object, as the target id, and nothing else about the arguments, so no ticket body or requester email lands in the log. The trail is eventually consistent, so give a row a moment to appear.</p>
<p>The reviewer who checks it can hold the Auditor seat, which is free and read-only.</p>
<h2 id="why-not-wait-for-zendesks-own-mcp-server">Why not wait for Zendesk's own MCP server?</h2>
<p>Zendesk's own server is the natural choice for a team that connects only Zendesk, once your account has it. Zendesk announced it on 19 May 2026. The server will let businesses connect "Zendesk tickets, knowledge, and other data to external AI systems in a trusted and governed way". The announcement lists it for "Early access this summer" (<a href="https://www.zendesk.com/newsroom/articles/relate-2026/">Zendesk's Relate 2026 announcement</a>, read October 2026). Zendesk's September 2026 release notes cover its MCP client reaching general availability, not the server. Ask Zendesk where your account stands before you plan around it.</p>
<p>Where Zendesk's server wins is plain. It comes from Zendesk, so no second vendor sits between your agents and your tickets, and it would run under Zendesk's own permission model.</p>
<p>What Elaichi adds sits across apps rather than inside Zendesk. One address carries Zendesk, <a href="/connectors/jira/">Jira</a> and Slack to Claude, ChatGPT and Cursor. The frontline role's blocks are written once, beside its rules for every other app it reaches. Frozen parameters on the shared toolbox pin brand and group. One audit trail covers every app, and removing or suspending one person ends their access to all of them on their next call. The announcement does not describe role rules that span apps or arguments pinned per tool, so put those questions to Zendesk as early access opens.</p>
<h2 id="what-happens-when-a-support-agent-leaves">What happens when a support agent leaves?</h2>
<p>Their access through Claude ends on their next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is re-read on every call, with no cache.</p>
<p>If your directory deprovisions people through SCIM, the standard for syncing users from a directory, that suspends the member in Elaichi. Suspension ends access the same way. Removing the member is a separate step an admin takes in Elaichi, and it runs a preflight first. The preflight lists every Zendesk connection the agent owns, private and shared alike. A private one that a shared toolbox depends on blocks the removal until an admin transfers it to a member. A private one that nothing beyond the agent depends on cannot be transferred and is deleted with them. A shared one can go to a member who is staying, and it is deleted only if the admin asks.</p>
<p>Watch for the person who pinned the team's toolbox entries. If they are removed, suspended through SCIM or lose <code>use</code> on the connection, those entries stop resolving for every agent until someone re-pins them. Offboarding lists them as a warning rather than a blocker.</p>
<p>The agent's Zendesk account itself is a separate step in Zendesk. <a href="/blog/offboarding-when-the-agent-holds-access/">Offboarding a member who holds MCP connections</a> walks the whole sequence, contractors included.</p>
<h2 id="when-should-zendesks-own-permissions-do-the-job-instead">When should Zendesk's own permissions do the job instead?</h2>
<p>When the Zendesk role behind the connection already forbids the action. Zendesk's <a href="https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/">Tickets API</a> allows deletion only for admins and for agents with permission to delete tickets. Its <a href="https://developer.zendesk.com/api-reference/ticketing/business-rules/deletion_schedules/">deletion schedules reference</a> lists creating a schedule as admin-only. If every agent connects a personal Zendesk account whose role cannot delete, Zendesk refuses the call. A matching Elaichi block then adds a second place to drift, and in a year nobody remembers which one carries the load. Personal connections have one cost: calls through an agent's own connection skip the toolbox, so its frozen brand and group do not apply to them.</p>
<p>The qualification is what the connection signs in as. Some teams share one Zendesk service account with admin rights, because that was the fast way to connect. Then the upstream role protects nothing, and the Elaichi block is the only gate.</p>
<p>If support is six people on one Zendesk account with no other connected app, a control plane is probably premature. Zendesk's own server may be the simpler route once it reaches your account. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The case for holding off on a gateway</a> lists the signals that end the wait.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>To check a tool's exact name before you write a rule, the Zendesk connector page lists them all.</p><a href="/connectors/zendesk/" class="cta-button">Open the Zendesk connector</a></aside>
<h2 id="what-can-this-setup-not-protect-against">What can this setup not protect against?</h2>
<p>Two things: instructions hidden in ticket text, and a loop of single replies.</p>
<p>The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. A ticket body with instructions in it is ordinary data to Zendesk and ordinary text to the model, so it can steer Claude toward a tool. The role's rules still decide whether that tool exists for the agent.</p>
<p>The bulk block stops one call reaching up to 100 tickets. It does not stop Claude calling <code>update_a_zendesk_ticket_by_id</code> once per ticket. A run of identical replies is not refused; it shows up in the audit trail, one entry per call.</p>
<p>The <a href="/blog/sales-team-chatgpt-salesforce-accounts/">Salesforce playbook for a sales team</a> runs the same order, and the <a href="/blog/finance-team-claude-xero/">finance team's Xero playbook</a> builds the opposite shape, an allow list of reads. The <a href="/connectors/category/helpdesk/">helpdesk connectors</a> and the <a href="/use-cases/">twelve team pages</a> are where to plan the next rollout.</p>
<h2>FAQ</h2><dl><dt><strong>How do you stop an AI assistant from deleting Zendesk tickets in bulk?</strong></dt><dd>In Elaichi, block delete_a_zendesk_ticket_by_id and the two deletion-schedule write tools with a restriction on the role your frontline agents hold. The Zendesk connector has no bulk-delete tool, but Zendesk's API lets its single-ticket delete run 400 times a minute, so the block is what stops a bulk delete. A restricted tool is withheld from the tool list and cannot be called, and the rule takes about two minutes to apply.</dd><dt><strong>Can a support lead still send one reply to every ticket in an outage?</strong></dt><dd>Yes, through an access request, not a personal rule. A personal rule cannot lift a role block. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. The lead files an access request for the bulk-update tool, and an admin with member:manage approves it. The approval creates an access grant for the lead alone that lifts exactly that tool out of their role rules. The delete block still applies to the lead. Zendesk's bulk update then reaches up to 100 tickets per call.</dd><dt><strong>Can you limit an AI assistant to one Zendesk brand or group?</strong></dt><dd>Yes, with frozen parameters in Elaichi. Freeze brand_id and group_id on the toolbox entry for create_a_zendesk_ticket, and every ticket the assistant opens lands in that brand and group. A frozen field is removed from the schema the model receives, and its value overwrites the call's arguments at execution. The freeze holds only for calls through that toolbox, so share the toolbox with the agents and leave the Zendesk connection unshared. Freezing group_id on ticket updates works too, but it moves every ticket the assistant updates into that group.</dd><dt><strong>Why not use Zendesk's own MCP server?</strong></dt><dd>If Zendesk is the only app your team connects and the server has reached your account, it may be the simpler choice, with no second vendor. Zendesk announced it on 19 May 2026 with early access that summer, and its September 2026 release notes cover its MCP client, not the server. Elaichi adds what spans apps: one address for every connected app, role rules written once, frozen arguments, one audit trail, and one removal that ends a person's access to all of them.</dd><dt><strong>What happens to a departing support agent's access through Claude?</strong></dt><dd>It ends on their next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is checked on every call. A SCIM deprovision suspends the member, which has the same effect, and removing them is a separate admin step with a preflight. Their Zendesk account itself is closed in Zendesk.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>What is an MCP gateway? The four shapes</title>
      <link>https://elaichi.ai/blog/what-is-an-mcp-gateway/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/what-is-an-mcp-gateway/</guid>
      <description>What is an MCP gateway: one address between AI clients and their tools that signs people in, applies rules and records calls. It comes in four shapes.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An MCP gateway is one address between AI clients and the tools they call. It signs each person in, decides which tools that person may reach, and keeps the record afterwards. Four products share the name: a hosted gateway over a vendor's catalog, a gateway in front of servers or APIs you bring, a per-member server inside an automation account, and a governed control plane like Elaichi that serves connectors, most of them its own. Sort a vendor into a shape before comparing features, by asking who authors the connectors and how many addresses your clients point at.</aside>
<h2 id="what-is-an-mcp-gateway">What is an MCP gateway?</h2>
<p>An MCP gateway is one address that sits between AI assistants, such as Claude or ChatGPT, and the business apps they can act in. It signs each person in, decides which tools that person may use, and keeps a record of each call that runs. Without one, each person wires each app into each assistant separately, and nobody can say afterwards who did what.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An endpoint is the address an AI client is pointed at. OAuth is the sign-in standard that lets software act as a named person without holding that person's password.</p>
<p>The question usually arrives with a deadline. Support wants Zendesk inside Claude, finance wants Xero inside ChatGPT, and engineering already lives in Cursor. With three AI clients and twenty apps, each person has sixty separate setups to create, and sixty to undo on their last day. One gateway turns that into three, one per client.</p>
<h2 id="what-are-the-four-shapes-of-mcp-gateway">What are the four shapes of MCP gateway?</h2>
<p>Four different products are sold under the name, and they differ in mechanism:</p>
<ol>
<li>A hosted gateway over MCP servers the vendor hosts or catalogs.</li>
<li>A gateway in front of MCP servers or APIs you bring, either self-hosted or inside an API management platform that added MCP.</li>
<li>A per-member server created inside an automation account.</li>
<li>A governed MCP control plane that serves connectors, most of which it authors, behind one address.</li>
</ol>
<p>The order matches <a href="/blog/best-mcp-gateways/">the vendor-by-vendor shortlist</a>, which places named products on the same four shapes. Shapes one and two are gateways in the strict sense. They sit in front of MCP servers that somebody else runs, either the vendor or your own team. Shape three gives each member a server of their own. Shape four is a control plane, which is the server itself and makes the access decision where it serves the tool. Elaichi is the fourth shape, and this page states plainly whom each shape suits and what it costs.</p>
<h2 id="shape-one-what-is-a-hosted-gateway-over-a-catalog">Shape one: what is a hosted gateway over a catalog?</h2>
<p>In this shape the vendor runs the MCP servers and gives you one hosted address into its collection. You connect your accounts to the vendor, and your AI clients call the vendor rather than servers you operate. Breadth arrives on the day you sign, which suits a team that wants coverage this quarter without operating servers. What you inherit is somebody else's list, so ask who repairs a catalog server when its third party changes an API.</p>
<p>MintMCP calls itself "The MCP gateway between your agents and your systems": a hosted gateway with an internal catalog of approved servers, servers it hosts for you, and "one endpoint per role" (<a href="https://www.mintmcp.com/mcp-gateway">mintmcp.com</a>, checked October 2026). <a href="/blog/mintmcp-alternative/">Where MintMCP and Elaichi overlap</a> is worked through separately.</p>
<p>Composio Connect is an MCP server at <code>connect.composio.dev/mcp</code> that reaches its apps through seven meta-tools. OAuth links are approved in the browser (<a href="https://docs.composio.dev/docs/composio-connect">docs.composio.dev</a>, checked September 2026). Composio's MCP Gateway page describes "one gateway, every server". On that page, "each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">composio.dev</a>, checked September 2026).</p>
<p>Governance exists in this shape, so it is not the axis to compare on. Composio's enterprise page describes permissions "set administratively, per user and per role, down to the individual action". It also describes logging of every tool call, denied calls included, and single sign-on (SSO) over SAML and OIDC (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked September 2026). The useful questions are where the connectors come from and how many addresses IT ends up administering. A per-team endpoint is easy to reason about at three teams and tedious at thirty. <a href="/blog/elaichi-vs-composio/">The Composio comparison</a> works through both.</p>
<p>Runlayer spans shapes one and two. It serves tools "through a governed MCP gateway across every major AI client" (<a href="https://runlayer.com">runlayer.com</a>, checked October 2026). Its connectors come from a catalog of templates maintained by Runlayer or by official vendors. Your team can also add its own MCP endpoints, or deploy servers to Runlayer (<a href="https://docs.runlayer.com/platform-connectors">Runlayer docs</a>, checked October 2026). The docs give no URL pattern, so ask how many addresses a rollout creates.</p>
<h2 id="shape-two-what-is-a-gateway-in-front-of-servers-you-bring">Shape two: what is a gateway in front of servers you bring?</h2>
<p>This shape assumes the servers or APIs already exist and that your team runs them. The gateway adds one door in front of them for sign-in, policy and logging. It is infrastructure, not coverage: it adds no apps, and it governs the ones already wired up.</p>
<p>One kind is a self-hosted MCP gateway. Lunar.dev describes MCPX as a self-hosted "Enterprise MCP Gateway" that sits between agents and the MCP servers, APIs and LLM providers they use. An open-source version is on GitHub (<a href="https://www.lunar.dev/">lunar.dev</a>, checked September 2026). Boomi announced its intent to acquire Lunar.dev on May 13, 2026, and has since completed it (<a href="https://boomi.com/blog/lunar-dev-boomi-acquisition/">boomi.com</a>, checked September 2026). If MCPX is on your list, <a href="/blog/lunar-mcpx-alternative-governed-access/">count your servers before you compare</a>.</p>
<p>The other kind is an API management platform that grew an MCP mode. Tyk's MCP Gateway proxies and governs remote MCP servers, and can generate an MCP proxy from a REST API that Tyk already manages. Its proxies for remote MCP servers come with every Tyk Gateway license, and upstream OAuth needs Tyk Enterprise Edition (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">tyk.io</a>, checked October 2026). Zuplo is an API gateway platform that also ships an MCP Gateway, federating MCP servers behind one OAuth-protected gateway (<a href="https://zuplo.com/mcp-gateway">zuplo.com</a>, checked September 2026). Kong AI Gateway supports MCP through AI MCP Server entities, which expose APIs as MCP tools (<a href="https://developer.konghq.com/ai-gateway/">developer.konghq.com</a>, checked September 2026).</p>
<p>This shape suits a platform engineer with services in production and staff to run them. If your own APIs already sit behind one of these platforms, exposing them as MCP tools is a configuration change, not a purchase. The trade-off is that the server count does not fall. Every server still needs uptime, credential rotation and a fix when an upstream API changes. On an API platform, MCP is one mode among several, so ask how your finance team's SaaS accounts would get behind it. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The real cost of running your own servers</a> works through that arithmetic, and <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">API gateway MCP against MCP-native</a> sets the two models side by side.</p>
<h2 id="shape-three-what-is-a-per-member-server-in-an-automation-account">Shape three: what is a per-member server in an automation account?</h2>
<p>Here an automation product gives each member an MCP server of their own inside the company's account. The server reuses the app connections and actions the automations already use, so nothing new has to be connected. The address model is one server per member, so the count grows with headcount.</p>
<p>Zapier describes Zapier MCP as a way for an MCP client to take actions in the apps connected to a Zapier account. It uses the same app connections and actions as Zaps (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">Zapier help center</a>, checked September 2026). Every client connects to the same Zapier URL, and "Each MCP client gets its own MCP server: one for Cursor, one for Claude, one for ChatGPT." For most MCP clients the member signs in inside the client, and Zapier creates the server during that sign-in. Clients not on Zapier's list, and code you write, use a connection token instead. That token is long-lived, tied to one server, and "grants whoever holds it the ability to run the server's tools" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">Zapier docs</a>, checked October 2026).</p>
<p>For token-based clients, Zapier's docs say to "give each user their own server and token rather than sharing one". In a rollout, admins can restrict members to a Zapier workspace, and app and action restrictions apply through MCP (<a href="https://docs.zapier.com/mcp/manage/rollout/overview">Zapier rollout docs</a>, checked October 2026). Zapier's security page does not say what happens to a leaver's server, so ask (<a href="https://docs.zapier.com/mcp/manage/security">Zapier security docs</a>, checked September 2026).</p>
<p>This shape suits a company whose automations already live in Zapier, with a team small enough that one server per member stays easy to count. <a href="/blog/zapier-mcp-alternative/">One endpoint instead of one server per member</a> works the count through for a full rollout.</p>
<h2 id="shape-four-what-is-a-control-plane-that-is-the-mcp-server">Shape four: what is a control plane that is the MCP server?</h2>
<p>In this shape nobody at the company runs an MCP server. The control plane serves the connectors, authoring most of them, and each SaaS account is connected once. A gateway forwards calls to servers other people run, while a control plane decides access where it serves the tool. Elaichi is built this way.</p>
<p>Elaichi serves one organization-wide endpoint, <code>POST /mcp</code>: standard MCP over Streamable HTTP, JSON-RPC 2.0, stateless, behind OAuth. A toolbox, a saved set of tools and the accounts behind them, never gets an address of its own, and the URL carries no token. Claude, ChatGPT and Cursor all point at that one address. An admin adds it once where the client allows. Each member then connects and signs in with their own grant, the record that lets a named person use a named resource.</p>
<p>Elaichi serves 600+ connectors and authors, maintains and runs most of them on its own infrastructure, so for those a third-party API change is Elaichi's problem rather than a ticket in your backlog. The rest are vendors' own MCP servers, whose tools the vendor builds and runs. Account credentials sit in a separate credential service, encrypted at rest, which also owns token refresh. In Elaichi, connected tools are never listed one by one, however few there are. A model looks a connected tool up with <code>search_tools</code> and calls it through <code>execute_tool</code>, which passes the same checks as a direct call.</p>
<p>Access has three layers, and they stay separate. Permissions come from role-based access control (RBAC), and each member holds exactly one role, enforced by a unique index. Sharing grants view, use or edit on a resource to a user, a team or the whole organization. Nobody sees a resource they neither own nor were given, and org admins are no exception. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p>Elaichi is not built as a proxy for a fleet of MCP servers you already run. An internal server your platform team built can come in as a remote MCP connector on Gold, or on Black once it launches, if it is reachable over public HTTPS. The other route is a custom connector authored from JSON config, or a fork of a public connector that pulls upstream changes through a review step. It is also a bet on one vendor's connector roadmap. If your main asset is a fleet of internal servers, a gateway in front of them fits better.</p>
<h2 id="which-shape-owns-the-address-the-connectors-and-the-record">Which shape owns the address, the connectors and the record?</h2>
<p>Four columns decide most purchases: who runs the servers, who authors the connectors, where clients point, and whom the shape serves.</p>
<table>
<thead>
<tr>
<th>Shape</th>
<th>Who runs the servers</th>
<th>Who authors the connectors</th>
<th>Address a client points at</th>
<th>Built for</th>
</tr>
</thead>
<tbody>
<tr>
<td>1. Hosted gateway over a catalog</td>
<td>The vendor</td>
<td>The vendor's catalog, or each server's publisher</td>
<td>A vendor endpoint, sometimes one per team</td>
<td>Breadth without operating servers</td>
</tr>
<tr>
<td>2. Gateway in front of servers or APIs you bring</td>
<td>Your team</td>
<td>Your team, or tools made from your APIs</td>
<td>One gateway in front of many servers</td>
<td>Platform teams with servers or APIs live</td>
</tr>
<tr>
<td>3. Per-member server in an automation account</td>
<td>The automation vendor</td>
<td>The automation product's app connections</td>
<td>One server per member</td>
<td>Companies whose automations already live there</td>
</tr>
<tr>
<td>4. Governed control plane</td>
<td>Nobody: the control plane is the server</td>
<td>The control plane vendor</td>
<td>One organization-wide endpoint</td>
<td>IT and operations rolling out to non-engineers</td>
</tr>
</tbody>
</table>
<p>A company with six internal services and no SaaS sprawl belongs in row two, and no amount of governance in row four changes that.</p>
<p>The record differs in a way that shows up during an incident. Behind a gateway you run, the gateway sees the call and the upstream server sees the work, so two systems get read side by side. Elaichi's <a href="/blog/what-an-ai-audit-log-must-capture/">audit log</a>, the append-only history of calls, is recorded at execution, so an entry shows which account the call really touched.</p>
<h2 id="what-does-a-control-plane-do-that-routing-alone-cannot">What does a control plane do that routing alone cannot?</h2>
<p>A product that only routes can allow a tool or block it. A control plane that serves the tool can also fix what the model is allowed to send. Freezing an argument is that third option, and it is finer than either.</p>
<p>Frozen parameters are a map over a tool's arguments, set on one toolbox entry. Two things happen. Frozen keys are removed from the schema the model is shown, so it cannot fill them in. Frozen values are merged over the caller's arguments at execution, so passing the key cannot un-freeze it. Precedence runs from entry defaults, to caller or model arguments, to frozen parameters, and the last one wins. That is how one workspace or one account label gets pinned while the rest of the tool stays usable.</p>
<p>A restriction binds the pinned operation, not the label, and <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches the name and an allow matches the operation</a> explains that asymmetry before you write rules.</p>
<h2 id="how-do-you-tell-which-shape-a-vendor-is-selling">How do you tell which shape a vendor is selling?</h2>
<p>Open the vendor's quickstart, not the homepage, and answer four questions. The quickstart shows the address model and the setup burden on its first screen, which is where the shapes separate.</p>
<ol>
<li>Count the addresses the setup produces: one per company, one per team, or one per member.</li>
<li>Find out who wrote the connector for your most important app, and who fixes it when that app's API changes.</li>
<li>Ask what happens to a leaver's access, and who has to act. In Elaichi, removal runs a preflight listing every connection the leaver owns. A private connection that a shared toolbox depends on blocks the removal until it is transferred to a member.</li>
<li>Ask how long a permission change takes to apply, and get a number rather than an adjective. In Elaichi a role or restriction change takes about two minutes.</li>
</ol>
<p>The answers sort the vendor. A setup that has you run or register servers is a gateway in front of servers you bring. A server created for each member is the per-member shape. A hosted catalog of servers you did not write is a hosted gateway. One address for the whole company, serving connectors the vendor wrote, is a control plane. Once the shape is clear, <a href="/blog/best-mcp-gateways/">compare the vendors within it</a> on the same mechanics.</p>
<h2 id="which-reader-does-each-shape-serve">Which reader does each shape serve?</h2>
<p>Match the shape to whoever is accountable when something goes wrong. If that person is a platform engineer who already owns services, a gateway in front of them keeps ownership where it is. If it is a developer shipping an agent product, a hosted catalog gets coverage fastest. If the company's automations already run in Zapier, a per-member server reuses connections that already exist. If it is the person who runs IT or operations, and the users sit in support, finance, sales and legal, a control plane fits. It removes the two jobs that person cannot staff: operating servers and maintaining connectors.</p>
<p>The IT reader also counts seats. A compliance reviewer can sit in the free, read-only Auditor seat, and <a href="/pricing/">how seats are counted</a> covers the plans.</p>
<h2 id="what-will-no-gateway-shape-do-for-you">What will no gateway shape do for you?</h2>
<p>No gateway shape sees the prompt through MCP, because the protocol does not carry it. A server receives a tool name and arguments, so nothing at the MCP layer can judge a call against what the person actually asked for. Elaichi does not claim otherwise. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on <code>POST /mcp</code> is per-operation role permissions, a forbidden classification that no OAuth scope can reach, output redaction, scope limits and an audit row for each call that reaches execution. Ask any vendor that claims more where its check runs, and what it can see.</p>
<p>Timing is the other assumption to correct before an incident. In Elaichi a role change or a restriction change takes about two minutes to take effect. Both sit behind a 60-second cache, and the change then has to reach the edge on every surface. Grant revocation, member removal and suspension are faster, and each is effective on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. If your incident plan depends on cutting access at once, use removal or suspension, not a restriction edit.</p>
<h2 id="when-is-none-of-the-four-shapes-worth-buying">When is none of the four shapes worth buying?</h2>
<p>One person, one AI client and one connected account do not need a gateway of any shape. The client's own connector signs that person in, the SaaS side logs what was touched, and there is no second address to reconcile. Two people sharing one app with a native connector can turn it on in the client's admin console and wait.</p>
<p>The threshold arrives with the second thing. A second client, a second account of the same app, or a leaver whose access has to be removed from more than one place at once. That is when sign-in, restrictions and one readable record start paying for themselves. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When a gateway is premature</a> lists the signals in full, and <a href="/blog/elaichi-vs-native-ai-connectors/">native client connectors compared</a> covers the stage in between.</p>
<p>For the protocol underneath all four shapes, browse <a href="/blog/category/how-mcp-works/">the how MCP works archive</a>. The <a href="/connectors/">connector catalog</a> shows which apps a control plane already covers, and the <a href="/use-cases/">team use cases</a> show where rollouts usually begin.</p>
<h2>FAQ</h2><dl><dt><strong>What is an MCP gateway?</strong></dt><dd>An MCP gateway is a single address that sits between AI clients and the tools they can call. It authenticates the person, applies rules about which tools that person may reach, and records the calls. The Model Context Protocol is the open standard that lets an AI client discover and call those tools. The name covers four product shapes: a hosted gateway over a vendor's catalog, a gateway in front of servers or APIs you bring, a per-member server inside an automation account, and a control plane that is the server itself.</dd><dt><strong>What is the difference between an MCP gateway and an MCP control plane?</strong></dt><dd>An MCP gateway sits in front of MCP servers that somebody else runs, either the vendor or your own team, and adds one place for sign-in, policy and logging. An MCP control plane is the server itself: it holds the connections, serves the connectors, and makes the access decision on each call. The practical difference is ownership. Behind a gateway, somebody still runs every server, keeps it up and fixes it when an upstream API changes. With a control plane such as Elaichi, your company runs no MCP servers.</dd><dt><strong>Is an MCP gateway the same as an API gateway that supports MCP?</strong></dt><dd>An API gateway that added MCP is one shape of MCP gateway, not the whole category. Tyk's MCP Gateway proxies and governs remote MCP servers and can generate an MCP proxy from a managed REST API (https://tyk.io/docs/ai-management/mcp-gateway/overview, checked September 2026). Zuplo ships an MCP Gateway that federates MCP servers behind one OAuth-protected gateway (https://zuplo.com/mcp-gateway, checked September 2026). Both govern traffic to servers and APIs that already exist. A control plane such as Elaichi is the server itself, so there is no fleet of servers underneath to front.</dd><dt><strong>Do I need an MCP gateway if I have one AI client and one SaaS account?</strong></dt><dd>No. With one person, one AI client and one connected account, the client's own connector handles sign-in and the SaaS application logs the activity. A gateway starts paying for itself when a second client is added, when the same application has two accounts, or when someone leaves and their access has to be cut in more than one place at once.</dd><dt><strong>How quickly does a restriction change take effect in Elaichi?</strong></dt><dd>Within about two minutes. Role membership and restriction rules resolve through a 60-second cache plus edge propagation, on the MCP endpoint, the console and the REST API alike. Grant revocation, member removal and suspension are effective on the next call, and removing or suspending a member revokes every live grant in the same transaction as the membership change.</dd><dt><strong>Does an MCP gateway store connector credentials?</strong></dt><dd>It depends on the shape, so ask each vendor. In Elaichi the credentials do not live in the control plane. A separate credential service holds per-account secrets, encrypted at rest with AES-256-GCM, and owns token refresh. A failed refresh marks the connection as needing re-authorization rather than failing silently. A connect URL is a one-time session that carries no token, which is why it is safe to return over MCP.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Best MCP gateways for company-wide AI access</title>
      <link>https://elaichi.ai/blog/best-mcp-gateways/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/best-mcp-gateways/</guid>
      <description>The best MCP gateways come in four shapes: a hosted catalog, a gateway you run, a per-member server or a control plane. Pick the shape, then the vendor.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> The best MCP gateways for company-wide AI access come in four shapes: a hosted gateway over a vendor's catalog, a gateway in front of servers or APIs you bring, a per-member server inside an automation account, and a governed MCP control plane with native connectors. Compare them on four mechanics: who authors the connectors, how many addresses your AI clients point at, where the access decision is made, and what the record proves. Elaichi is the fourth shape, serving 600+ connectors, most of them its own work, through one organization-wide endpoint behind OAuth, and it fronts MCP servers your engineers already run as remote MCP connectors under the same rules.</aside>
<h2 id="what-are-the-best-mcp-gateways-for-company-wide-ai-access">What are the best MCP gateways for company-wide AI access?</h2>
<p>Two hundred people already use ChatGPT, Claude and Cursor. Four systems hold the actual work: Salesforce, Jira, Notion and Xero. IT has been asked to put one governed layer between those clients and those systems, instead of a drawer full of pasted API keys. There is no single list of the best MCP gateways for that job. The products sold under the name come in four shapes, and the shape decides more than any feature grid does.</p>
<p>First the jargon. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An endpoint is the address an AI client is pointed at. OAuth is the sign-in standard that lets a person approve access in a browser instead of pasting a key. A grant is the record saying a named person may use a named resource.</p>
<p>Four shapes are on the market:</p>
<ol>
<li>A hosted gateway over MCP servers the vendor hosts or catalogs for you.</li>
<li>A gateway in front of MCP servers or APIs you bring, self-hosted or inside an API management platform.</li>
<li>A per-member server created inside an automation account.</li>
<li>A governed MCP control plane that authors most of its connectors and serves them behind one organization-wide endpoint. Elaichi is this shape.</li>
</ol>
<p>The same products are also sold as an "MCP control plane" and an "MCP management platform", and the four shapes listed here cover all of them.</p>
<p>Choose the shape first, and the vendor shortlist falls out of it. Elaichi is one of the four, and each shape gets a plain statement of where it wins.</p>
<h2 id="which-four-mechanics-separate-one-mcp-gateway-from-another">Which four mechanics separate one MCP gateway from another?</h2>
<p>Four mechanics decide how an MCP gateway behaves once sixty people use it. A feature grid lists checkboxes, while these four predict the tickets you will get later.</p>
<p><strong>Who authors the connectors.</strong> There are three answers. The vendor writes and serves them, the vendor fronts servers somebody else runs, or you run the servers yourself. The answer decides who you call when a third party changes its API, and how a missing app gets added.</p>
<p><strong>How many addresses clients point at.</strong> Some products give the organization one endpoint, some give each team one, and some give each member a server of their own. Multiply that count by the AI clients you support, then by everyone who joins or leaves. That number is the rollout, and later it is the offboarding.</p>
<p><strong>Where the access decision is made.</strong> The decision can sit in a vendor's gateway, a gateway you operate, an automation account's settings, or the control plane that serves the tools. Ask who a rule can target, and whether it can name a single tool. Then ask how long a change takes to take effect, and accept a number rather than the word immediately.</p>
<p><strong>What the record proves.</strong> An audit log is the append-only history of what happened. "Which of my two Notion workspaces did the agent write to?" is the first question after an unexpected change. A record that names the account the call actually reached answers it. A record of what the person asked for does not.</p>
<h2 id="how-do-the-mcp-gateway-shapes-compare-vendor-by-vendor">How do the MCP gateway shapes compare, vendor by vendor?</h2>
<p>The table places each named vendor in its shape and answers the four mechanics from that vendor's own pages only. An ask cell means the page does not state the answer, not that the product lacks it.</p>
<table>
<thead>
<tr>
<th>Vendor and shape (each vendor's own pages)</th>
<th>Who authors the connectors</th>
<th>How many addresses clients point at</th>
<th>Where the access decision is made</th>
<th>What the record proves</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://www.mintmcp.com/mcp-gateway">MintMCP</a>: hosted gateway over an approved catalog</td>
<td>An internal catalog of approved servers, plus servers MintMCP hosts for you; ask who maintains each</td>
<td>One endpoint per role</td>
<td>At MintMCP's gateway, tool by tool</td>
<td>Every call logged at the gateway; ask what one record holds</td>
</tr>
<tr>
<td><a href="https://runlayer.com">Runlayer</a>: governed gateway over a catalog, plus servers you bring</td>
<td>Catalog templates maintained by Runlayer or official vendors, plus endpoints you add or deploy</td>
<td>Ask: the docs give no URL pattern</td>
<td>At Runlayer's proxy, on every tool invocation, down to single tools</td>
<td>Ask</td>
</tr>
<tr>
<td><a href="https://composio.dev/mcp-gateway">Composio</a>: hosted gateway, one endpoint per team</td>
<td>1,500+ apps behind "one gateway, every server"; ask who maintains each</td>
<td>One endpoint per team</td>
<td>In Composio, set per user and per role, down to the individual action</td>
<td>Each tool call, with user, team, tool, action and outcome, denied calls included</td>
</tr>
<tr>
<td><a href="https://www.lunar.dev/">Lunar.dev</a> MCPX: gateway you host</td>
<td>Whoever runs the MCP servers and APIs behind it</td>
<td>Ask</td>
<td>At the self-hosted gateway, between agents and their servers</td>
<td>Ask</td>
</tr>
<tr>
<td><a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk</a>, <a href="https://zuplo.com/mcp-gateway">Zuplo</a>, <a href="https://developer.konghq.com/ai-gateway/">Kong</a>: API platforms that added MCP</td>
<td>Your MCP servers, or MCP tools made from your own APIs</td>
<td>Zuplo: one OAuth-protected gateway. Tyk and Kong: ask</td>
<td>At the API gateway, in front of your servers or APIs</td>
<td>Ask</td>
</tr>
<tr>
<td><a href="https://docs.docker.com/ai/mcp-catalog-and-toolkit/mcp-gateway/">Docker MCP Gateway</a>: open-source gateway you run</td>
<td>MCP servers packaged as container images from Docker's catalog of "300+ verified servers", or a custom catalog that limits the approved set</td>
<td>One gateway per machine under Docker Desktop's MCP Toolkit, or wherever you run it with Compose</td>
<td>At the gateway you run, which isolates each server in its own container</td>
<td>Call logs with "the tool name and argument shape metadata only"</td>
</tr>
<tr>
<td><a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/">Cloudflare MCP server portals</a>: portal in front of remote MCP servers</td>
<td>Remote HTTP MCP servers you or their vendors run, up to 80 per portal</td>
<td>One portal URL, signed into through Cloudflare Access</td>
<td>Cloudflare Access sign-in, tools picked per portal, and each server's own OAuth</td>
<td>Cloudflare Access logs the individual requests made through the portal's tools</td>
</tr>
<tr>
<td><a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/manage-byo-mcp-server">Microsoft Agent 365</a> tooling gateway, in preview: gateway for MCP servers registered with Microsoft</td>
<td>Servers you register, plus Microsoft's own</td>
<td>Ask</td>
<td>Admins approve and block whole servers at runtime; tool-level blocking for these servers is planned</td>
<td>Gateway tool calls can be hunted in Microsoft Defender</td>
</tr>
<tr>
<td><a href="https://docs.zapier.com/mcp/manage/rollout/overview">Zapier MCP</a>: per-member server</td>
<td>Zapier's app connections and actions, the same ones Zaps use</td>
<td>One shared URL, with a server per member per client, created at sign-in</td>
<td>Account-level app and action restrictions, applied through MCP</td>
<td>User-level activity logs for tool calls, in a History tab</td>
</tr>
<tr>
<td>Elaichi: control plane with its own and vendor-run connectors</td>
<td>Elaichi authors and maintains most of its 600+ connectors; native MCP connectors are the vendor's own server</td>
<td>One organization-wide endpoint behind OAuth</td>
<td>Roles, sharing and restrictions, checked wherever a member can reach a tool, up to execution</td>
<td>Writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account actually reached</td>
</tr>
<tr>
<td><a href="https://www.merge.dev/merge-agent-handler">Merge Agent Handler</a>: not placed</td>
<td>Ask</td>
<td>Ask</td>
<td>Ask</td>
<td>Ask</td>
</tr>
</tbody>
</table>
<p>The Merge Agent Handler row is all questions, because its product page states none of the four mechanics. The Docker, Cloudflare and Microsoft rows were each checked October 2026 on the vendor page linked in that row, and the Microsoft tooling gateway is a preview inside Agent 365, which is generally available.</p>
<h2 id="which-mcp-gateways-host-the-servers-for-you">Which MCP gateways host the servers for you?</h2>
<p>MintMCP and Composio both describe a gateway the vendor runs over a catalog it lists. Your AI clients connect to the vendor rather than to servers you operate. The pull of the shape is breadth on the day you sign.</p>
<p>MintMCP calls itself "The MCP gateway between your agents and your systems", with "thousands of MCPs they can install in one click, bundled by role, access controlled and logged" (<a href="https://www.mintmcp.com/mcp-gateway">mintmcp.com</a>, checked October 2026). A company can publish an internal catalog of approved servers, host its own servers on the gateway behind its SSO, and "Group servers into one endpoint per role". MintMCP says every call is logged at the gateway, and that the audit log can be exported to a SIEM or streamed over OTLP (<a href="https://www.mintmcp.com">mintmcp.com</a>, checked October 2026). What one record holds is a question to put to MintMCP. <a href="/blog/mintmcp-alternative/">Where MintMCP and Elaichi overlap</a> is worked through separately.</p>
<p>Composio's MCP Gateway page describes "one gateway, every server" and lists 1,500+ apps (<a href="https://composio.dev/mcp-gateway">composio.dev</a>, checked September 2026). On that page, "each team gets its own MCP endpoint carrying only the tools it is permitted to use". It also lists SAML or OIDC single sign-on (SSO), so employees sign in with the company identity provider. SCIM 2.0 provisioning lets that provider create and remove accounts automatically.</p>
<p>Composio's enterprise page says permissions are "set administratively, per user and per role, down to the individual action". It says "every tool call is logged with the user, team, tool, action and outcome, denied calls included". Composio also offers self-hosting at the Enterprise tier (<a href="https://composio.dev/enterprise">composio.dev/enterprise</a>, checked September 2026). Per-team endpoints are easy to reason about inside one team. Ask what has to change, in every client, when one person moves team. <a href="/blog/one-endpoint-vs-per-team-endpoint/">Per-team and org-wide endpoints</a> compares the two address models, and <a href="/blog/elaichi-vs-composio/">the Composio breakdown</a> goes further.</p>
<p>Runlayer spans the first two shapes. It describes "AI enablement, security, and control in one platform", serving tools "through a governed MCP gateway across every major AI client" (<a href="https://runlayer.com">runlayer.com</a>, checked October 2026). Its docs define a connector as "a managed MCP server in Runlayer". Connectors come from three places. One is a catalog of templates maintained by Runlayer or by official vendors. The others are an MCP endpoint your team points Runlayer at, and a server you deploy to Runlayer's infrastructure (<a href="https://docs.runlayer.com/platform-connectors">Runlayer docs</a>, checked October 2026).</p>
<p>Each user still signs in to the provider once per OAuth connector, with their own credentials. Access rules can target users, groups, roles or agent accounts, down to specific tools. Runlayer's proxy evaluates them "on every tool invocation", and Runlayer says a saved rule "takes effect immediately" (<a href="https://docs.runlayer.com/platform-policies">Runlayer policies</a>, checked October 2026). It runs as a hosted deployment or self-hosted in your own AWS account (<a href="https://docs.runlayer.com">Runlayer docs</a>, checked October 2026). The docs describe adding a connector to a client from that connector's page, and give no URL pattern. So ask how many addresses a 200-person rollout creates, and what one audit entry holds.</p>
<p><strong>Choose this shape if</strong> breadth of listed servers on day one matters more than who authors each one. It also assumes your security review accepts a vendor hosting the servers and the credentials, although Runlayer and Composio's Enterprise tier both offer self-hosting. Before signing, ask who fixes a catalog server when its third party changes an API: the gateway vendor, or whoever published that server.</p>
<h2 id="which-mcp-gateways-sit-in-front-of-servers-you-already-run">Which MCP gateways sit in front of servers you already run?</h2>
<p>Lunar.dev's MCPX and the MCP features of Tyk, Zuplo and Kong sit in front of servers or APIs you bring. The gateway governs the traffic, and the connectors behind it belong to whoever runs those servers.</p>
<p>Lunar.dev describes MCPX as a self-hosted "Enterprise MCP Gateway" that sits between agents and the MCP servers, APIs and LLM providers they use. An open-source version is on GitHub (<a href="https://www.lunar.dev/">lunar.dev</a>, checked September 2026). Boomi announced its intent to acquire Lunar.dev on May 13, 2026, and has since completed it (<a href="https://boomi.com/blog/lunar-dev-boomi-acquisition/">boomi.com</a>, checked September 2026). If MCPX is on your list, <a href="/blog/lunar-mcpx-alternative-governed-access/">count your servers first</a>.</p>
<p>Tyk comes from API management. Tyk's MCP Gateway proxies and governs remote MCP servers, and it can generate an MCP proxy from a REST API that Tyk already manages. Proxies fronting a remote MCP server are available on all Tyk Gateway licenses, while upstream OAuth and the REST-to-MCP proxy need Tyk Enterprise Edition (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk docs</a>, checked October 2026).</p>
<p>Zuplo is an API gateway platform that also ships an MCP Gateway, which federates MCP servers behind one OAuth-protected gateway (<a href="https://zuplo.com/mcp-gateway">zuplo.com</a>, checked September 2026).</p>
<p>Kong AI Gateway supports MCP through AI MCP Server entities, which expose APIs as MCP tools (<a href="https://developer.konghq.com/ai-gateway/">Kong docs</a>, checked September 2026).</p>
<p>A proxy you run gives you anything your engineers can write, plus the pager that comes with it. <a href="/blog/api-gateway-with-mcp-vs-mcp-native/">API gateway MCP against MCP-native</a> sets the two models side by side, and <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the real cost of self-hosting</a> works through the math.</p>
<p><strong>Choose this shape if</strong> your engineers already operate MCP servers, or an API management platform already carries your traffic. An MCP feature inside a platform you already pay for may cost less than a new product. A self-hosted gateway also keeps the traffic on infrastructure you control. Elaichi is not this shape: it is a hosted service you do not run, and the server itself for the connectors it authors.</p>
<h2 id="how-does-a-per-member-server-like-zapier-mcp-work-across-a-company">How does a per-member server like Zapier MCP work across a company?</h2>
<p>Zapier MCP gives each member a server of their own inside the company's Zapier account, one per AI client. It fits a company whose automations already live in Zapier.</p>
<p>Zapier describes Zapier MCP as a way for an MCP client to take actions in the apps connected to a Zapier account. It uses the same app connections and actions as Zaps (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">Zapier help center</a>, checked September 2026).</p>
<p>Every client connects to the same Zapier URL, and "Each MCP client gets its own MCP server: one for Cursor, one for Claude, one for ChatGPT." For most MCP clients, the member signs in inside the client, and Zapier creates the server during that sign-in. Clients not on Zapier's list, and code you write, use a connection token instead. That token is long-lived, tied to one server, and "grants whoever holds it the ability to run the server's tools". Zapier says to treat it like a password and to "give each user their own server and token rather than sharing one" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">Zapier docs</a>, checked October 2026).</p>
<p>In an organization rollout, an admin acts in the MCP client, and "each member still signs in and runs tool calls as themselves". Admins can restrict members to a Zapier workspace, and app and action restrictions apply through MCP (<a href="https://docs.zapier.com/mcp/manage/rollout/overview">Zapier rollout docs</a>, checked October 2026).</p>
<p>Zapier's security page says Enterprise SAML SSO extends to MCP access. A History tab shows user-level activity logs for tool calls (<a href="https://docs.zapier.com/mcp/manage/security">Zapier security docs</a>, checked September 2026). It does not say what happens to a member's server when that member leaves the Zapier account, so ask. <a href="/blog/zapier-mcp-alternative/">One endpoint instead of one server per member</a> works through the per-member count for a full rollout.</p>
<p><strong>Choose this shape if</strong> the company already runs its automations in Zapier and the app connections people need already exist there. It suits a team small enough that one server per member stays easy to count. Nothing new has to be connected, and the app and action restrictions admins already set carry over.</p>
<h2 id="where-does-a-governed-mcp-control-plane-like-elaichi-fit">Where does a governed MCP control plane like Elaichi fit?</h2>
<p>Elaichi is the fourth shape. It authors most of its connectors, serves those from its own infrastructure, and exposes every connected account through one organization-wide endpoint behind OAuth. Its answers to the four mechanics follow, and so do its limits.</p>
<p><strong>Connectors.</strong> Elaichi serves 600+ connectors and authors and maintains most of them. The rest are native MCP connectors, each a vendor's own MCP server that Elaichi staff publish and Elaichi governs under the same rules. Your company does not run MCP servers for either kind. The authored part is a bet on one vendor's roadmap. When the app you need is missing, you author a custom connector from JSON config or fork a public one. Upstream changes then arrive through a review step that separates new tools, safe updates, conflicts and removals.</p>
<p><strong>Addresses.</strong> Every connected account is served through one organization-wide endpoint, <code>POST /mcp</code>: standard MCP over Streamable HTTP, stateless, behind OAuth. A toolbox is a saved set of tools and the accounts behind them. It never gets a URL of its own, and the address carries no embedded token. Claude, ChatGPT and Cursor all point at the same URL. An admin adds it once where the client allows, and each member then connects and signs in with their own grant.</p>
<p><strong>Access decision.</strong> Elaichi makes the decision in three layers, kept apart on purpose. Permissions are role-based access control (RBAC). Each member holds exactly one role, so each role is a complete persona. Sharing grants view, use or edit on a resource. Members see only the resources they own or that were shared with them, and org admins are no exception. Restrictions decide which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Enforcement runs at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</p>
<p><strong>Freshness.</strong> Changes land at two speeds, and an evaluation should keep them apart. A role change or a restriction change takes about two minutes to take effect, on MCP, the console and REST alike. Revoking a grant, removing a member and suspending one are all faster, and each is effective on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's revoked state is then re-read on every single call.</p>
<p><strong>Record.</strong> Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account the call actually reached, read from the execution, not from what the caller intended. A call from Claude, ChatGPT or Cursor is recorded under the person who signed in, with surface <code>mcp</code> and the client named, and those three are marked verified. The <code>ai_assistant</code> actor kind marks only the Elaichi Agent. None of it is guessed from a user agent. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. Elaichi accepts Splunk HEC and Microsoft Sentinel as destinations but delivers events only to Datadog. The read-only Auditor seat is free, so a compliance reviewer does not consume a license. <a href="/blog/what-an-ai-audit-log-must-capture/">The fields an audit row must hold</a> go into more depth.</p>
<p><strong>Choose this shape if</strong> the company does not want to operate MCP servers and uses more than one AI client. It also fits when an auditor will ask about a specific call. <strong>Look elsewhere if</strong> your engineers already run MCP servers and want policy in front of them. Look elsewhere too if a long-tail app matters more than who wrote the connector. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on the endpoint: per-operation permissions, a forbidden classification no OAuth scope can reach, output redaction, scope limits and audit logging of each call that reaches execution.</p>
<h2 id="which-mcp-gateway-fits-which-situation">Which MCP gateway fits which situation?</h2>
<p>The situation decides the shape, and the shape decides the shortlist. Find the row that matches how your company already works.</p>
<table>
<thead>
<tr>
<th>Situation</th>
<th>Shape and vendors to shortlist</th>
</tr>
</thead>
<tbody>
<tr>
<td>You already run MCP servers or APIs behind an API platform</td>
<td>A gateway you host: Lunar.dev MCPX, Tyk, Zuplo or Kong</td>
</tr>
<tr>
<td>Developers run MCP servers on their own machines and you want them contained</td>
<td>Docker MCP Gateway</td>
</tr>
<tr>
<td>You want one sign-in in front of remote MCP servers and already use Cloudflare One</td>
<td>Cloudflare MCP server portals</td>
</tr>
<tr>
<td>Everyone works in Microsoft Copilot and Teams</td>
<td>Copilot Studio governed through Power Platform, with Agent 365's gateway in preview; see <a href="/blog/copilot-studio-vs-mcp-gateway/">Copilot Studio vs an MCP gateway</a></td>
</tr>
<tr>
<td>The automation account is already paid for and tool calls are few</td>
<td>Zapier MCP</td>
</tr>
<tr>
<td>You want a catalog of approved third-party servers hosted for you</td>
<td>MintMCP, Runlayer or Composio</td>
</tr>
<tr>
<td>You run no MCP servers, hold many SaaS accounts and support several AI clients</td>
<td>A control plane that authors most of its connectors, such as Elaichi</td>
</tr>
<tr>
<td>Three people, one app and one AI client</td>
<td>Nothing yet; see <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway</a></td>
</tr>
</tbody>
</table>
<p>A company that fits two rows usually ends up with two products, and the four mechanics in this comparison say where each rule lives.</p>
<h2 id="what-should-you-ask-every-mcp-gateway-vendor-in-writing">What should you ask every MCP gateway vendor in writing?</h2>
<p>Ask every vendor the same eight questions, in writing, including the ones this page already places. A product page says what the vendor chose to publish. A written answer is something you can hold them to in a security review.</p>
<p>Merge Agent Handler gets all eight. Its product page describes a way to "securely connect your agents to thousands of third-party tools", and says nothing about the four mechanics. Its address model, credential shape and connector authorship are questions to put to Merge (<a href="https://www.merge.dev/merge-agent-handler">merge.dev</a>, checked September 2026). <a href="/blog/elaichi-vs-merge-agent-handler/">The Merge Agent Handler comparison</a> covers that decision in more depth.</p>
<p>The eight questions:</p>
<ul>
<li>Who authors the connectors, and who fixes one when a third party changes an API?</li>
<li>Is the endpoint one address for the organization, one per team, or one per member?</li>
<li>Is any URL or token a bearer credential, meaning anyone who holds it can use it, and how long does it live?</li>
<li>Who can a rule target, and how long does a change take to take effect, measured rather than promised?</li>
<li>What is in one audit record: the account actually reached, the client the call came through, and argument values or only names?</li>
<li>What happens to a leaver's access and their connected accounts on their last day?</li>
<li>Which region holds the data, and is that a guarantee or a placement preference?</li>
<li>What is the billing unit: seats, tool calls or tasks?</li>
</ul>
<p>Written answers are the comparison. A demo shows only the path the vendor chose. The billing question has its own worked comparison of <a href="/blog/mcp-gateway-pricing/">per-seat and per-call pricing</a>.</p>
<h2 id="when-should-you-buy-none-of-these-yet">When should you buy none of these yet?</h2>
<p>Six people using AI against two apps, with no auditor asking questions, do not need any of the four shapes. <a href="/blog/elaichi-vs-native-ai-connectors/">Native client connectors</a> and careful admin settings will hold for a while. If two engineers run local MCP servers on their own laptops, a gateway is overhead. Local development does not share credentials across a company, and the developer holds the key on the machine. One team building an agent against one internal database needs a server, not a control plane.</p>
<p>What these products solve is shared credentials, mixed clients and the question asked afterward. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The case for waiting</a> lists the signals that say you have waited long enough.</p>
<h2 id="how-do-you-test-a-shortlist-of-mcp-gateways-in-a-week">How do you test a shortlist of MCP gateways in a week?</h2>
<p>Run the same five steps against every vendor still on the list, and compare recordings rather than decks. Each step tests one of the four mechanics.</p>
<ol>
<li>Pick one team and one system they use daily, for example support and Zendesk. Ask each vendor who authors that connector and who fixes it when Zendesk changes its API.</li>
<li>Connect the system, point Claude or ChatGPT at the vendor's endpoint, and have two people sign in as themselves. Count the addresses and tokens the rollout created.</li>
<li>Block one destructive tool for one role, then time how long the block takes to bite. In Elaichi a restriction change takes about two minutes.</li>
<li>Run five real tasks, one built to fail. Check which account each record names, whether it marks an AI as the actor, and whether argument values were written.</li>
<li>Remove one of the two people and check what their client can still do on the next call.</li>
</ol>
<p>Step five is where the shapes separate. Browse the <a href="/connectors/">connector catalog</a> for the systems that team runs, and see <a href="/use-cases/">how each function uses governed access</a>. Check <a href="/pricing/">plans and seat counting</a> before you scope the pilot. For the definitions behind these shapes, start with <a href="/blog/what-is-an-mcp-gateway/">what an MCP gateway is</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What is the difference between an MCP gateway and an MCP control plane?</strong></dt><dd>An MCP gateway sits in front of MCP servers that somebody else runs or hosts, and governs the traffic to them. A control plane such as Elaichi is the server for the connectors it authors, and it exposes those and vendors' own MCP servers through one organization-wide endpoint behind OAuth. The practical difference is who you call when a third party changes an API, and whether your company operates MCP servers at all.</dd><dt><strong>Do you need a separate MCP endpoint for each team?</strong></dt><dd>Not with Elaichi. One organization-wide endpoint, POST /mcp, serves every AI client and every member, with no per-toolbox URLs and no embedded tokens. What varies per person is the OAuth grant, not the address. Other products divide the address by team or by member, so count the endpoints and tokens a rollout creates before comparing anything else.</dd><dt><strong>How fast does revoking an employee's AI access take effect?</strong></dt><dd>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's revoked state is re-read on every single call, so revocation holds on the next call. Role changes and restriction changes are slower. They take about two minutes to take effect, because they resolve through a 60-second cache plus edge propagation.</dd><dt><strong>What should one audit record from an MCP gateway contain?</strong></dt><dd>It should name the person, the tool, the outcome and the account the call actually reached, because the first question after an unexpected change is which of two workspaces an agent wrote to. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). It records whether an AI took the action as a field, and logs the one path argument that names the object, as the target id, and nothing else about the arguments. The read-only Auditor seat is free, so a reviewer does not consume a license.</dd><dt><strong>Which MCP gateway fits a company whose engineers already run MCP servers?</strong></dt><dd>A gateway in front of those servers, either self-hosted or part of an API management platform that added MCP. Elaichi is a hosted gateway too, and the server for the connectors it authors. It can sit in front of a company's own server, added on Gold, or on Black once it launches, as a remote MCP connector, but a team whose main job is operating its own servers is better served by a gateway.</dd><dt><strong>Where does Runlayer fit among MCP gateways?</strong></dt><dd>Runlayer describes a governed MCP gateway that spans two shapes. It serves catalog connectors maintained by Runlayer or by official vendors, and it fronts MCP endpoints your team adds or deploys. Its proxy checks access rules on every tool invocation, down to single tools, and it runs hosted or in your own AWS account. Its docs give no URL pattern, so ask how many addresses a rollout creates.</dd><dt><strong>What are the alternatives to Runlayer and MintMCP?</strong></dt><dd>The alternative depends on the shape you need rather than on a ranking. For another hosted gateway over a catalog, Composio is the closest comparison. For MCP servers you already run, a gateway you host fits better, such as Lunar.dev MCPX or an API platform that added MCP. If you hold many SaaS accounts and run no servers of your own, a control plane such as Elaichi fits: it authors most of its connectors and serves them behind one organization-wide endpoint.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>Elaichi vs Merge Agent Handler: three forks</title>
      <link>https://elaichi.ai/blog/elaichi-vs-merge-agent-handler/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/elaichi-vs-merge-agent-handler/</guid>
      <description>Elaichi vs Merge Agent Handler comes down to three forks: one address or many, a grant or a stored secret, and who authors the connectors.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> Elaichi vs Merge Agent Handler turns on three forks: the address your AI clients point at, what each client holds, and who writes the connectors. Elaichi answers with one organization-wide MCP endpoint behind OAuth, a grant per member, and 600+ connectors, most of them authored by Elaichi. Merge's product page describes Agent Handler as a way to securely connect agents to thousands of third-party tools while managing and monitoring their interactions. Its answers to the three forks are questions to put to Merge, and this post lists them.</aside>
<p>Elaichi vs Merge Agent Handler turns on three forks: the address, what the AI client holds, and who writes the connectors. Elaichi's answers are one organization-wide MCP endpoint, an OAuth grant per member, and connectors it mostly authors itself. Merge describes Agent Handler as a way to "securely connect your agents to thousands of third-party tools, while managing and monitoring all tool interactions" (<a href="https://www.merge.dev/merge-agent-handler">merge.dev</a>, checked October 2026). Its answers to the three forks are not on record here, so this post puts each one to Merge as a question.</p>
<p>The request usually arrives from one team. Support wants Claude to read Zendesk. Two weeks later finance wants ChatGPT near Xero, and legal has questions about both. You are now picking a shape you will have to defend in a year.</p>
<h2 id="elaichi-vs-merge-agent-handler-what-can-be-compared">Elaichi vs Merge Agent Handler: what can be compared?</h2>
<p>Every Elaichi row below can be stated from the product itself. Every Merge row is a question. This blog states a named vendor's behavior only from that vendor's own page, with the date it was read. For Agent Handler that is one line on <a href="https://www.merge.dev/merge-agent-handler">Merge's product page</a> (checked October 2026). Elaichi is a governed MCP control plane. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<table>
<thead>
<tr>
<th>Row</th>
<th>Elaichi</th>
<th>Merge Agent Handler</th>
</tr>
</thead>
<tbody>
<tr>
<td>Address model (fork one)</td>
<td>One organization-wide <code>POST /mcp</code> endpoint behind OAuth; every AI client points at the same address</td>
<td>Ask Merge: how many endpoints exist at 200 employees, and who creates each one</td>
</tr>
<tr>
<td>Credential shape (fork two)</td>
<td>The client holds an OAuth grant only; per-account secrets sit in a separate credential service, AES-256-GCM at rest</td>
<td>Ask Merge: what the client stores, and whether any part of it is long-lived</td>
</tr>
<tr>
<td>Connector authorship (fork three)</td>
<td>Elaichi serves 600+ connectors and authors most of them, the rest being vendors' own MCP servers; custom or forked connectors via JSON config, with a review surface for upstream changes</td>
<td>Ask Merge: who writes the connectors, and who fixes one when the upstream API changes</td>
</tr>
<tr>
<td>Audit</td>
<td>Keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none), naming the account reached; logs the one path argument that names the object, as the target id, and nothing else about the arguments; free read-only Auditor seat</td>
<td>Ask Merge: which calls get an entry, and does it name the connected account reached</td>
</tr>
<tr>
<td>Offboarding</td>
<td>Grant revocation effective on the next call; a preflight lists every connection the departing member owns; a private one a shared toolbox relies on blocks removal until it is transferred to one member or deleted</td>
<td>Ask Merge: is removal effective by cache expiry or by transaction, and what happens to personal connections</td>
</tr>
<tr>
<td>Pricing</td>
<td>Per user: Gold lists at $15 per user per month in USD, or $120 per user per year (<a href="/pricing/">pricing</a>); 14-day trial</td>
<td>Ask Merge: which billing unit, whether seats, tool calls or tasks</td>
</tr>
</tbody>
</table>
<p>Borrow the same rule for your own evaluation. Read each vendor's product documentation rather than a comparison grid, this one included. A vendor whose docs answer the address, credential and connector questions in plain language can be evaluated in an afternoon.</p>
<h2 id="fork-one-is-the-address-per-user-or-per-organization">Fork one: is the address per user or per organization?</h2>
<p>Elaichi gives the whole organization one address. Every SaaS account is connected once, and its tools are served through one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth. It speaks standard MCP over Streamable HTTP and JSON-RPC 2.0. The MCP specification defines that transport as one HTTP POST per message to a single endpoint (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports">MCP transports</a>). There are no per-toolbox URLs and no embedded tokens. There is no MCP server to create, list or revoke per person, so what varies between members is the grant, not the address.</p>
<p>That shows up at rollout. An admin adds the URL once where the client allows it, and each member then connects and signs in with their own grant. In Claude Team or Enterprise an owner adds it under Organization settings > Connectors, while on Pro or Max each person adds it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166">Anthropic's guide</a>). Cursor's admin MCP allowlist is Enterprise only and "does not push it to users' machines", so each developer adds it in their own Cursor (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor's docs</a>). ChatGPT's steps are in <a href="/blog/connect-elaichi-to-chatgpt/">connecting Elaichi to ChatGPT</a>. A fourth MCP client is the same shape, not a fresh project.</p>
<p>Other shapes multiply what sits behind the address. Zapier MCP gives every client the same endpoint, but "Each MCP client gets its own MCP server", so each member holds one server per client. For clients that use a connection token, Zapier says to "give each user their own server and token rather than sharing one" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how Zapier MCP connections work</a>, checked October 2026). Composio's MCP Gateway page says "each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked October 2026). Both are built for a different reader, and both multiply the things you track. The <a href="/blog/zapier-mcp-alternative/">arithmetic of one organization server against one per member</a> is worked through on its own. Ask Merge how many addresses exist at 200 employees, and who creates each one.</p>
<h2 id="fork-two-what-does-the-ai-client-actually-hold">Fork two: what does the AI client actually hold?</h2>
<p>With Elaichi, the client holds an OAuth grant and nothing else. OAuth is the sign-in handshake that gives an application limited access without handing over a password. The MCP authorization spec makes the server an OAuth 2.1 resource server, and it says access tokens "MUST NOT be included in the URI query string" (<a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization</a>). Elaichi embeds no token in its URL, and no secret sits in a client config file.</p>
<p>Revocation follows from that. The grant's <code>revoked_at</code> field is re-read from the organization store on every single call, with no cache. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next call is already blocked. Role and restriction changes work differently. They resolve through a short cache and take effect within about two minutes.</p>
<p>Connector credentials never live in Elaichi. Per-account secrets sit in a separate credential service, encrypted with AES-256-GCM at rest, and that service owns refresh. A failed refresh marks the connection <code>needs_reauth</code> rather than failing quietly. A connect URL is a one-time session carrying no token, which is why it is safe to return over MCP. An organization can also supply its own OAuth app per connector, gated on <code>connector:manage</code> rather than <code>connection:manage</code>.</p>
<p>The contrast to test is a long-lived string in a config file. For clients outside its supported list, and for code, Zapier MCP uses a connection token. Zapier's docs say that token is long-lived, tied to one server, and "grants whoever holds it the ability to run the server's tools" (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>, checked October 2026). Ask Merge what the AI client stores, and what happens to it when the holder leaves.</p>
<h2 id="fork-three-who-writes-the-connectors-you-depend-on">Fork three: who writes the connectors you depend on?</h2>
<p>Elaichi serves 600+ connectors, and authors and maintains most of them on its own infrastructure. The rest are vendors' own MCP servers, each published by Elaichi staff rather than drawn from an open registry. Your company does not run MCP servers. When a connector Elaichi wrote breaks, there is one party to fix it. Reports about a native MCP connector's tools go to the app's vendor.</p>
<p>Custom work has a path. A connector can be authored from JSON config or forked from a public connector. A fork can pull upstream changes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default. The <code>connector:create</code> permission is flagged high trust, because a custom connector can be pointed at any destination.</p>
<p>The trade-off, stated plainly: if the app you need is not in the catalog, somebody has to author or fork it. A vendor that lists servers other people publish may show that app on its site today, and whether it works next month depends on whoever publishes it. Merge's page counts its tools in the thousands (<a href="https://www.merge.dev/merge-agent-handler">merge.dev</a>, checked October 2026). Ask Merge who writes them, and who fixes one when the upstream API changes. The <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">managed versus run-it-yourself cost breakdown</a> covers the third option.</p>
<h2 id="who-decides-which-tools-each-person-can-use">Who decides which tools each person can use?</h2>
<p>Admins do, through three layers Elaichi keeps separate on purpose. Permissions are 58 action strings grouped into roles, and a member holds exactly one role, enforced by a unique index. Sharing is one grant of view, use or edit on a resource to a user, a team or the whole organization. Members see their own resources and the ones shared with them, and nothing else. Restrictions decide which connectors and which individual tools a target may reach.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Within each layer, blocks always beat allows. One trap: the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. A block can catch a tool by its name or by the operation behind it. An allow counts only the operation, because a tool's displayed name is a label the governed party can edit. The <a href="/blog/block-matches-name-allow-matches-operation/">name against operation rule</a> explains the asymmetry.</p>
<p>Frozen parameters handle the narrower case where one argument must not move. A frozen key is removed from the schema the model is shown, and its value is merged over whatever the caller sends at execution. Passing the key cannot unfreeze it. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself.</p>
<h2 id="which-tools-does-the-model-see">Which tools does the model see?</h2>
<p>Control-plane operations, such as managing members or connections, are listed individually. App tools are handled differently: connected tools are never listed one by one, however few there are. The model looks a tool up through <code>search_tools</code> and calls it through <code>execute_tool</code>, which is only a naming indirection. It unwraps to the same name and arguments and falls through the identical gates.</p>
<p>Ranking is lexical over tool name, description and connector label, with a floor on relevance. A tool must account for at least half of the query's weight, where rarer words weigh more. Without a floor a search always returns something, and something from an app you did not ask about is worse than nothing, because the model calls it. The <a href="/blog/search-tools-ranking-floor-idf/">reasoning behind the floor</a> sets out the incident that produced it.</p>
<h2 id="what-does-the-audit-trail-record-after-a-tool-call">What does the audit trail record after a tool call?</h2>
<p>Elaichi's trail holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The account on each entry is the one the call actually reached, taken from the execution rather than the intent. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments. Each entry also records the surface, <code>mcp</code>, and the OAuth client, with Claude, ChatGPT and Cursor marked verified. The call is recorded under the person who signed in, so the client is known at the point of action instead of guessed later from a user agent.</p>
<p>Two error strings exist per failed call. The one returned to the caller is derived from the third party's response body and is never written anywhere else. The one written to the audit trail is never derived from the request or the response, because audit records are organization-visible and fanned out to whatever SIEM the customer configured. In Elaichi, export to your own Datadog comes with the Black plan, which is launching soon. Splunk HEC and Microsoft Sentinel are accepted as destinations, but Elaichi delivers events only to Datadog. The trail is append-only and eventually consistent, so a row may take a moment to appear. The read-only Auditor seat is free, so a compliance reviewer does not consume a license.</p>
<p>One honest limit. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds on the endpoint is a role check per operation, the <code>forbidden</code> classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution.</p>
<h2 id="how-fast-does-access-end-when-somebody-leaves">How fast does access end when somebody leaves?</h2>
<p>On the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the departing person's next call fails. The cleanup around it is the part that usually gets missed.</p>
<p>Elaichi runs an offboarding preflight. It lists every connection the departing member owns. A private connection pinned by a toolbox its owner shared blocks the removal until an admin transfers it to one other active member or deletes it, where a toolbox is a named set of configured tools. A private connection that nothing beyond the member depends on cannot be transferred and is deleted with them. Nothing transfers to a team, the organization or the admin running the removal. A shared connection stays in place unless the admin names an action. Deleting it takes an explicit request. Otherwise transfer it to a member who is staying, which leaves every grant on it as it was. Delegated toolbox entries surface as a non-blocking warning, and re-pinning the entry is the fix. The <a href="/blog/offboarding-when-the-agent-holds-access/">contractor offboarding sequence</a> walks through a live case.</p>
<h2 id="where-is-data-held-and-how-do-people-sign-in">Where is data held, and how do people sign in?</h2>
<p>Elaichi has three regions, <code>eu</code>, <code>us</code> and <code>apac</code>, chosen at organization creation and fixed afterwards. For EU and US, the organization's data store and the execution of its org-scoped requests and tool calls stay in that jurisdiction. APAC uses best-effort placement and is not a residency guarantee. Connections created since 2026-10-05 have credentials placed in the organization's region, by best-effort placement for APAC. Older connections stay where they were until reconnected, which copies them into the region. Credentials are encrypted at rest with AES-256-GCM. The audit trail is stored in one EU log instance for every region.</p>
<p>Sign-in covers Google, GitHub and Microsoft, email codes, TOTP MFA with single-use recovery codes, and passkeys. SAML and OIDC SSO are built in-house, with SCIM v2 for users and groups and group-to-role mapping. Onboarding has four paths: emailed single-use invite links with roles and teams pre-assigned, verified-domain auto-join with a configurable default role, SCIM provisioning, and just-in-time SSO.</p>
<h2 id="when-is-a-different-product-the-better-buy">When is a different product the better buy?</h2>
<p>Sometimes the other product wins, and saying so saves a procurement cycle. If the job is pulling your customers' data into your own product, that is a unified API problem rather than an employee access problem, and Elaichi is the wrong tool for it. Ask Merge whether Agent Handler is built for agents your own product ships, or for employees working in their own AI clients.</p>
<p>If your engineers need per-user sessions in application code, rather than employees working inside Claude, look at a developer-first product. Composio's homepage addresses developers building agents, and its docs describe an SDK with per-user sessions and managed auth (<a href="https://composio.dev">composio.dev</a>, <a href="https://docs.composio.dev">docs.composio.dev</a>, checked October 2026). There is a <a href="/blog/elaichi-vs-composio/">side-by-side with Composio</a> here.</p>
<p>If two people in one team need one app, buy nothing yet. The case for <a href="/blog/when-you-dont-need-an-mcp-gateway/">holding off on a gateway</a> is real, and a control plane over a single connection is overhead with a monthly bill. When the time comes, Gold lists at $15 per user per month in USD, and the <a href="/pricing/">pricing page</a> shows the price for your region.</p>
<h2 id="what-should-you-ask-merge-before-you-sign">What should you ask Merge before you sign?</h2>
<p>Write these down and send them. The answers are more useful than any comparison table, this one included.</p>
<ul>
<li>Is Agent Handler built for agents your product ships to customers, or for employees working in Claude, ChatGPT and Cursor?</li>
<li>How many endpoints exist for a 200-person company, and who creates each one?</li>
<li>What does the AI client store, and is any part of it long-lived?</li>
<li>When a person is removed, how long until their next tool call fails, and is that a cache or a transaction?</li>
<li>Who authors the connectors, and who fixes one when the upstream API changes?</li>
<li>Which tool calls get an audit entry, and does it name the connected account reached?</li>
<li>Can you choose a region that holds the data store, the credentials and the calls?</li>
<li>Is SSO over SAML and OIDC included, with SCIM provisioning and group-to-role mapping?</li>
<li>What is the billing unit: seats, tool calls, or tasks?</li>
</ul>
<h2 id="how-can-two-people-evaluate-both-in-a-week">How can two people evaluate both in a week?</h2>
<p>Pick one team and one app, then give it a week and two people: an IT owner and one person from that team. Support with Zendesk works. So does <a href="/blog/sales-team-chatgpt-salesforce-accounts/">sales with Salesforce</a>.</p>
<p>Run the same script against each vendor. The point is not to see whether a read call succeeds, because any working product manages that. The point is to see what breaks when a person leaves, and what the record shows afterwards.</p>
<h2 id="what-decides-the-choice-in-the-end">What decides the choice in the end?</h2>
<p>Three forks decide it: one address or many, a grant or a stored secret, and connectors from the vendor or from a registry. Everything else is a feature list that will have changed by the time you renew.</p>
<p>The other <a href="/blog/category/comparisons/">vendor comparisons</a> run the same structure against named products. Check the <a href="/connectors/">connector catalog</a> for the apps your teams actually use, and the <a href="/use-cases/">team use cases</a> page for what a first rollout looks like.</p>
<h2>FAQ</h2><dl><dt><strong>What does Merge say Agent Handler does?</strong></dt><dd>Merge's product page describes Agent Handler as a way to "securely connect your agents to thousands of third-party tools, while managing and monitoring all tool interactions" (https://www.merge.dev/merge-agent-handler, checked October 2026). That is the one statement about it this blog makes. Its address model, what an AI client stores and who authors its connectors are questions to put to Merge directly.</dd><dt><strong>How many MCP endpoints does Elaichi create for a company?</strong></dt><dd>One. Elaichi serves every connected SaaS account through a single organization-wide MCP endpoint, POST /mcp, using standard MCP over Streamable HTTP and JSON-RPC 2.0, behind OAuth. There are no per-toolbox URLs, no embedded tokens, and no per-user MCP server to create or revoke. Claude, ChatGPT, Cursor and any other MCP client point at that one address, and each member connects once and signs in with their own grant.</dd><dt><strong>How quickly does revoking someone's access take effect in Elaichi?</strong></dt><dd>It depends on what changed. Grant revocation, member removal and member suspension are effective on the next call, because the grant's revoked_at field is re-read from the organization store on every call with no cache, and removing or suspending a member revokes every live grant in the same transaction as the membership change. Role changes and restriction changes resolve through a short cache and take effect within about two minutes.</dd><dt><strong>Who writes the connectors that Elaichi serves?</strong></dt><dd>Elaichi authors and maintains most of its 600+ connectors on its own infrastructure. The rest are native MCP connectors, each the app vendor's own MCP server, which the vendor builds and runs and Elaichi governs. Customer companies do not run MCP servers themselves. An organization can also author a custom connector from JSON config, or fork a public one and pull upstream changes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals.</dd><dt><strong>What does Elaichi cost, and is there a trial?</strong></dt><dd>Elaichi has two plans, Gold and Black. Gold lists at $15 per user per month in USD, or $120 per user per year, and https://elaichi.ai/pricing/ shows the price for your region. Gold starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Billable seats are active memberships with a minimum of one. Suspended members and the free-seat roles, Guest, Billing Admin and the read-only Auditor, are not counted.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>MCP server registry vs first-party connectors</title>
      <link>https://elaichi.ai/blog/mcp-registry-vs-first-party-connectors/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-registry-vs-first-party-connectors/</guid>
      <description>MCP server registry vs first-party connectors comes down to who fixes a broken tool: each server&apos;s own author, or one vendor that wrote and serves them.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> The MCP server registry vs first-party connectors choice decides who owns maintenance. A registry lists servers that other people write and run, so a broken tool sits in somebody else's queue while you route around it. Elaichi authors, maintains and serves most of its connectors behind one organization-wide MCP endpoint, so for those the repair path is a single vendor. The cost is coverage: one vendor's catalog is one vendor's roadmap.</aside>
<h2 id="mcp-server-registry-vs-first-party-connectors-what-is-the-difference">MCP server registry vs first-party connectors: what is the difference?</h2>
<p>MCP server registry vs first-party connectors is a choice about authorship. A registry lists servers that other people write and run. First-party connectors are written, maintained and served by one vendor. Both speak MCP: MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Both can put a policy check in front of a call. They differ on who repairs a tool when it breaks.</p>
<p>The protocol now has an official registry to measure the term against. The <a href="https://modelcontextprotocol.io/registry/about">official MCP Registry</a> calls itself a "centralized metadata repository for publicly accessible MCP servers". It hosts metadata that points to packages on npm, PyPI or Docker Hub, not the code itself. Its metadata is "deliberately unopinionated", and it leaves security scanning to those package registries and to the marketplaces built on top of it. As of October 2026 it is still in preview.</p>
<table>
<thead>
<tr>
<th>Axis</th>
<th>MCP server registry</th>
<th>First-party connectors (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Quality control</td>
<td>Varies by each server's author and the catalog's admission policy</td>
<td>One vendor's bar applied to every connector it authors</td>
</tr>
<tr>
<td>Maintenance ownership</td>
<td>Whoever wrote the server, on their release cadence</td>
<td>Elaichi owns the fix for its own connectors; the app vendor builds and runs a native MCP connector's tools</td>
</tr>
<tr>
<td>Security review</td>
<td>Spread across authors, package registries and marketplaces</td>
<td>Single review surface across the connectors Elaichi authors</td>
</tr>
<tr>
<td>Updates</td>
<td>Ship when each author ships</td>
<td>Ship behind the same <code>POST /mcp</code> clients already use</td>
</tr>
<tr>
<td>Coverage</td>
<td>Broad and grows fast, long tail included</td>
<td>Bounded to what one vendor writes or publishes, 600+ connectors</td>
</tr>
<tr>
<td>Setup effort</td>
<td>Enable per server, sometimes host it, per-server credentials</td>
<td>Connect a SaaS account once, one endpoint for every client</td>
</tr>
</tbody>
</table>
<p>A tool that worked in March returns an error in April. The agent retries, summarizes something vague, and an analyst opens a ticket with IT. How long that ticket stays open is decided by authorship.</p>
<p>Breadth is what you evaluate on the day you buy. Repair is what you live with every week after. A registry gives you a long list quickly. First-party authorship gives you one party to hold to a fix. Pick the variable you will be measured on, which for most IT and operations owners is time to a working tool, not the count of available tools.</p>
<h2 id="who-fixes-the-tool-when-the-saas-vendor-changes-its-api">Who fixes the tool when the SaaS vendor changes its API?</h2>
<p>In a federated shape, the fix belongs to whoever authored the server. That is sometimes the SaaS vendor, sometimes a community maintainer, sometimes the gateway vendor when it hosts the server too. Your gateway can block the broken tool, pin an older version if one exists, or wait. None of those is a repair. The repair happens in a repository you do not control, on a schedule you do not set. If forty teams run forty applications, the worst case is forty separate maintainers with forty separate release cadences.</p>
<p>In a first-party shape, the connector is the vendor's own code. Elaichi serves 600+ connectors and authors, maintains and runs most of them on its own infrastructure. The rest are native MCP connectors: each app vendor's own server, published by Elaichi staff one by one rather than drawn from a registry, and governed under the same rules. Companies do not run MCP servers. A broken tool in a connector Elaichi wrote is one vendor's defect with one queue behind it.</p>
<p>Breakage also arrives quietly through credentials. Connector credentials never live in Elaichi. A separate credential service holds per-account secrets, encrypted at rest with AES-256-GCM, and owns token refresh. When a refresh fails, the connection is marked <code>needs_reauth</code> rather than failing silently. An admin sees a state instead of a run of confusing tool errors.</p>
<h2 id="what-is-a-federated-registry-built-for">What is a federated registry built for?</h2>
<p>A registry-and-gateway product is built for an organization that already runs MCP servers, or that wants a wide catalog immediately. Lunar.dev describes a self-hosted enterprise MCP gateway that sits between agents and the MCP servers, APIs and LLM providers they use (<a href="https://www.lunar.dev/">lunar.dev</a>, checked October 2026). Tyk's MCP Gateway proxies and governs remote MCP servers, and Tyk Gateway can also generate an MCP proxy from a Tyk-managed REST API (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk's documentation</a>, checked October 2026). If servers already exist in your estate, that is the natural fit and the reason those products exist.</p>
<p>Hosted variants move the running off your machines. Whether they also move the authorship depends on the vendor. Composio Connect is an MCP server at <code>https://connect.composio.dev/mcp</code> that gives an agent access to "1000+ apps" through 7 meta-tools (<a href="https://docs.composio.dev/docs/composio-connect">Composio's documentation</a>, checked October 2026). Ask any vendor in this shape two things in writing: who writes the patch when a tool in its catalog breaks, and how long a patch usually takes to ship.</p>
<h2 id="what-does-first-party-authorship-cost-you">What does first-party authorship cost you?</h2>
<p>It costs you optionality. One vendor's catalog is one vendor's roadmap. If the app your legal team runs is not in it, you wait or you author it yourself. Name that constraint before it surprises you in month three.</p>
<p>Elaichi's answer to the gap is custom connectors authored from JSON config, which can also be forked from a public connector. The permission that allows this, <code>connector:create</code>, is flagged high trust, because a custom connector can be pointed at any destination. Keep it in a small number of roles. The second cost is that you cannot run the connector code inside your own network. If that is a hard requirement, read <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">what self-hosting MCP servers actually costs</a> instead.</p>
<h2 id="does-a-broken-connector-change-the-address-your-clients-point-at">Does a broken connector change the address your clients point at?</h2>
<p>With Elaichi, no. Every connected account is served through one organization-wide MCP endpoint, <code>POST /mcp</code>, which speaks standard MCP over Streamable HTTP. It sits behind OAuth, the sign-in protocol that issues a client a grant instead of a shared secret. There are no per-toolbox URLs and no embedded tokens.</p>
<p>An admin adds that address once where each client allows it, and each member then connects and signs in with their own grant. In Claude Team and Enterprise, the owner's step is Organization settings > Connectors. Members then find the connector under Customize > Connectors and click Connect (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Claude's help center</a>, as of October 2026). In ChatGPT, full MCP with write actions is a beta on Business, Enterprise and Edu plans. An admin creates and publishes the app there (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help center</a>, as of October 2026). <a href="/blog/connect-elaichi-to-chatgpt/">Connecting Elaichi to ChatGPT</a> walks through the steps. A connector fix ships behind the same address, and nobody reconfigures a client.</p>
<p>Address models differ across the category, and the vendor's own words are the thing to read. Composio's MCP Gateway page says "Each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">composio.dev</a>, checked October 2026). More endpoints is not automatically worse. Every address is still something somebody has to maintain, distribute and retire. Count them before you commit.</p>
<h2 id="does-a-bigger-catalog-mean-a-longer-tool-list-for-the-model">Does a bigger catalog mean a longer tool list for the model?</h2>
<p>Not with Elaichi. Federating many servers grows the list of tools a client hands the model before it picks one. In Elaichi, connected tools are never listed one by one, however few there are. The model searches with <code>search_tools</code> and calls its pick through <code>execute_tool</code>, while control-plane operations stay listed individually.</p>
<p>Ranking inside <code>search_tools</code> is purely lexical over tool name, description and connector label. A relevance floor, a minimum share of the query that a tool must match, keeps a query about one app from returning a plausible tool from another. That matters because a wrong tool is worse than none: the model calls it. <a href="/blog/search-tools-ranking-floor-idf/">How tool search picks one tool from hundreds</a> covers the mechanics.</p>
<h2 id="can-a-connector-update-change-what-your-rules-mean">Can a connector update change what your rules mean?</h2>
<p>It can, if rules bind to names. A tool's advertised name can be edited by whoever maintains the connector's documentation, so a rule written against a name is written against a label the governed party controls. Elaichi pins the canonical operation against the catalog when you write the rule. A block matches on the tool name or the pinned operation. An allow matches on the pinned operation only. <a href="/blog/block-matches-name-allow-matches-operation/">Why a block matches the name and an allow does not</a> sets out the reasoning.</p>
<p>In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Plan for the delay when you change a rule. A restriction or role change takes effect within about two minutes, on the MCP endpoint, the console and the REST surface alike. Grant revocation, member removal and suspension take effect on the next call, because a grant's revoked state is re-read on every call. During an incident, revoke the grant rather than editing a restriction.</p>
<h2 id="what-does-the-audit-trail-show-when-one-vendor-owns-the-code">What does the audit trail show when one vendor owns the code?</h2>
<p>One record shape. Elaichi writes audit events and application logs in the same shape, so a single query answers what happened instead of correlating two systems by eye. It keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry names the account the call actually reached, taken from the execution rather than from the intent. After an unexpected change, the first thing anyone asks is which of two Notion workspaces the agent wrote to, and the entry says.</p>
<p>The log pipe has a firewall in it. Two error strings exist per failed call. The one returned to the caller is derived from the third party's response body and is never written anywhere else. The one written to the audit trail is never derived from the request or the response. Audit records are visible across the organization and readable by the in-product assistant, and a vendor's error body written there would leak third-party data through the log. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<h2 id="what-happens-to-connections-when-somebody-leaves">What happens to connections when somebody leaves?</h2>
<p>Offboarding runs a preflight. It lists every connection the departing member owns, private and shared alike. A private connection pinned by a toolbox (a shared, saved set of tools and the accounts they use) blocks the removal until the admin transfers it to another active member, never to the admin running the removal. A private connection nothing else depends on cannot be transferred and is deleted with the member. A shared connection a team depends on is left untouched unless the admin deletes it, so transfer it to someone staying and every grant on it stays as it was. Delegated toolbox entries surface as a non-blocking warning, and re-pinning is the fix.</p>
<p>Ask a federated vendor the same thing in plain terms: what happens to the servers and credentials attached to a member who leaves. <a href="/blog/offboarding-when-the-agent-holds-access/">What to do about departing contractors and AI access</a> works through the contractor version.</p>
<h2 id="can-you-fork-a-connector-and-still-get-upstream-fixes">Can you fork a connector and still get upstream fixes?</h2>
<p>Yes. Forking is the middle path when the shipped connector is close but not right. A forked connector can pull upstream changes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default, so accepting an upstream batch does not silently delete a tool a synthetic tool depends on.</p>
<p>Two guardrails keep the maintenance story predictable. A connector cannot be deleted while connections still use it. A forked connector's identity includes its declared lineage, walked to the root, block-only, and failing closed if the chain is truncated or cyclic. A fork cannot be used to shed a block that applied to its parent.</p>
<h2 id="when-is-a-registry-the-right-answer">When is a registry the right answer?</h2>
<p>A registry-and-gateway product fits when you already run MCP servers you intend to keep. It also fits when your engineers author servers over proprietary databases, or when you need an app today that no first-party catalog covers. For internal servers, the <a href="https://modelcontextprotocol.io/registry/about">official MCP Registry</a> is not the place: it does not support private servers and recommends running a private registry of your own.</p>
<p>A first-party control plane is the right answer when your bottleneck is tickets about broken tools and clients that need reconfiguring.</p>
<p>Sometimes you need neither shape yet. If two people use one assistant against one app, and that app ships an MCP server your client can point at directly, point it there and revisit in a quarter. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The cases where a gateway is premature</a> are written up separately.</p>
<h2 id="how-do-you-decide-in-an-afternoon">How do you decide in an afternoon?</h2>
<p>Run this before you sit through another demo. It takes about two hours and produces an answer you can defend.</p>
<ol>
<li>List the six apps your agents must reach next quarter. Not twenty, six.</li>
<li>For each, find out who authors the MCP server or connector, and where the code lives.</li>
<li>Ask each vendor, in writing, who patches a broken tool and what the median turnaround is.</li>
<li>Count the addresses each shape leaves you maintaining, per team and per client.</li>
<li>Check how long a rule change takes and how long an access cut takes, separately. They are different numbers.</li>
</ol>
<p>For a per-team rollout order, see the twelve <a href="/use-cases/">team playbooks</a>. The <a href="/connectors/">connector catalog</a> lists what is authored and served, and <a href="/blog/category/comparisons/">the rest of the comparisons</a> cover the other shapes in this category.</p>
<h2>FAQ</h2><dl><dt><strong>What is an MCP server registry?</strong></dt><dd>A catalog of MCP servers that other parties publish and run. The official MCP Registry describes itself as a centralized metadata repository for publicly accessible MCP servers. It stores metadata that points to packages hosted elsewhere, leaves security scanning to those package registries and to the marketplaces built on it, and was still in preview in October 2026. Gateway products federate servers like these behind one entry point, while maintenance of each server stays with whoever wrote it.</dd><dt><strong>Who maintains a first-party MCP connector?</strong></dt><dd>The vendor that authors it. In Elaichi's case most connectors are written, maintained and served from Elaichi's own infrastructure, so a tool that stops working after a SaaS API change is one vendor's defect with one support queue behind it. A native MCP connector is the app vendor's own server, so reports about its tools go to that vendor. Companies using Elaichi do not run MCP servers themselves.</dd><dt><strong>Does a connector fix force me to reconfigure my AI clients?</strong></dt><dd>Not with a single-endpoint model. Elaichi serves every connected account through one organization-wide MCP endpoint at POST /mcp, with no per-toolbox URLs and no embedded tokens, so a connector fix ships behind the same address that Claude, ChatGPT and Cursor already use. Models that issue an endpoint per team or per member leave more addresses to maintain when something changes.</dd><dt><strong>Do I still need a registry or gateway for internal APIs?</strong></dt><dd>If your engineers author MCP servers over proprietary internal databases, a self-hosted gateway or a private registry is the fitting architecture, because you own both the API and the server in front of it. The official MCP Registry lists only publicly accessible servers and recommends a private registry for internal ones. A first-party connector catalog answers a different problem: reaching the SaaS accounts a company already pays for without anybody running server code.</dd><dt><strong>Can a forked connector keep receiving upstream fixes?</strong></dt><dd>Yes. A connector forked from a public one can pull upstream changes through a review surface that separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default, so accepting an upstream batch does not quietly remove a tool something else depends on.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>How to roll out Cursor to an engineering team</title>
      <link>https://elaichi.ai/blog/engineering-team-cursor-jira/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/engineering-team-cursor-jira/</guid>
      <description>To roll out Cursor to an engineering team, connect Jira and Slack once, block deletes per role, pin the project and channel, then have engineers sign in.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> To roll out Cursor to an engineering team with Elaichi, connect Jira and Slack once, give engineers one role, block the deletes and webhooks, and freeze the Jira project and the Slack channel on a toolbox shared with the team in place of the connections. Each engineer then adds one organization-wide endpoint in their own Cursor and signs in with OAuth. GitHub is not in Elaichi's catalog, so it needs a custom connector or stays outside the rollout. Rule changes take about two minutes, and removing a member ends their access on the next call.</aside>
<p>An engineer adds a Jira server to her Cursor config, pastes a personal API token, and her agent starts filing tickets. Within a month the snippet has spread around the team. Nobody can list who holds which token, or what each one can reach. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>To roll out Cursor to an engineering team on purpose, turn that order around. Connect the accounts and write the rules first, and let the editor come last. This playbook does it for Jira and Slack, and it is plain about GitHub, which Elaichi does not connect.</p>
<h2 id="how-do-you-roll-out-cursor-to-an-engineering-team">How do you roll out Cursor to an engineering team?</h2>
<p>Connect Jira and Slack once for the company, share engineers a toolbox of the tools they need, give them one role with rules on it, and then point Cursor at a single address. Each engineer adds that address in their own Cursor and signs in as themselves. Nobody pastes a token into a file.</p>
<p>Elaichi serves every connected account through one organization-wide endpoint, <code>POST /mcp</code>, which is standard MCP over Streamable HTTP behind OAuth. An endpoint is the web address a client calls. OAuth is the sign-in flow that gives a client a grant, a revocable permission tied to one person, instead of a copied secret. The grant is what differs between engineers, and it is what you revoke when someone leaves. Elaichi writes and hosts the Jira and Slack connectors itself, so your team runs no MCP server of its own.</p>
<p>Cursor reads its MCP servers from JSON: <code>~/.cursor/mcp.json</code> applies everywhere, and a project's <code>.cursor/mcp.json</code> applies to that project, per Cursor's <a href="https://cursor.com/docs/mcp">MCP documentation</a>. A remote server such as Elaichi is a <code>url</code> entry in that file, and Cursor supports OAuth for servers that require it. The same page says "MCP distribution and MCP policy are configured separately."</p>
<p>Distribution is the team admin's half. A Cursor team admin can add Elaichi as a shared Team MCP server under Dashboard, Plugins &#x26; MCPs, then choose Add to Team Marketplace. That makes it available in the Agent Window, the IDE and the CLI, where engineers install it from Customize. Linking a server to a marketplace "does not install or enable it for everyone". Policy is the other half: only Enterprise admins set the MCP allowlist. Cursor's <a href="https://cursor.com/docs/enterprise/model-and-integration-management">enterprise admin docs</a> say adding a server to it "does not push it to users' machines".</p>
<p>So the per-engineer step is small but real: install or add the address once, then finish the OAuth sign-in. Cursor asks for approval before using MCP tools by default, so engineers see each call before it runs. Claude and ChatGPT take the same address if the company uses them too.</p>
<p>Behind the address, three layers decide what an engineer's agent can reach. Permissions are role-based access control (RBAC): 58 action strings, such as <code>tool:execute</code>, grouped into roles, with exactly one role per member. Sharing decides which connections and toolboxes a member can use at all, and no admin role widens that view. Restrictions decide which connectors and which individual tools a target may reach, and most of this playbook is about them.</p>
<h2 id="can-cursor-reach-github-through-elaichi">Can Cursor reach GitHub through Elaichi?</h2>
<p>No. GitHub is not in Elaichi's connector catalog, so this rollout cannot hand engineers governed GitHub tools.</p>
<p>There are two honest options. The first is a custom connector. Elaichi custom connectors are authored from JSON config, and creating one needs the <code>connector:create</code> permission. Elaichi flags that permission as high trust, because a custom connector can be pointed at any destination. Treat it as a small engineering project with an owner. Whoever writes the config decides which GitHub operations exist at all.</p>
<p>The second option is to leave GitHub out of this rollout. Engineers keep reaching GitHub the way they do today, and the governed address covers Jira and Slack.</p>
<p>GitHub does appear in Elaichi in one place, as a way to sign in to Elaichi itself, next to Google and Microsoft. That is an identity option, not a connector, and it gives Cursor no GitHub tools.</p>
<p>The rest of this playbook covers <a href="/connectors/jira/">Jira</a> and <a href="/connectors/slack/">Slack</a>, which the catalog does have. If your team tracks work somewhere other than Jira, check the <a href="/connectors/category/ticketing/">ticketing connectors</a> before you plan around one.</p>
<h2 id="what-can-an-engineer-do-in-jira-and-slack-on-day-one">What can an engineer do in Jira and Slack on day one?</h2>
<p>Most of the work around the code: reading the issue, finding related bugs, filing new ones, noting what changed and telling the team.</p>
<table>
<thead>
<tr>
<th>What the engineer asks Cursor for</th>
<th>Tool that runs</th>
</tr>
</thead>
<tbody>
<tr>
<td>The issue being fixed, with its discussion</td>
<td><code>get_single_jira_issue_by_id</code>, <code>list_all_jira_issue_comments</code></td>
</tr>
<tr>
<td>Related bugs, found with a JQL query</td>
<td><code>list_all_jira_search</code></td>
</tr>
<tr>
<td>A new bug, filed without leaving the editor</td>
<td><code>create_a_jira_issue</code></td>
</tr>
<tr>
<td>A note on the issue saying what changed</td>
<td><code>create_a_jira_issue_comment</code></td>
</tr>
<tr>
<td>A log file attached to the issue</td>
<td><code>create_a_jira_issue_attachment</code></td>
</tr>
<tr>
<td>Last night's incident thread</td>
<td><code>list_all_slack_conversation_replies</code></td>
</tr>
<tr>
<td>The last time this error came up</td>
<td><code>list_all_slack_search</code></td>
</tr>
<tr>
<td>A status update in the team channel</td>
<td><code>create_a_slack_chat</code></td>
</tr>
</tbody>
</table>
<p>Two Jira reads make the writes go better. The <code>list_all_jira_search</code> tool takes JQL, Jira's query language, so "my open bugs in this sprint" is one call. The <code>list_all_jira_issue_createmeta</code> tool returns the fields each project requires, so the agent can check them before it calls <code>create_a_jira_issue</code>.</p>
<p>Other reads fill in context, such as <code>list_all_jira_projects</code>, <code>list_all_jira_versions</code> and <code>list_all_jira_labels</code> in Jira, and <code>list_all_slack_conversation_history</code> and <code>list_all_slack_files</code> in Slack.</p>
<p>The remaining writes are edits to issues, comments and messages: <code>update_a_jira_issue_by_id</code>, <code>update_a_jira_issue_comment_by_id</code> and <code>update_a_slack_chat_by_id</code>. There is also <code>slack_conversations_join</code>, which adds the Slack account to a channel. That one deserves a decision of its own, since it widens the set of channels the account belongs to.</p>
<h2 id="which-jira-and-slack-tools-should-you-block-first">Which Jira and Slack tools should you block first?</h2>
<p>The deletes, the webhooks and the admin reads that no engineer needs. Write each as a block rule on the engineer role, and leave everything else open while the pilot runs.</p>
<p>A restriction is a rule about which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. So until you write the first block, restrictions narrow nothing at all. Start with these:</p>
<ul>
<li><code>delete_a_jira_issue_by_id</code>, whose description notes that <code>deleteSubtasks</code> set to true removes the subtasks with the issue. One call can take a parent issue and everything under it.</li>
<li><code>delete_a_jira_issue_comment_by_id</code>, because the comments on a bug are where its history lives.</li>
<li><code>create_a_jira_webhook</code> and <code>delete_a_jira_webhook_by_id</code>. Creating a webhook tells Jira to send events to a URL, which makes it a quiet way to move data out. No task an engineer runs from Cursor needs either one.</li>
<li><code>delete_a_slack_chat_by_id</code>, which deletes a message by channel and timestamp. Slack's <a href="https://docs.slack.dev/reference/methods/chat.delete/">chat.delete reference</a> ties what a call can remove to the token behind it, so its reach depends on who connected Slack.</li>
</ul>
<p>Then weigh the admin reads. In Jira, <code>list_all_jira_audit_logs</code> returns Jira's own audit records and <code>list_all_jira_licenses</code> returns the instance's licensing. In Slack, <code>list_all_slack_team_billing_info</code> returns the billing plan, and <code>list_all_slack_team_access_logs</code> returns each person's IP address, user agent and location. That last one is personal data about colleagues, and no engineering task needs it.</p>
<p>A block rule matches the advertised tool name or the operation Elaichi pinned against the catalog when the rule was saved. An allow rule matches the pinned operation only. Whoever edits a connector's documentation can rename a tool, so a name is a label the governed side controls, and <a href="/blog/block-matches-name-allow-matches-operation/">rules bind the operation instead</a>.</p>
<p>Hold off on allow rules until you mean them. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. A half-drafted allow rule with no tools in it locks the whole engineering team out.</p>
<p>Two layers of rules apply to each engineer at once: the role's rules and the rules aimed at that person. A tool is reachable only when both layers admit it. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Inside each layer, a block always beats an allow. If the engineering manager needs a tool the role blocks, she files an access request and an admin approves it. That lifts only the approved tool for her, and every other role rule keeps applying.</p>
<p>OAuth scopes add a second lock on each engineer's grant. A connected tool whose method is a delete needs <code>mcp:destructive</code> as well as <code>mcp:tools</code>. A tool classified <code>forbidden</code> is reachable under no scope at all. A new block takes about two minutes to reach every engineer's session, so wait that long before you test it.</p>
<h2 id="how-do-you-pin-cursor-to-one-jira-project-and-one-slack-channel">How do you pin Cursor to one Jira project and one Slack channel?</h2>
<p>Freeze the argument that picks the destination. On <code>create_a_jira_issue</code>, freeze the project inside <code>fields</code>. On <code>create_a_slack_chat</code>, freeze <code>channel</code> to the team's channel.</p>
<p>Frozen parameters are values fixed on a toolbox entry, where a toolbox is a saved set of tools and accounts an agent works through. Freezing has two effects. The frozen key is stripped from the schema the model sees, so Cursor is never asked to choose a project or a channel. It can still see a note that the key is frozen, and often the value. At execution the frozen value is merged over the caller's arguments. An agent that sends the key anyway still lands where you pinned it. The order runs entry defaults, then the caller's or model's arguments, then frozen values last.</p>
<p>One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. An engineer who also holds <code>use</code> on the Jira or Slack connection, directly or through a team or organization share, reaches the same tools unfrozen. A block on those tools does not close the gap, because restrictions apply to toolbox entries too and would withhold the frozen entries as well. Leave the connections unshared, and share the toolbox with the engineering team.</p>
<p>The <code>create_a_jira_issue</code> tool's description reads "Requires fields and update parameters". In Jira's <a href="https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post">Create issue</a> API, the target project is one of the entries in <code>fields</code>. Elaichi's frozen parameters work over a tool's flattened argument space, so you can pin the project and leave the summary and description free. An agent working on the payments service then files into the payments project and nowhere else.</p>
<p>The <code>create_a_slack_chat</code> tool "Requires channel". Slack's <a href="https://docs.slack.dev/reference/methods/chat.postMessage/">chat.postMessage reference</a> defines that argument as the channel, private group or direct message to send to. That is the choice you do not want a model making. Freeze it to the team's channel, and the agent cannot post to the company-wide one.</p>
<p>Two neighbors deserve the same care. Freeze <code>channel</code> on <code>update_a_slack_chat_by_id</code> as well. Block <code>slack_conversations_join</code>, or freeze its <code>channel</code>, so the Slack account stays in the rooms you chose. The <a href="/blog/it-team-claude-slack-messaging/">IT team's Slack playbook</a> goes further on pinning a posting channel.</p>
<p>Frozen values and restrictions do different jobs. A restriction decides whether a tool is reachable at all. A frozen value decides where a reachable tool can write.</p>
<h2 id="why-cant-cursor-move-a-jira-issue-to-done">Why can't Cursor move a Jira issue to Done?</h2>
<p>Because the Jira connector's update tool does not perform transitions. The description of <code>update_a_jira_issue_by_id</code> says so directly: "issue transition is not supported here".</p>
<p>That follows Jira's own API. Atlassian's <a href="https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-put">Edit issue</a> reference says a transition is not supported there, and sends callers to a separate <a href="https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post">Transition issue</a> operation. In Jira, moving an issue from To Do to Done is a workflow step, not an edit to a field. A transition can even carry its own screen of fields.</p>
<p>Plan the rollout around it. Status changes stay with people, or with automation you configure inside Jira. The agent can still read the statuses a project uses through <code>list_all_jira_status</code>, and it can comment with what changed through <code>create_a_jira_issue_comment</code>. Tell engineers before the pilot that closing the ticket is still their job.</p>
<h2 id="what-does-cursors-tool-list-show-once-jira-and-slack-are-connected">What does Cursor's tool list show once Jira and Slack are connected?</h2>
<p>Two meta-tools and Elaichi's own operations, but no Jira or Slack tool by name. In Elaichi, connected tools are never listed one by one, however few there are. Cursor looks a Jira or Slack tool up through <code>search_tools</code>, then calls it through <code>execute_tool</code>, which adds no privilege: the call passes every check a direct call would. <a href="/blog/context-window-problem-mcp-tools/">Why connected tools stay out of the list</a> explains the design.</p>
<p>A tool a restriction withholds is left out of the tool list and cannot be called. If Cursor searches for the restricted <code>delete_a_jira_issue_by_id</code>, it sees only the name, flagged as restricted, with no schema.</p>
<p>When an engineer cannot find a tool they expected, check the dull causes first. What an engineer can see is filtered by their role and by the scopes on their grant. A Jira connection that is <code>pending</code> or <code>needs_reauth</code> contributes no tools at all, so it looks absent rather than broken. Search also has <a href="/blog/search-tools-ranking-floor-idf/">a floor that returns nothing rather than the wrong app</a>.</p>
<h2 id="who-changed-that-jira-issue-and-was-it-an-agent">Who changed that Jira issue, and was it an agent?</h2>
<p>Elaichi's append-only audit log holds one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each record shows which Jira or Slack account the call actually reached, and a call from Cursor is recorded under the engineer who signed in, with surface <code>mcp</code> and Cursor named as the OAuth client. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI audit log must capture</a> covers the rest of the record.</p>
<h2 id="what-order-should-a-cursor-rollout-follow">What order should a Cursor rollout follow?</h2>
<p>Accounts and rules first, the editor last. A rollout that starts in Cursor spends its first week granting exceptions, and every exception is a rule written in a hurry.</p>
<ol>
<li>Connect the company's Jira and Slack accounts once in Elaichi, from the <a href="/connectors/">connector catalog</a> of 600+ connectors.</li>
<li>Pin the day-one Jira and Slack tools into a toolbox and share it with the engineering team. Leave the connections themselves unshared, so every engineer's call runs through the toolbox. Nobody reads the secrets back.</li>
<li>Create one engineer role carrying <code>tool:execute</code> and nothing the job does not need. Without <code>tool:execute</code> the tool list is empty, and each member holds exactly one role, so this one has to be complete.</li>
<li>Write block rules on that role for the Jira and Slack deletes, both webhook tools and the admin reads you decided against.</li>
<li>Freeze the project inside <code>fields</code> on <code>create_a_jira_issue</code>, and <code>channel</code> on <code>create_a_slack_chat</code>, in the toolbox entries engineers will use.</li>
<li>Wait about two minutes for the rules to reach every surface.</li>
<li>Have a Cursor team admin add the endpoint as a Team MCP server and list it in the team marketplace. If an Enterprise admin runs Cursor's MCP allowlist, add the endpoint there too. Then have two engineers install it in their own Cursor and sign in.</li>
<li>Ask one pilot agent to delete a throwaway issue in a sandbox project. Search should show the delete tool only as restricted, and an attempt through <code>execute_tool</code> is refused.</li>
<li>After a day, read the pilot's audit entries and adjust the rules.</li>
<li>Invite everyone else with the role preassigned on the invite link. Give the compliance reviewer the Auditor seat, which is free and read-only.</li>
</ol>
<p>Past the pilot, the joining path matters as much as the rules. Elaichi has SAML and OIDC single sign-on (SSO) built in. It also has SCIM v2, the standard for syncing users and groups from a directory. Group-to-role mapping lets a directory group carry the engineer role.</p>
<h2 id="what-happens-to-a-developers-cursor-access-when-they-leave">What happens to a developer's Cursor access when they leave?</h2>
<p>It ends with their membership. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant is checked on every call with no cache, so the next call from their Cursor fails. A SCIM deprovision from your directory suspends the member, which ends access the same way. Removing them is a separate step an admin takes in Elaichi.</p>
<p>Do not plan a departure around a role downgrade. Role and restriction changes pass through a short cache and take about two minutes. That suits tuning rules, not an exit.</p>
<p>The Elaichi address left in their Cursor is harmless on its own. Everyone uses the same address, and the grant was the part that belonged to them.</p>
<p>Removal also runs a preflight that lists every connection the developer owned. A private connection the team's toolbox entries are pinned to blocks the removal. It goes through once an admin transfers that connection to one other active member, never to themselves or to a team, or deletes it. A private connection that nothing beyond the developer depends on cannot be transferred and is deleted with them. A shared connection the team still depends on is deleted only if the admin asks for it; a transfer leaves every grant on the connection as it was. If the developer pinned the team's toolbox entries, those entries stop resolving for every engineer until someone re-pins them, which offboarding flags as a warning. Their Atlassian and Slack accounts are a separate step in those tools. The full sequence, contractors included, is in <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding a member who holds MCP connections</a>.</p>
<h2 id="why-not-use-atlassians-or-slacks-own-mcp-server">Why not use Atlassian's or Slack's own MCP server?</h2>
<p>Both vendors run one, and a team that needs only one of the two apps may be better served by that vendor's server. Atlassian publishes an "Official remote MCP server for Atlassian" that connects Jira, Confluence and more "to Claude, ChatGPT, Cursor, VS Code, and other AI tools using OAuth 2.1 or API tokens". Its README adds that "every action respects the user's existing access controls" (<a href="https://github.com/atlassian/atlassian-mcp-server">Atlassian's repository</a>, read October 2026). Slack's server answers at <code>https://mcp.slack.com/mcp</code>, and Slack says "Workspace admins can approve and manage all MCP client integrations" (<a href="https://docs.slack.dev/ai/slack-mcp-server/">Slack's MCP server docs</a>, read October 2026).</p>
<p>Where they win is plain. Each runs under its own app's permission model, and neither puts a second vendor between Cursor and your data.</p>
<p>What Elaichi adds is the layer across the two apps. Engineers add one address rather than two servers, and the same address serves Claude and ChatGPT. The engineer role's blocks on Jira and Slack deletes are written once, in one place. Frozen parameters on the shared toolbox pin the Jira project and the Slack channel. One audit trail covers both apps, and one removal or suspension in Elaichi ends a developer's access to both on their next call. Neither page describes a rule that covers Jira and Slack together, or a frozen argument, so ask each vendor if you need one.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The Jira connector page lists every Jira tool Elaichi serves, with the setup for Claude, ChatGPT and Cursor.</p><a href="/connectors/jira/" class="cta-button">See the Jira connector</a></aside>
<h2 id="when-does-a-cursor-rollout-not-need-any-of-this">When does a Cursor rollout not need any of this?</h2>
<p>When Cursor only touches local code, or when the whole team is a handful of engineers on their own accounts. A Cursor install that reads local files and writes local code reaches no SaaS account. There is nothing for a control plane to govern and no shared credential to manage.</p>
<p>Size matters too. Take five engineers who all administer one Jira project, with no contractor and no reviewer asking who did what. Personal setups with local MCP servers cost them less. That is a defensible choice, and the controls in this playbook would buy them little.</p>
<p>If your only question is which MCP servers engineers may run, an Enterprise admin's allowlist in Cursor may be the whole answer.</p>
<p>A second Jira site, a contractor or an auditor asking who closed a ticket changes the math. So does a team too big for anyone to know every config. The threshold test in <a href="/blog/when-you-dont-need-an-mcp-gateway/">when you don't need an MCP gateway yet</a> applies to Cursor unchanged.</p>
<p>One limit holds at any size. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. A poisoned Jira comment can still steer a model toward a tool. Restrictions decide whether that tool exists for the engineer.</p>
<p><a href="/blog/what-is-an-mcp-gateway/">The four shapes an MCP gateway takes</a> shows where this approach sits. The <a href="/blog/sales-team-chatgpt-salesforce-accounts/">sales team's Salesforce playbook</a> runs the same order with ChatGPT, and <a href="/use-cases/">use cases</a> lists what each of the twelve teams typically connects.</p>
<h2>FAQ</h2><dl><dt><strong>Does each engineer need their own MCP server URL to use Cursor with Elaichi?</strong></dt><dd>No. Elaichi serves every connected account through one organization-wide endpoint, POST /mcp, behind OAuth. Every engineer adds that same address in their own Cursor and signs in as themselves, and what differs is each engineer's grant and the role they hold. A Cursor team admin can share the address through the team marketplace, and an Enterprise admin can allowlist it, but neither installs it on anyone's machine.</dd><dt><strong>Can Elaichi connect Cursor to GitHub?</strong></dt><dd>No. GitHub is not in Elaichi's connector catalog, so a Cursor rollout through Elaichi covers tools such as Jira and Slack and leaves GitHub out. The route inside Elaichi is a custom connector authored from JSON config. Creating one needs the connector:create permission, which Elaichi flags as high trust because a custom connector can be pointed at any destination. GitHub also appears as a way to sign in to Elaichi itself, which is identity only and gives Cursor no GitHub tools.</dd><dt><strong>Can Cursor move a Jira issue to Done through Elaichi?</strong></dt><dd>No. The Jira connector's update_a_jira_issue_by_id tool states that issue transition is not supported, which matches Jira's REST API, where a transition is a separate operation from editing an issue. An agent can still read a project's statuses and comment on the issue with what changed. Moving the issue through the workflow stays with a person or with automation configured inside Jira.</dd><dt><strong>How do you stop Cursor from posting in the wrong Slack channel?</strong></dt><dd>Freeze the channel argument on the create_a_slack_chat tool in the toolbox entry engineers use. In Elaichi a frozen key is removed from the schema the model is handed, so the model cannot pick a channel. At execution the frozen value is merged over the caller's arguments, so sending the key anyway changes nothing. The freeze holds only for calls through that toolbox, so share the toolbox with engineers and leave the Slack connection unshared. Freeze channel on update_a_slack_chat_by_id as well if message edits should stay in the same place.</dd><dt><strong>How long does a new Jira block rule take to reach engineers in Cursor?</strong></dt><dd>In Elaichi, a restriction or role change takes about two minutes to reach every engineer's session, on the MCP endpoint, in the console and over REST alike, because rules resolve through a short cache and edge distribution. Grant revocation, member removal and member suspension act on the next call. Wait that long before testing a new block from Cursor.</dd><dt><strong>Can Elaichi stop prompt injection reaching Cursor through a Jira ticket?</strong></dt><dd>No. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees the prompt a person typed, so it has nothing to screen. What still applies to every Cursor call is role-based access control per operation, the forbidden tool classification, output redaction, OAuth scope limits and an audit row for each call that reaches execution. A poisoned ticket can persuade a model to try a tool, and governance decides whether that tool is reachable.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>OAuth or API keys for AI agents?</title>
      <link>https://elaichi.ai/blog/oauth-vs-api-keys-for-ai-agents/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/oauth-vs-api-keys-for-ai-agents/</guid>
      <description>Choosing OAuth or API keys for AI agents comes down to revocation: a grant is checked on every call, while a key works until someone rotates it.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> OAuth vs API keys for AI agents is a revocation question before it is an authentication one. API keys and long-lived MCP connection tokens are bearer strings that keep working until somebody rotates them at the issuer, while an OAuth grant is a record the issuer checks. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call, so the next call fails. Long-lived strings remain the honest answer for headless callers with no person present to sign in.</aside>
<h2 id="oauth-or-api-keys-for-ai-agents-what-is-the-difference">OAuth or API keys for AI agents: what is the difference?</h2>
<p>A contractor's last day was Friday. On Monday somebody in IT asks whether their AI access is gone. The answer was settled months earlier, by whoever set up the first assistant. Choosing OAuth or API keys for AI agents is that question in short form. It is about revocation before it is about authentication.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. An assistant that acts in your company's SaaS accounts holds one of two kinds of credential. The kind decides how fast you can stop it.</p>
<p>The first family is the static string: an API key, or a long-lived MCP connection token. Think of it as a password for a program. Whoever has a copy can use it, and the service at the other end cannot tell one holder from another.</p>
<p>The second family is the grant. A grant is a permission slip the service keeps on file, saying that this app may act for this named person within set limits. The service reads the slip when the app calls, so tearing it up is how you stop the app. OAuth is the sign-in flow that writes the slip: the person approves the app once, and the app never learns their password.</p>
<p>That design was the point. The <a href="https://www.rfc-editor.org/rfc/rfc6749">OAuth 2.0 framework, RFC 6749</a>, opens with the problem of third-party apps storing a person's password, often in clear text. It defines an authorization grant as a credential that represents the owner's approval. A static string carries no approval from anyone. Holding it is the approval.</p>
<table>
<thead>
<tr>
<th>What matters</th>
<th>API key or connection token</th>
<th>OAuth grant</th>
</tr>
</thead>
<tbody>
<tr>
<td>What the agent holds</td>
<td>A copy of the secret itself</td>
<td>A token backed by a record the issuer keeps</td>
</tr>
<tr>
<td>Who a call names</td>
<td>Whoever holds the string</td>
<td>One person, acting through one client</td>
</tr>
<tr>
<td>How you take it back</td>
<td>Rotate it at the issuer, then replace every copy</td>
<td>Revoke the record; in Elaichi the next call fails</td>
</tr>
<tr>
<td>What a leaked copy reaches</td>
<td>Everything the string can do, until rotation</td>
<td>What that person's grant allows, until revocation</td>
</tr>
<tr>
<td>Needs a person present</td>
<td>Never</td>
<td>Once, to sign in</td>
</tr>
</tbody>
</table>
<p>Most companies run both families at once and cannot say which is where. Assistants sign in. Scripts carry strings.</p>
<h2 id="how-does-zapier-mcp-issue-each-one">How does Zapier MCP issue each one?</h2>
<p>Zapier MCP documents both families, and the split follows the client rather than anyone's preference. For most MCP clients, the member adds Zapier as a connector and signs in inside the client. Zapier creates the server during that sign-in, one per client. Clients not on Zapier's list, and code you write yourself, use a connection token instead. Zapier describes that token as long-lived and tied to one server, and says it "grants whoever holds it the ability to run the server's tools". Its guidance is to treat the token like a password, never distribute it, and keep one server and token per user rather than sharing. Every client connects to the same endpoint at <code>mcp.zapier.com</code>, so the URL is not itself a credential. Sources: the <a href="https://docs.zapier.com/mcp/get-started/quickstart">Zapier MCP quickstart</a> and <a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>, checked October 2026.</p>
<p>So the precise statement is narrower than the one that gets repeated. Connection tokens are documented for code and for unlisted clients, and most clients sign in. Describing Zapier MCP as token-based across the board reads one page and skips the other.</p>
<p>In a company rollout of Zapier MCP, each member still signs in and runs tool calls as themselves. Admins can restrict members to a Zapier workspace, and app and action restrictions apply through MCP. A History tab shows user-level activity logs for tool calls. What the security page does not say is what happens to a member's server when that member leaves the Zapier account. That is a question to put to Zapier before a rollout, not a gap to assert. Sources: the <a href="https://docs.zapier.com/mcp/manage/rollout/overview">rollout overview</a> and the <a href="https://docs.zapier.com/mcp/manage/security">Zapier MCP security page</a>, checked September 2026.</p>
<p>Whether each member should also get a server of their own is <a href="/blog/zapier-mcp-alternative/">a separate design question</a>.</p>
<h2 id="what-changes-between-revoking-a-grant-and-rotating-a-key">What changes between revoking a grant and rotating a key?</h2>
<p>Revoking a grant is one write at the issuer. Rotating a key or token means finding every string the person could have used, then replacing each copy that legitimate callers still need.</p>
<p>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. A grant here is the OAuth record that lets one client, signed in as one member, call the organization's MCP endpoint. Elaichi reads its <code>revoked_at</code> field fresh from the organization store on every call, with no cache in between. No token has to expire first, and every client that member pointed at the endpoint fails on its next request.</p>
<p>The OAuth standard for revocation names the gap to ask about. <a href="https://www.rfc-editor.org/rfc/rfc7009">RFC 7009</a> defines how a client tells the issuer that a token is no longer needed. Revoking one token can take down the grant behind it as well. The RFC also concedes that in practice there can be a propagation delay, with some servers aware of a revocation and others not. So ask any vendor how its revocation flag is read, and whether anything caches it. A grant cached for an hour behaves like a key for that hour.</p>
<p>Not everything in Elaichi moves at grant speed, and writing otherwise is the usual mistake. Role membership and restrictions sit behind a 60-second cache, and a change also has to reach the edge. A restriction is a rule about which connectors and which individual tools a target may reach. A change to one takes effect within about two minutes, on MCP, the console and REST alike. Cut the person and the next call fails; narrow what the person may reach and the change lands inside that window.</p>
<p>Nothing happens to a static string until somebody rotates it. There is no per-call check to fail, because the string is the check. A key issued in March still works in October unless an operator replaced it.</p>
<p>Rotation is a distribution problem rather than an access-control one. The value sits in an environment file, a CI secret store, a laptop, a vendor's settings screen and often a chat thread. Copies also turn up in shell history and in a config file that was committed once and reverted. None of them reports back, so the issuer cannot count them. Until the last copy is replaced, rotation is an outage waiting for whichever caller you forgot.</p>
<p>That is not a flaw in one product. It is what a bearer credential is, which is why vendors who issue one say to treat it like a password. The price is that removing access becomes an inventory exercise across systems you do not control. The grant shape has a price too, a read on the hot path, and every call pays it for the sake of freshness.</p>
<h2 id="what-does-a-grant-carry-that-a-token-does-not">What does a grant carry that a token does not?</h2>
<p>A grant carries a person and a set of scopes, so the server decides on every call rather than once per string. A key carries whatever rights the issuer packed into it, and no person at all.</p>
<p>Scope is the first difference. Some vendors issue narrow keys per scope. Many issue one key with the account's full rights, so the agent gets more reach than its task needs. OAuth builds the limit in. Under <a href="https://www.rfc-editor.org/rfc/rfc6749">RFC 6749</a>, access tokens represent specific scopes and durations of access, granted by the owner and enforced by the servers.</p>
<p>Attribution is the second difference. A key has no person inside it. The third party's log shows the key, and a stranger holding it looks identical to the person who was meant to.</p>
<p>In Elaichi the grant then meets a ladder of checks. First comes the <code>tool:execute</code> permission, which gates the whole endpoint. Without it the tool list is empty, and any call fails with an error that names the missing permission. The Guest, Auditor and Billing Admin roles do not have it.</p>
<p>Four OAuth scopes sit underneath: <code>mcp:read</code>, <code>mcp:write</code>, <code>mcp:destructive</code> and <code>mcp:tools</code>. A tool classified <code>forbidden</code> is reachable under none of them. The <code>mcp:tools</code> scope does not replace the ladder, so deleting through a connected tool still needs <code>mcp:destructive</code>.</p>
<p>What a grant does not decide is reach. That is a separate layer, set by restrictions, which govern which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. Blocks beat allows. Before writing a first rule, read <a href="/blog/block-matches-name-allow-matches-operation/">why a block matches a tool's name but an allow matches only its operation</a>.</p>
<h2 id="why-does-the-model-never-see-the-connector-secret">Why does the model never see the connector secret?</h2>
<p>Elaichi never hands the connector secret to the model, or to the client. A key given to a model sits in the context window, where it can be echoed into an answer or into a shared transcript.</p>
<p>Connector credentials are not stored in Elaichi at all. Each account's secret lives with a separate credential service, encrypted with AES-256-GCM at rest, and that service owns refresh. When a refresh fails, the connection is marked <code>needs_reauth</code>, so a stale account shows up as stale instead of failing quietly. For the connectors Elaichi authors, no third-party MCP server sits in the path to receive the secret. A native MCP connector's server is the app vendor's own, and Elaichi never forwards its own access token to it.</p>
<p>What the client holds is the grant. Elaichi serves one organization-wide MCP endpoint, <code>POST /mcp</code>, behind OAuth, and Claude, ChatGPT and Cursor all point at the same address. Each member connects once and signs in with a grant of their own. The address carries no secret and is identical for everyone; the grant behind it is what differs. That is the shape the <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a> asks for. It requires the token in an Authorization header on every HTTP request, and it forbids putting a token in the URL's query string.</p>
<p>A connect URL is a one-time session with no token inside it, so it is safe to hand back over MCP. Mistaking a setup link for a credential is a common error.</p>
<p>An organization can bring its own OAuth app per connector. The accepted body is <code>client_id</code>, <code>client_secret</code> and scopes, and nothing shaped like an endpoint can be expressed. Changing it requires <code>connector:manage</code> rather than <code>connection:manage</code>. Somebody allowed to delete a connection therefore cannot also repoint the organization's OAuth app.</p>
<p>One limit belongs in this section, stated plainly. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. An MCP server never sees the user's prompt, so keeping a secret out of the prompt does nothing against injection. What the endpoint does enforce is a permission check per operation, the <code>forbidden</code> class, output redaction, the grant's scopes and a record of every call that reaches execution.</p>
<h2 id="who-gets-a-grant-in-the-first-place">Who gets a grant in the first place?</h2>
<p>A grant is only as trustworthy as the sign-in that produced it. In Elaichi that sign-in can be Google, GitHub or Microsoft, an email code, TOTP MFA with single-use recovery codes, or a passkey.</p>
<p>Enterprise SSO (signing in through the company's identity provider) over SAML and OIDC is built in-house. SCIM v2, the standard an identity provider uses to create and remove accounts, covers users and groups, and groups map to roles. A domain verified by DNS TXT record lets new colleagues auto-join with a configurable default role.</p>
<p>Elaichi's own API tokens get the handling any long-lived secret needs. They are hashed at rest and shown once, so the value on screen is the only copy. The record of each action stores <code>actor_kind</code> as a field rather than an inference, with values including <code>user</code>, <code>api_token</code> and <code>ai_assistant</code>, which marks the Elaichi Agent. Token traffic stays separable from human traffic without anyone guessing from a user agent.</p>
<h2 id="what-happens-when-you-remove-somebody-from-the-organization">What happens when you remove somebody from the organization?</h2>
<p>In Elaichi, access stops on the next call. The reason is structural: removing or suspending a member revokes every live grant in the same transaction as the membership change. The static strings that person created or copied are untouched, and they are the slow half of the job.</p>
<p>The order that works:</p>
<ol>
<li>Suspend or remove the member in Elaichi. The next call from any client they used fails.</li>
<li>If the person stays but their reach was wrong, write a restriction against their role or against them as a user. Allow about two minutes for it to take effect.</li>
<li>Rotate every API key and connection token at its issuer, then replace each copy in environment files, CI stores and vendor screens. No membership change reaches these, and no control plane shortens this step.</li>
<li>Filter the audit trail by actor and time window to see what ran before the cut. Rows are eventually consistent, so the newest can lag by a moment.</li>
</ol>
<p>Elaichi will not complete a removal blindly. A toolbox is a named bundle of tools and the accounts they run against. A preflight refuses a removal while one of the person's private connections is still relied on by a shared toolbox. Transfer that connection to another active member, or delete it. A transfer goes to one member, never to a team or the organization. A private connection that nothing beyond the person depends on cannot be transferred and is deleted with them. Delegated toolbox entries raise a warning that does not block, and re-pinning them is the fix.</p>
<p>Removal also stays tractable at company scale because there is only one address. Every member reaches the same endpoint, so there is no per-user server to find and delete. The grant is the only per-person piece. <a href="/blog/offboarding-when-the-agent-holds-access/">A leaver's offboarding, step by step</a> covers the full sequence when connections are still in use.</p>
<h2 id="what-does-the-audit-trail-show-after-access-is-cut">What does the audit trail show after access is cut?</h2>
<p>Revocation settles what happens next. The record settles what already happened, and the two credential families leave different evidence behind.</p>
<p>A static string identifies itself, not a person. When two scripts share one key, the third party's log credits both calls to that key. Who sat behind each call then becomes a guess from addresses and timing.</p>
<p>A grant names a member, so the trail can name one too. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). A member who has left still shows as "Former member" instead of vanishing, and <a href="/blog/what-an-ai-audit-log-must-capture/">what an agent's audit row should hold</a> has its own post.</p>
<h2 id="when-is-a-long-lived-key-or-token-still-the-right-answer">When is a long-lived key or token still the right answer?</h2>
<p>When there is no browser and no person present to sign in. That covers more callers than people expect.</p>
<p>A nightly sync, a CI step, a script on a server and code written against an endpoint cannot complete an interactive sign-in on a schedule. A grant needs somebody present the first time, and a headless caller has nobody there at 3am. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization">MCP authorization spec</a> makes the same concession for local servers. Its OAuth flow is written for HTTP transports. A server running over STDIO, launched by the client as a local program, is told to take credentials from the environment instead.</p>
<p>The second case is the third party itself. Plenty of vendors issue nothing but keys. When that is all there is, Elaichi's credential service stores the value encrypted. Reading the configuration back returns the public values plus <code>secret_paths</code>: the dot-paths that were encrypted, with none of their values. That list alone decides whether a variable counts as a secret. An edit to an encrypted value through read-back is refused. The refusal reads the same whichever side produced it, so probing teaches a caller nothing.</p>
<p>A prototype belongs here too, and so does a client that is not on any vendor's supported list.</p>
<p>Take the trade knowingly. You gain a caller that runs without a person. You accept secure storage, the narrowest scope the issuer offers, a named owner and a rotation schedule.</p>
<h2 id="how-do-you-check-what-you-have-today">How do you check what you have today?</h2>
<p>Run this before deciding anything. It takes an afternoon, and it usually surprises people.</p>
<ol>
<li>List every MCP client in use: Claude, ChatGPT, Cursor and anything a developer wired up directly.</li>
<li>For each one, note whether it signed in with OAuth or was handed a static string.</li>
<li>For every static string, find the other copies: CI, shell history, shared documents, a teammate's machine.</li>
<li>Pick one person who left last quarter and call their access path. Do not ask whether it was revoked.</li>
<li>Time how long a permission change takes to reach the tool surface, and test that number rather than quoting a vendor page.</li>
</ol>
<p>Step four is the one that changes minds. If a leaver's path still works, the credential was a bearer string and nobody rotated it.</p>
<h2 id="when-do-you-not-need-a-control-plane-for-this">When do you not need a control plane for this?</h2>
<p>When one person uses one assistant against one personal account. Sign in with OAuth inside the client, and revoke the grant in the vendor's own settings page when you are done. There is no organization to answer to and no second account to mix up.</p>
<p>A single developer's key in a local environment file is the same story. The blast radius is one human, and the revocation plan is to rotate the key and tell nobody, because nobody else has it. Adding a control plane to that is work with no return.</p>
<p>The calculation changes at two moments: the first leaver, and the first reviewer who asks to see what an agent did. <a href="/blog/when-you-dont-need-an-mcp-gateway/">The argument for not buying yet</a> sets out where that line sits. If the open question is who should run the server that holds the credential, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the operating cost of self-hosting MCP servers</a> covers it. The <a href="/connectors/">connector catalog</a> lists what each account can be connected as, and the <a href="/security/">security overview</a> covers residency, customer-managed keys and the audit trail.</p>
<h2>FAQ</h2><dl><dt><strong>What is the difference between OAuth and API keys for AI agents?</strong></dt><dd>An OAuth grant is a record the issuer keeps, saying that a named client may act for a named person within set scopes. It can be marked revoked at the issuer, and in Elaichi the agent's next call then fails. An API key is a string whose possession is the authorization. It stays valid until somebody rotates it at the issuer, after which every caller still holding the old value breaks until it is updated. It carries no identity of the person behind the call.</dd><dt><strong>What is the difference between an MCP connection token and an OAuth grant?</strong></dt><dd>A connection token is a long-lived bearer string, in the same family as an API key. Whoever holds a copy can run the tools behind it, so taking it back means rotating it and then updating every caller that still needs it. An OAuth grant is a record on the server, tied to one member and one client. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the revocation field is re-read on every call, so access ends with the next request.</dd><dt><strong>How quickly does revoking an AI agent's access take effect in Elaichi?</strong></dt><dd>Grant revocation, member removal and member suspension are effective on the next call, because Elaichi re-reads the revocation field from the organization store on every call with no cache. Role membership and restriction changes work differently. They sit behind a 60-second cache and also have to reach the edge, so they take effect within about two minutes across MCP, the console and REST.</dd><dt><strong>When should an AI agent still use a long-lived API key or token?</strong></dt><dd>When there is no browser and no person present to complete a sign-in. Nightly jobs, CI steps and code written against an endpoint cannot produce an interactive OAuth consent on a schedule, and the MCP specification itself tells local STDIO servers to take credentials from the environment. A key is also the only option when the third party issues nothing else. Give it the narrowest scope the issuer offers, plus a named owner responsible for rotating it.</dd><dt><strong>Does Zapier MCP require a connection token?</strong></dt><dd>Not for most clients. Zapier documents that for most MCP clients the member adds Zapier as a connector and signs in inside the client, and Zapier creates the server during that sign-in. Connection tokens are documented for clients not on Zapier's list and for code you write yourself. Zapier describes those tokens as long-lived and tied to one server, and says to treat one like a password (docs.zapier.com, checked October 2026).</dd><dt><strong>Is an MCP server URL or a connect URL a credential?</strong></dt><dd>A bare server address is not, but a URL with a token embedded in it is. The MCP authorization specification forbids putting access tokens in a URL's query string and requires them in a header on every request. Zapier says its mcp.zapier.com endpoint is not a credential; the connection token is. In Elaichi the address is one organization-wide endpoint behind OAuth, and a connect URL is a one-time session that carries no token. Guard the token or grant behind an address, not the address itself.</dd></dl>]]></content:encoded>
      <dc:creator>Roopendra Talekar</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>how-mcp-works</category>
    </item>
    <item>
      <title>Offboarding AI access, contractors included</title>
      <link>https://elaichi.ai/blog/offboarding-when-the-agent-holds-access/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/offboarding-when-the-agent-holds-access/</guid>
      <description>Offboarding AI access in Elaichi takes effect on the next call. Here is what the removal preflight checks, and the order that works.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> When you offboard a member with MCP connections in Elaichi, their AI client stops working on the next call, because removing or suspending a member revokes every live grant in the same transaction as the membership change. Contractors are handled exactly like employees. The removal runs a preflight that lists every connection the member owns, and only a private one pinned by a shared toolbox entry can hold it up, so transfer that connection to an active member who is staying or delete it. Role and restriction changes are the slow path and take effect within about two minutes.</aside>
<h2 id="what-does-offboarding-ai-access-cut-off-on-the-next-call">What does offboarding AI access cut off on the next call?</h2>
<p>Offboarding AI access in Elaichi takes effect on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The grant's <code>revoked_at</code> value is read again from the organization store on every single call, with no cache in front of it. Nothing has to expire first, so the next tool call from that person's Claude, ChatGPT or Cursor session fails.</p>
<p>Two terms, defined once. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A grant is the OAuth record that lets one member's AI client call the organization's MCP endpoint, the single web address every client connects to. OAuth is the sign-in flow that issues that record instead of handing out a shared password.</p>
<p>It does not matter how many clients the person signed in from. Every live grant goes in the same transaction, so a Claude desktop session and a Cursor install both stop together. Suspension is the same cut. It revokes the grants exactly as removal does, and suspended members drop out of the billable seat count. That makes suspension the first move whenever the rest of the offboarding is not ready.</p>
<p>Two parts of offboarding work differently. Narrowing what someone can reach, rather than removing them, takes effect within about two minutes. And the removal itself can be refused while other members still depend on the departing member's accounts.</p>
<h2 id="how-does-contractor-offboarding-work-when-an-ai-client-holds-access">How does contractor offboarding work when an AI client holds access?</h2>
<p>A contractor is a member with an end date, and the same cut applies to them. Contractor offboarding for AI access is still its own step, separate from closing the HR ticket.</p>
<p>A contractor finishes on a Friday. HR closes the ticket, someone disables the laptop login, and the assumption is that the story ends there. Suppose the contractor pointed <a href="https://claude.ai">Claude</a>, <a href="https://chatgpt.com">ChatGPT</a> or <a href="https://cursor.com">Cursor</a> at your organization's MCP endpoint. The question is no longer whether their single sign-on (SSO) account is off. It is whether the next tool call from that client gets data back.</p>
<p>That call does not come from a machine you control. It comes from a desktop client holding a bearer token, the standard OAuth 2.0 credential defined in <a href="https://www.rfc-editor.org/rfc/rfc6750">RFC 6750</a>, which works for whoever holds it. The token is tied to a grant, issued when the contractor signed in, and checked on every call to <code>POST /mcp</code>. The client holds no credential for any of your SaaS accounts, and the endpoint address carries nothing personal to them.</p>
<p>Three terms decide what you do next, and they are not interchangeable:</p>
<ul>
<li><strong>Grant.</strong> Whether this person may call the endpoint at all. It exists or it does not.</li>
<li><strong>Role.</strong> The bundle of permissions the person inherits, such as Member, Guest or Auditor. Each member holds exactly one.</li>
<li><strong>Restriction.</strong> A rule on a role or on one person that takes away a connector or a single tool.</li>
</ul>
<p>What makes contractors different is the calendar, not the mechanism. The end date is known in advance, so the ownership questions can be settled while the person is still around to answer them. Some contractors come back part-time the next quarter, which makes narrowing a role tempting when removal is the right call. And a contractor may hold an API key directly from a vendor, which no change in Elaichi reaches.</p>
<h2 id="which-offboarding-changes-take-effect-on-the-next-call">Which offboarding changes take effect on the next call?</h2>
<p>Grant revocation, member removal and suspension do. Role changes and restriction changes take effect within about two minutes. That difference decides what you do at 5pm on the last day.</p>
<p>The fast side is fast because of where the flag lives. Elaichi keeps the revocation flag in the organization store and reads it live on every call, so there is nothing to wait out. The slow side is a cache. Role membership and restrictions resolve through a 60-second cache plus edge propagation, on the MCP endpoint, the console and the REST API alike. Moving a contractor from Member to Guest is correct, and Guest lacks the <code>tool:execute</code> permission, so the move does end tool access. It just ends it within about two minutes.</p>
<table>
<thead>
<tr>
<th>Action</th>
<th>Takes effect</th>
<th>Why</th>
<th>Use it when</th>
</tr>
</thead>
<tbody>
<tr>
<td>Suspend a member</td>
<td>Next call</td>
<td>The revocation flag is read live, with no cache</td>
<td>The ownership decisions are not settled yet</td>
</tr>
<tr>
<td>Remove a member</td>
<td>Next call, once the preflight passes</td>
<td>Same live read as suspension</td>
<td>The person is leaving and nothing of theirs is pinned</td>
</tr>
<tr>
<td>Revoke one grant</td>
<td>Next call</td>
<td>Same live read</td>
<td>One client sign-in has to end while the membership stays</td>
</tr>
<tr>
<td>Change a role</td>
<td>Within about two minutes</td>
<td>60-second cache plus edge propagation</td>
<td>Scope is shrinking and the person is staying</td>
</tr>
<tr>
<td>Add a restriction</td>
<td>Within about two minutes</td>
<td>Same cached path as roles</td>
<td>One connector or tool has to go for a role or a person</td>
</tr>
</tbody>
</table>
<p>The operational rule follows. If access has to stop today, suspend or remove the member. Do not narrow the role and walk away from the screen. Narrowing is right when a contractor's scope shrinks and they stay, and wrong when they leave in ten minutes.</p>
<p>If you do narrow with a restriction, two details catch people out. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. And the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. The cases are worked through in <a href="/blog/per-tool-vs-per-app-restrictions/">per-tool versus per-connector restrictions</a>.</p>
<h2 id="why-does-one-endpoint-remove-half-the-problem">Why does one endpoint remove half the problem?</h2>
<p>Elaichi serves every connected account through one organization-wide MCP endpoint at <code>POST /mcp</code>, so there is no per-person address to track down on somebody's last day. The address carries no token and is the same for every member and every set of tools. Nobody creates, lists or deletes an MCP server per member. The address stays fixed, and the grant is the part that differs between people.</p>
<p>That holds across the 600+ connectors in the Elaichi catalog. Claude, ChatGPT, Cursor and any other MCP client all point at the same address and sign in. Offboarding comes down to one person's grants, not a search through client config files for addresses. A setup with one server per team or per person turns each of those servers into a separate item on the last-day checklist.</p>
<p>The other half of the problem is the accounts other people depend on, which is the job of the offboarding preflight.</p>
<h2 id="why-can-offboarding-a-member-be-refused">Why can offboarding a member be refused?</h2>
<p>Offboarding a member with MCP connections is refused while one of that member's private connections is pinned into a toolbox entry other people use. The refusal names the entries that block it. You resolve each one, and the removal completes.</p>
<p>In Elaichi, a toolbox is a named set of tool entries shared with other members, and each entry points at one specific connected account. The situation behind a refusal is ordinary. A finance analyst leaves on Friday. Their personal QuickBooks account is pinned into two toolbox entries, and three people in finance call those entries every day. Remove the analyst without a decision about that account and one of two bad things happens. Either the entries stop working in the middle of a month-end close, or a departed person's credential keeps serving tool calls with nobody accountable for it.</p>
<p>The offboarding preflight lists every connection the departing member owns, private and shared alike, and sorts what they leave behind into three groups:</p>
<ol>
<li><strong>Private connections no toolbox entry references.</strong> These are cleaned up along with the membership, with no decision needed from you.</li>
<li><strong>Private connections a toolbox entry references.</strong> These block the removal until each one is transferred to another active member or deleted. A shared connection never blocks the removal, and is deleted only if you explicitly ask for it.</li>
<li><strong>Delegated toolbox entries.</strong> These raise a warning that does not block. Each needs a new pin, and re-pinning is a fix rather than a decision about a credential.</li>
</ol>
<p>The console shows the blocking list and the warnings on the same screen, and they mean different things. One stops the removal until you resolve it. The other is a to-do you can clear after the person has gone. Reading them as one list is how a shared entry ends up pinned to nothing.</p>
<p>The preflight deliberately does not choose for you, because both defaults are wrong. Deleting everything takes a working shared entry away from a support shift, and the first person to notice is a rep whose tool call fails in front of a customer. Keeping everything leaves an unowned credential in the path of an AI client. Naming the blocking entries and stopping is the only behavior that makes no credential decision on your behalf.</p>
<p>Plan for this step to take longer than one click. The time depends on how many connections the person built up, not on a fixed number. It is also the step that gets skipped when someone tries to offboard from a phone between meetings.</p>
<h2 id="how-do-you-resolve-a-connection-the-preflight-flags">How do you resolve a connection the preflight flags?</h2>
<p>Transfer it to another active member who is staying, or delete it. Each choice carries a different trade-off, and neither option hands the connection to the organization, to a team, or to the admin running the removal.</p>
<p><strong>Transfer to another active member.</strong> Right for a shared login that was only personal by accident, such as a billing portal or a vendor account, and for an account a team still depends on. A transfer sets a new owner and leaves every grant on the connection exactly as it was, but every toolbox entry the departing owner pinned to it stops resolving, for everyone including the new owner, so someone who is staying has to re-pin them. Pick the person on that team who will actually use the account.</p>
<p><strong>Who the successor cannot be.</strong> Not the organization, not a team, and not you if you are the admin running the removal. Access to the connection still comes only from explicit view, use or edit shares. No organization-level permission widens who can see the account in Elaichi, not even for owners and admins.</p>
<p><strong>Check the credential before you transfer.</strong> If your offboarding also disables the departing person's user inside the third-party app, the stored credential will stop refreshing. A failed refresh marks the connection <code>needs_reauth</code> instead of failing silently. The connection then offers no tools until the new owner reconnects with their own login.</p>
<p><strong>Delete it.</strong> Correct when the account really was personal to the person leaving. Re-pin the affected toolbox entries to an account whose owner is staying, often a shared company login connected by someone on the team and shared with it.</p>
<p><strong>A private connection is the one that holds things up.</strong> Only a private connection can block the removal, and a private one pinned by a toolbox its owner shared waits for your decision. Transfer it to someone who is staying, or delete it and re-pin the affected entries to an account the new owner signs in to as themselves. Deciding rather than defaulting is more work, and it is the right amount of work. The alternative is an organization that quietly inherits logins nobody chose to inherit, which is what a reviewer asks about six months later.</p>
<p><strong>Delegated entries.</strong> Re-pin each entry the warning names to the accounts you chose for the transfers. None of them holds up the removal.</p>
<p>No option hands anyone the secret. Reading back an account's configuration in Elaichi returns its public values plus <code>secret_paths</code>, the list of dot-paths that were encrypted, with none of their values. Editing one is refused. Nobody moves a token by hand during offboarding, because nobody can read one.</p>
<h2 id="in-what-order-should-you-offboard-someone-on-their-last-day">In what order should you offboard someone on their last day?</h2>
<p>Suspend first, work the preflight, complete the removal, then clean up outside Elaichi. The same order serves an employee and a contractor.</p>
<ol>
<li><strong>Suspend first if anything is unsettled.</strong> In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. You get the cutoff on the day, and the ownership decisions can wait for a calmer hour.</li>
<li><strong>Open the removal and read the preflight.</strong> It lists every connection the member owns, private and shared alike. Only a private one pinned by a toolbox entry blocks the removal.</li>
<li><strong>Decide a new owner per connection, not per person.</strong> Every transfer goes to one active member who is staying, so pick the person who will use the account. For a contractor, that is often whoever takes over the work.</li>
<li><strong>Resolve the private connections and re-pin.</strong> Transfer each to a member who is staying, or delete it and point the affected entries at a different account.</li>
<li><strong>Clear the delegated-entry warnings.</strong> Re-pin those entries to the accounts you settled in step 3.</li>
<li><strong>Complete the removal.</strong> Personal connections that nothing references are cleaned up with the membership.</li>
<li><strong>Revoke at the source.</strong> Elaichi stops the endpoint reaching an account. It does not deprovision the person's Salesforce or Zendesk user, and it cannot touch an API key they kept in their own password manager. Close those in each vendor's admin console.</li>
<li><strong>Read the audit log the next morning.</strong> Filter the last two weeks by that actor. You are looking for tool calls nobody expected, not for a clean bill of health.</li>
</ol>
<p>If the plan is to narrow rather than remove, say for a contractor returning part-time next quarter, change the role and allow about two minutes. Then check the console instead of assuming the change is live.</p>
<p>If your identity provider drives Elaichi membership over SCIM v2 (System for Cross-domain Identity Management), which provisions users and groups automatically, make the ownership decisions before the deprovision event. A SCIM deprovision suspends the member, which ends their access on the next call, but it does not remove them, so the preflight still waits for you. The connection questions are easier to answer while the person is still reachable on Slack. SCIM keeps the directory right, and <a href="/blog/identity-provider-scim-vs-mcp-grants/">what SCIM does not carry</a> is a subject of its own.</p>
<p>A standing habit helps more than any runbook. Pin shared toolbox entries to accounts owned by someone who is likely to stay, and most departures then have nothing to resolve.</p>
<h2 id="how-do-you-check-what-their-assistant-did-before-they-left">How do you check what their assistant did before they left?</h2>
<p>Read the Elaichi audit log the morning after, filtered to that person. Removal does not scrub anyone's history. The log is append-only, and a departed member shows as "Former member" instead of vanishing from the records, which matters when the review happens three months after a contract ended.</p>
<p>Every tool call their client made that reached execution is on record, along with which account it reached. That answers the question you will actually be asked, which is not whether they were removed but what their assistant touched. What a single row holds is set out in <a href="/blog/what-an-ai-audit-log-must-capture/">what an AI audit log must capture</a>.</p>
<p>Two practical notes. The <code>actor_kind</code> field is recorded at the point of action, and a call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. So separating what a person's assistant did from what they did in a browser is a read of the entry rather than forensics. The value <code>ai_assistant</code> marks only the Elaichi Agent. The trail is also eventually consistent, so a call from 11pm may take a moment to show up in an 8am review. Check again before concluding that nothing happened.</p>
<p>If a compliance reviewer runs the review rather than an operator, give them an Auditor seat. It is read-only and free, and it lacks <code>tool:execute</code>, so the endpoint advertises no tools to them at all. They see the log, not the tools.</p>
<p>One limit applies to the record itself. Deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name. Deletion does not purge the audit history. Each record ages out under the log server's 90-day retention, counted from when it was written. If your retention policy needs one person's records gone entirely, raise it on <a href="/contact/">/contact/</a> before you write the policy.</p>
<h2 id="what-does-revocation-not-reach">What does revocation not reach?</h2>
<p>Revocation stops future calls. It does not pull back data that already left, and it does not touch credentials or logins that live outside Elaichi. Say so plainly to whoever signs off on the offboarding.</p>
<p><strong>Data the person copied out.</strong> Suppose a contractor read a customer list through a governed tool call in week three and pasted it into a personal assistant account. The audit log records the read and nothing about the paste. No access-control layer, MCP-based or otherwise, can see what happens to data after it lands in a model's context window. That is the shadow AI part of the problem, meaning AI tools staff use without IT's knowledge, and no offboarding step reverses it.</p>
<p>The control you do have sits upstream of the paste. It is a record of what was reachable and when, plus restrictions that keep the reachable set small. A tool a restriction withholds is left off the tool list and cannot be called. Search names it only as restricted, with no schema. That is a different guarantee from telling the model not to use it.</p>
<p><strong>Credentials held outside Elaichi.</strong> Connector credentials never live in Elaichi. A separate credential service holds per-account secrets, encrypted at rest, and owns token refresh. Removing a membership does not log anybody out of QuickBooks. It stops the organization's endpoint reaching that account on the departing member's behalf. The person's own user inside the app stays active until you close it there. An API key they copied into a password manager keeps working until the vendor revokes it. Every OAuth-based connection shares this limit, whichever product sits in front of it.</p>
<p><strong>A shared login.</strong> If the contractor used a vendor login that three other people also use, removing them from Elaichi changes nothing at the vendor. They still know the password. The fix is a per-person account at the vendor, and it comes first. No control at the MCP layer replaces an identity that does not map one to one to a person.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>For a security review, the security page covers how credentials are held, how access is shared, and how each action is attributed to a person.</p><a href="/security/" class="cta-button">Read the security overview</a></aside>
<h2 id="when-does-none-of-this-apply-to-you">When does none of this apply to you?</h2>
<p>If nobody shares a connection, none of the refusals will ever fire. One person connected two apps to their own AI client, and no toolbox entry points at anyone else's account. Offboarding is then removing the membership and revoking access inside each SaaS app by hand.</p>
<p>The same is true when a contractor logged in to one SaaS app with their own account and never connected an AI client at all. Offboarding is that vendor's admin console plus your identity provider. Standard SCIM deprovisioning, defined in <a href="https://www.rfc-editor.org/rfc/rfc7644">RFC 7644</a>, already covers that case, and nothing here improves on it. At that size a control plane solves a problem you do not have yet, and the case for <a href="/blog/when-you-dont-need-an-mcp-gateway/">holding off on an MCP gateway</a> sets it out in full.</p>
<p>The case for one governed endpoint starts when the contractors are plural, the connected accounts are plural, and nobody can say which app an assistant reached last Tuesday. For how roles, restrictions and seat classes fit together before anyone leaves, see the <a href="/product/">product overview</a>, and the <a href="/security/">security page</a> covers SSO, SCIM and residency. To see what a team's accounts look like once they are shared properly, browse the <a href="/connectors/">connector catalog</a> or the <a href="/use-cases/">per-team setups</a>. More on the wider subject sits under <a href="/blog/category/governance/">governance</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Does removing a member cut off their AI access straight away?</strong></dt><dd>Yes, on the next call. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The revocation flag is read from the organization store on every call with no cache, so the member's next tool call from Claude, ChatGPT, Cursor or any other MCP client fails. Narrowing a role or adding a restriction is different and takes effect within about two minutes.</dd><dt><strong>How do you cut off a contractor's AI access on their last day?</strong></dt><dd>Suspend or remove the contractor, exactly as you would an employee. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so the next call from their AI client is refused. Suspend first if shared accounts still need a new owner, since the removal waits for those decisions. Then revoke anything the contractor authorized personally, such as an API key, in the vendor's own admin console.</dd><dt><strong>Why does Elaichi refuse to remove a member?</strong></dt><dd>Elaichi refuses a member removal while one of that member's private connections is referenced by a toolbox entry, meaning a shared set of tool entries pinned to specific connected accounts. The refusal names the blocking entries. Transfer each referenced connection to another active member, or delete it, and the removal then completes. Personal connections that no toolbox entry references are cleaned up with the membership.</dd><dt><strong>Can a private connection be transferred to another member during offboarding?</strong></dt><dd>Yes, when a shared toolbox still relies on it. Offboarding transfers that private connection to another active member, which sets a new owner and leaves every grant on the connection as it was. It never hands the connection to the organization, to a team, or to the admin running the removal. A private connection that nothing beyond the person depends on cannot be transferred this way and is deleted with them. Delete a blocking one instead when the account really was personal to the person leaving, then re-pin any affected toolbox entries to an account the new owner signs in to as themselves.</dd><dt><strong>Does removing a member delete their activity from the audit log?</strong></dt><dd>No. The Elaichi audit log is append-only, so a removed member's tool calls stay on record, and the person appears as "Former member" rather than dropping out of the trail. Deleting an organization deletes its connector credentials but leaves three stores: the audit history, analytics events, and the credential service's organization, environment and installed-connector configuration rows. Elaichi reports that residue by name.</dd></dl>]]></content:encoded>
      <dc:creator>Nachi Raman</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>governance</category>
    </item>
    <item>
      <title>Which Notion workspace did ChatGPT write to?</title>
      <link>https://elaichi.ai/blog/product-team-chatgpt-notion-workspace/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/product-team-chatgpt-notion-workspace/</guid>
      <description>Elaichi&apos;s audit trail names the Notion workspace each ChatGPT call reached. Pin the connection or database first, and the other workspace is out of reach.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> In Elaichi, the audit trail answers which Notion workspace ChatGPT wrote to: each entry records the account the call actually reached, as the execution saw it rather than as the model intended. To stop a wrong-workspace write before it happens, share the product team a toolbox pinned to one workspace, with the parent database frozen where one fits, rather than the connections themselves. Page and block deletes sit behind a block rule on the product role.</aside>
<h2 id="which-notion-workspace-did-chatgpt-write-to">Which Notion workspace did ChatGPT write to?</h2>
<p>The audit trail tells you. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each records the Notion workspace the call actually reached, which comes from the execution itself, not from what the model meant to do. To stop the wrong-workspace write before it happens, share the team a toolbox pinned to one workspace, with the database frozen where one fits. The model is then never offered the other.</p>
<p>Product teams end up here easily. One workspace is the company wiki. The second arrived with an acquisition, an agency or a team that moved before IT had an opinion, and both contain a page called Roadmap. When ChatGPT edits "the roadmap", the first question after an unexpected change is which of the two it touched, and a timestamp is not an answer.</p>
<p>To answer it, filter the trail by the person, or by free text on the workspace's connection label, and read the account on each write. <a href="/blog/what-an-ai-audit-log-must-capture/">What an AI agent audit log must capture</a> covers the rest of each entry.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves Notion from its 600+ catalog through one organization-wide endpoint. <a href="/connectors/notion/">Notion's connector page</a> lists its tools, and the <a href="/connectors/category/knowledge-management/">knowledge management connectors</a> sit beside it.</p>
<h2 id="how-does-the-model-choose-between-two-notion-workspaces">How does the model choose between two Notion workspaces?</h2>
<p>From labels, unless you take the choice away. When both workspace connections are shared with a product manager, each Notion tool that can reach both takes a required <code>connection</code> argument. Its values are the account labels in the tool's schema, and the model fills it in on every call.</p>
<p>Label the connections so a person can tell them apart. "Notion Core Wiki" and "Notion Atlas" beat "Notion" and "Notion 2". Account labels stay scorable in Elaichi's tool search on purpose, so a distinct label helps the model and whoever reads the trail later. A value that names no real account returns an error listing the real ones, not a write somewhere else.</p>
<p>Through Elaichi, connected tools are never listed one by one, however few there are, so ChatGPT reaches a Notion tool by searching for it. <a href="/blog/search-tools-ranking-floor-idf/">How search picks one tool from hundreds</a> covers the ranking. Labels make the model's guess better, but they do not take the guess away.</p>
<h2 id="how-do-you-stop-a-write-landing-in-the-wrong-notion-workspace">How do you stop a write landing in the wrong Notion workspace?</h2>
<p>Share the team a toolbox pinned to one workspace, not the connections themselves. A toolbox is a curated set of tools shared with a team. The person who connected the workspaces leaves both connections unshared. They pin the core wiki into a toolbox entry for each tool the team writes with. If the team still reads the acquired workspace, its read tools get entries pinned to that one. Then they share the toolbox with the product team at <code>use</code>. From there, the team runs Notion only through those entries and cannot open or reshare the connections behind them.</p>
<p>Where it fits, pin the database too. The page-create tool, <code>create_a_notion_page</code>, makes a page "as a child of an existing page or database". Freeze the parent database's ID on that entry, and the model files a spec in the specs database and nowhere else. A frozen key is removed from the schema the model is offered. A frozen value is merged over the caller's arguments at execution, so passing the key anyway changes nothing. <a href="/blog/frozen-parameters-wire-transfer-receiver/">Locking a tool argument</a> shows the same mechanism on a payment tool.</p>
<p>One condition: a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. Anyone who also holds <code>use</code> on a workspace's connection, directly or through a team share, reaches its tools without the pins. Do not try to close that path with a block rule, because a block withholds the tool everywhere, the pinned entry included. Close it by not sharing the connection.</p>
<p>One side door stays open after the pin. The move tool, <code>create_a_notion_page_move</code>, moves a page "to a different parent location". Leave it out of the toolbox, or block it on the product role, if filed pages must stay where they were filed.</p>
<h2 id="which-notion-deletes-should-the-product-team-lose">Which Notion deletes should the product team lose?</h2>
<p>Page and block deletes, plus the trash flag that does the same job. Block <code>delete_a_notion_page_by_id</code> and <code>delete_a_notion_block_child_by_id</code> on the product role. Notion's <a href="https://developers.notion.com/reference/delete-a-block">delete-a-block reference</a> says a delete sets the block to <code>in_trash: true</code> and moves it to the Trash, "where it can still be accessed and restored". So a delete can be undone, but only by someone who notices it in the right workspace.</p>
<p>Updates can trash content too. The page-update tool, <code>update_a_notion_page_by_id</code>, changes a page's "properties, icon, cover, or trash status", so a block on the delete tools leaves that path open. Either block it as well, or freeze its trash argument to <code>false</code> on the toolbox entry. Notion's API calls that field <code>in_trash</code> in <a href="https://developers.notion.com/reference/patch-page">the update-page reference</a>, and you should copy the exact path from the tool's schema in Elaichi before you freeze it. Frozen to <code>false</code> on the entry, it means an edit made through that entry can never double as a delete.</p>
<p>The catalog has no tool named for deleting a database. Notion trashes one through an update instead: its update-database body takes <code>in_trash</code>, "Whether the database should be moved to or from the trash" (<a href="https://developers.notion.com/reference/update-a-database">update a database</a>). The catalog describes <code>update_a_notion_database_by_id</code> as changing a database's title, description or schema, so check its schema in Elaichi for that field. If it is there and a database must survive, block the tool too, and make schema changes in Notion itself.</p>
<p>Put these blocks on the role the product team holds. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A newly connected workspace is fully reachable until a rule exists. Write the rules as blocks, not as an allowlist. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. <a href="/blog/block-matches-name-allow-matches-operation/">Why blocks and allows match differently</a> explains that rule, and why a block also catches a renamed tool.</p>
<h2 id="how-do-you-set-up-both-workspaces-for-chatgpt">How do you set up both workspaces for ChatGPT?</h2>
<p>Connect each workspace once, share the team a toolbox rather than the connections, and give every member one role. Sharing grants <code>view</code>, <code>use</code> or <code>edit</code> on one resource, a toolbox included, and the grantee can be a person, a team or everyone in the organization. A member's view holds what they own plus what was explicitly shared with them. No organization-level permission widens that list quietly, owners and admins included.</p>
<p>Exactly one role per member is enforced, so a role is a whole persona rather than a bolt-on. The <code>tool:execute</code> permission gates the endpoint ahead of every other check, and Guest, Billing Admin and Auditor do not have it. Sign-in can run on your identity provider: Elaichi has SAML and OIDC SSO built in-house, plus SCIM v2 with group-to-role mapping. A product manager added to the Product group arrives with the role that group maps to.</p>
<p>In ChatGPT, writes need Business, Enterprise or Edu. OpenAI says full MCP support, "including modify/write actions, is rolling out in beta" to those plans (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI help center</a>, checked October 2026). There, an admin creates the app and publishes it. Pro users connect "with read/fetch permissions in developer mode", so a product manager on Pro can read the roadmap but cannot file a spec. <a href="/blog/connect-elaichi-to-chatgpt/">Connecting Elaichi to ChatGPT</a> has the steps.</p>
<h2 id="why-not-use-notions-own-mcp-server">Why not use Notion's own MCP server?</h2>
<p>For a team on one workspace that needs only Notion in ChatGPT, Notion's own server is the simpler choice. Notion describes it as "a remote MCP server hosted by Notion". After OAuth, the client can "read and update content that you can access" (<a href="https://developers.notion.com/docs/mcp">Notion's developer docs</a>, checked October 2026). Notion's own permissions decide what each person reaches, and there is no second vendor. Workspace owners "can manage MCP client access" from Notion's Settings, under Connections, and organization owners can "list and revoke members' connections".</p>
<p>Elaichi adds what spans more than Notion:</p>
<ul>
<li><strong>One address.</strong> ChatGPT, Claude and Cursor reach Notion and every other connected app through the same organization endpoint.</li>
<li><strong>One rule set per role.</strong> The product role's delete blocks sit beside its rules for every other app, written once.</li>
<li><strong>Pinned entries.</strong> A shared toolbox entry pinned to one workspace, with the database frozen, offers the model nothing else, and the model cannot override the pin.</li>
<li><strong>One audit trail.</strong> Every app's calls land in one record, each entry naming the account it reached.</li>
<li><strong>One place to cut access.</strong> In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Removing a product manager stops their calls through Elaichi to every connected app, starting with the next one. Notion still holds their account, which you close in Notion or your identity provider.</li>
</ul>
<p>Notion's page does not describe pinning a write to one database or a trail that spans other apps, and it has no reason to: its job is Notion.</p>
<h2 id="what-happens-when-the-pm-who-connected-a-workspace-leaves">What happens when the PM who connected a workspace leaves?</h2>
<p>Their access ends with their membership, and the team's toolbox needs someone new to vouch for it. Each toolbox entry records who pinned it, and that is re-checked on every call. If that person loses <code>use</code> on the connection, is removed, or is suspended through SCIM, their entries stop resolving for every grantee until someone still present re-pins them. Offboarding lists those entries as a warning that does not block the removal.</p>
<p>Removing the PM also runs a preflight. It lists every connection they own, private and shared alike. A shared connection the team still depends on can go to another active member, which leaves every grant on it as it was. It is deleted only if the admin asks for that. Nothing transfers to the organization, to a team, or to the admin running the removal. A private connection that nothing beyond the PM depends on cannot be transferred and is deleted with them. A private connection that a shared toolbox depends on blocks the removal until an admin transfers it to a member. Wherever the connection lands, keep sharing the toolbox rather than the connection, so the pins still hold.</p>
<p>A SCIM deprovision suspends the member and never removes them. SCIM's <code>active</code> attribute carries a meaning that "is determined by the service provider" (<a href="https://www.rfc-editor.org/rfc/rfc7643">RFC 7643</a>). Whether the identity provider sends <code>active: false</code> or a delete, Elaichi sets the member to suspended. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The PM's next call through Elaichi is refused. Removal, with its preflight, stays a separate step an admin takes in Elaichi, and the PM's Notion account is another.</p>
<p>Revoking a share or disconnecting an account also lands on the next call. A role or restriction change is the slow one: it takes about two minutes. <a href="/blog/offboarding-when-the-agent-holds-access/">How offboarding lands for an AI client</a> explains the two speeds.</p>
<h2 id="what-does-this-cost-a-product-team">What does this cost a product team?</h2>
<p>Elaichi has two plans, Gold and Black, and every workspace starts with a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. <a href="/pricing/">Pricing</a> shows the current price for your region. Billable seats are active memberships, minimum one. Suspended members do not count, and neither do the free-seat roles: Guest, Billing Admin and Auditor. That matters here, because a compliance reviewer can watch the Notion trail on an Auditor seat without costing a license. If a trial ends without checkout, the workspace pauses: plan-gated features lock, nothing is deleted, and subscribing picks up where it left off.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The Notion connector page lists every Notion tool Elaichi serves, with the setup for Claude, ChatGPT and Cursor.</p><a href="/connectors/notion/" class="cta-button">See the Notion connector</a></aside>
<h2 id="when-does-a-product-team-not-need-this-yet">When does a product team not need this yet?</h2>
<p>When there is one Notion workspace, a few people, and an agent that only reads. A control plane is overhead there, and Notion's own server covers it. Revisit when a second workspace appears, or when someone asks which account an agent wrote to and nobody can say. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When an MCP gateway is premature</a> lays out that decision.</p>
<p>One limit applies either way. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What holds instead is configuration the model cannot change: a hostile instruction inside a Notion page still cannot reach a restricted delete or the other workspace.</p>
<p>For the same rollout on a CRM instead of a wiki, see <a href="/blog/sales-team-chatgpt-salesforce-accounts/">the sales team's Salesforce playbook</a>. Scope by department sits on <a href="/use-cases/">use cases</a>, and the rest of the catalog is at <a href="/connectors/">connectors</a>.</p>
<h2>FAQ</h2><dl><dt><strong>How do you tell which Notion workspace an AI agent wrote to?</strong></dt><dd>Read the audit trail. Elaichi writes one entry for each connected-tool call that reaches execution (a call refused earlier writes none), and the account recorded on each is the one the call actually reached, read off the execution and never inferred from the model's intent. With two Notion workspaces connected, filter the trail by the person and read the account on each write.</dd><dt><strong>How do you stop ChatGPT writing to the wrong Notion workspace?</strong></dt><dd>Share a toolbox, not the connections. The person who connected the workspaces leaves both connections unshared, pins the right workspace into a toolbox entry for each tool the team writes with, and shares the toolbox at use. Where one database fits, freeze the parent database on the page-create entry as well. Anyone who also holds use on a workspace's connection reaches its tools without the pins, so do not share the connection itself.</dd><dt><strong>How do you stop an AI agent from deleting Notion pages?</strong></dt><dd>Block delete_a_notion_page_by_id and delete_a_notion_block_child_by_id with a restriction on the role the product team holds. Blocks always beat allows. Notion's update tools can also move a page or a database to the trash, so either block them too or freeze the page update's trash argument to false on the toolbox entry. Notion keeps trashed content restorable, but someone has to notice first.</dd><dt><strong>Why not use Notion's own MCP server?</strong></dt><dd>For one workspace and one app, Notion's server is simpler. Notion hosts it, the client reads and updates only content the person can already access, and workspace owners manage MCP clients in Notion's settings. Elaichi adds one address across apps and clients, restrictions written once per role across apps, frozen arguments such as a pinned database, and one audit trail across apps. One removal in Elaichi ends that person's access through it to every app from their next call, while their Notion account is closed separately.</dd><dt><strong>Does a SCIM deprovision remove someone from Elaichi?</strong></dt><dd>No. A SCIM deprovision suspends the Elaichi member and never removes them. Suspension revokes every live grant, so the person's next call through Elaichi is refused. Removing the member, with its offboarding preflight, is a separate step an admin takes in Elaichi, and their Notion account is another.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>team-playbooks</category>
    </item>
    <item>
      <title>Shadow AI browser extension log: what it proves</title>
      <link>https://elaichi.ai/blog/shadow-ai-it-admin-browser-extension-log/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/shadow-ai-it-admin-browser-extension-log/</guid>
      <description>A shadow AI browser extension log proves which AI extensions are installed, where, and which sites they asked to read. It cannot show what anyone pasted.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> A shadow AI browser extension log proves which assistant extensions are installed, how widely, and which permissions and websites they asked for. It cannot show what anybody pasted, which account they signed into, or what happened outside the managed browser. Elaichi closes the gap from the other side: one organization-wide MCP endpoint with read-only restrictions first, so the assistant reads the ticket with permission and the paste has no job to do.</aside>
<p>A shadow AI browser extension log proves which AI assistant extensions are installed and how widely. It also shows what each one asked to reach, down to the websites it can read or change. It does not prove that anyone pasted company data, which account they used, or what happened on a phone or an unmanaged laptop. Read it as a measure of exposure, then pull the records that answer the rest.</p>
<p>Legal asks whether anyone is putting customer data into an AI assistant. You open the Apps &#x26; extensions usage report in the Google Admin console, and one row answers the question badly:</p>
<pre><code>App name       App type           Install type   Installs   Permission
AI Assistant   Chrome extension   normal         143        9
</code></pre>
<p>Its detail page lists the websites the extension asked to read or change data on, and for this one that means every site. Five more rows look like it: six assistants, across most of a fleet of 212 managed browsers.</p>
<p>The report is useful: it sizes the exposure, and <a href="https://support.google.com/chrome/a/answer/9902456?hl=en">Google's documentation</a> notes that the same screen can block or force-install an extension for an organizational unit. It also stops well short of the question legal asked. The instinct is to block all six. Blocking moves the traffic to the phone, the personal browser profile and the assistant's web app, none of which this console sees.</p>
<h2 id="what-does-a-shadow-ai-browser-extension-log-actually-prove">What does a shadow AI browser extension log actually prove?</h2>
<p>It proves installation and requested access, and nothing about content.</p>
<p>For each extension, Chrome's report gives you five facts:</p>
<ul>
<li>The app name and its ID, which pin the vendor.</li>
<li>How it was installed: by admin policy, normally, by other software on the machine, or unpacked in developer mode.</li>
<li>How many browsers, profiles and ChromeOS devices carry it.</li>
<li>How many permissions it requested, and on its detail page, which websites it asked to read or change.</li>
<li>Whether its Chrome Web Store listing is still published or was taken down.</li>
</ul>
<p>Reporting has to be turned on first, and Google says data can take up to 24 hours to show up. The row is an inventory of capability, not a record of behavior. An extension that can read and change data on every site can read an open Salesforce tab. The report does not say that it did. Treat the install count as your exposure and stop there.</p>
<h2 id="what-can-the-extension-log-not-tell-you">What can the extension log not tell you?</h2>
<p>Four things, and each one breaks a conclusion somebody will try to draw from the report.</p>
<p><strong>Content.</strong> No paste text, no uploaded file, no prompt. A paste happens on the device and leaves no record in the system the data came from. Endpoint DLP (data loss prevention software on the device) is the tool built to see it. <a href="https://learn.microsoft.com/en-us/purview/endpoint-dlp-create-policy-restrict-paste-in-browsers">Microsoft Purview</a>, for one, evaluates content at the moment it is pasted into a browser and can audit, warn or block by destination site. <a href="/blog/casb-dlp-vs-governed-mcp-endpoint/">What a CASB and DLP each see</a> sets that instrument beside a governed endpoint.</p>
<p><strong>Account.</strong> The row does not say whether the person signed into the assistant with corporate SSO (single sign-on, where your identity provider issues the session) or with a personal account. The two carry very different retention and discovery consequences.</p>
<p><strong>Purpose.</strong> An assistant used to reword a sentence and one used to summarize a customer's support history look identical in the report.</p>
<p><strong>Coverage.</strong> The report covers enrolled browsers, managed profiles and ChromeOS devices. It does not see the mobile app, an unmanaged laptop, or the assistant's web interface used without an extension. A number taken from it is a floor, not a measurement.</p>
<h2 id="which-other-logs-should-you-pull-before-writing-the-policy">Which other logs should you pull before writing the policy?</h2>
<p>Three partial records beat one, so pull all three before the policy meeting.</p>
<p>Start with the OAuth grants in your identity provider. OAuth is the sign-in flow that hands an application a scoped token instead of a password. In Google Workspace, the API controls page lists the third-party apps that have accessed Google data (<a href="https://support.google.com/a/answer/7281227?hl=en">Google's admin help</a>). It shows how many users each app has and which Google services it uses. In Microsoft Entra, an enterprise app's User consent tab shows the permissions granted to specific users or groups (<a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/manage-application-permissions">Microsoft's guide</a>). Those lists find assistants connected straight to mail and files, which the extension report never sees.</p>
<p>Next, the admin consoles of Salesforce, Notion, Zendesk and the other systems that hold the data show which apps were authorized against them.</p>
<p>Last, the admin console of any assistant you already pay for usually shows who is signed in to the workspace.</p>
<p>None of the three shows a paste. Without endpoint DLP, that is the honest state of the evidence, which is why a policy written from the extension report alone gets argued about rather than followed.</p>
<h2 id="why-do-people-paste-company-data-into-ai-assistants">Why do people paste company data into AI assistants?</h2>
<p>Because copy and paste is the only read path they have.</p>
<p>A support agent with forty open tickets wants a summary of a customer's history. The assistant cannot reach Zendesk, so the agent becomes the data pipe: open the desk, select the thread, switch tabs, paste. A finance analyst wants last quarter's figures explained, so the sheet goes into the chat window. Neither person is defying a policy. They are working around a missing connector, and the company data now sits in the chat history of a tool nobody approved.</p>
<p>That is the useful reading of the report: six assistants on most of the fleet is a request for an assistant that can see the ticket. Give it that, with permission, and the paste has no job to do.</p>
<h2 id="what-does-a-sanctioned-read-path-look-like">What does a sanctioned read path look like?</h2>
<p>One organization-wide endpoint, with read-only restrictions first.</p>
<p>MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">MCP specification</a> describes tools as the way a model reaches external systems, such as querying a database or calling an API. Elaichi is a governed MCP control plane. Each SaaS account is connected once, and its tools are served from one address, <code>POST /mcp</code>. That address speaks standard MCP over Streamable HTTP and sits behind OAuth. Nobody gets a personal URL, and no token sits in a client config.</p>
<p>An admin adds that address once where the client allows it. Each person then connects, signing in with their own grant. On Claude Team and Enterprise, an owner registers it in Organization settings > Connectors, and members connect from Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp">Anthropic's setup steps</a>). In ChatGPT, full MCP support with write actions is a beta on Business, Enterprise and Edu as of October 2026 (<a href="https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt">OpenAI's help article</a>). There, an admin or owner creates and publishes the app for the workspace, and <a href="/blog/connect-elaichi-to-chatgpt/">connecting ChatGPT</a> walks through the steps.</p>
<p>Two layers decide what anybody can see and do. Role-based access control (RBAC) sets what a member may do, and every member holds exactly one role. Sharing decides what they can see at all: a person sees only resources they own or that someone explicitly shared with them, and no organization-level permission quietly widens that list.</p>
<p>Restrictions are the third layer, and the one that matters here. A restriction sets which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. So the first restriction you write is the one that changes anything.</p>
<h2 id="in-what-order-should-you-set-up-read-only-access">In what order should you set up read-only access?</h2>
<p>Connect the accounts, write the allow rules, pilot one client, then read the audit trail.</p>
<p>One trap comes before the rules. In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. No rule is stricter, and none is easier to create by accident.</p>
<p>Write blocks for deletes as well as allows for reads, because blocks always beat allows. A block matches either the tool's advertised name or the operation the rule was pinned to. An allow matches that operation only, so a vendor renaming a tool cannot widen what you allowed. <a href="/blog/block-matches-name-allow-matches-operation/">Why the two rules match differently</a> sets out the reasoning.</p>
<p>Some arguments are not the model's to choose, such as the workspace or the region. Freeze them. A frozen key is cut from the tool's schema. The frozen value overrides anything the model sends when the call runs.</p>
<p>Role and restriction changes in Elaichi take effect within about two minutes on every surface: MCP, the console and REST. Grant revocation, member removal and suspension land on the next call, because the grant is re-read from the organization store each time. Plan the pilot around both timings rather than assuming either one.</p>
<h2 id="what-does-the-assistant-see-once-accounts-are-connected">What does the assistant see once accounts are connected?</h2>
<p>It sees less than people expect. In Elaichi, connected tools are never listed one by one, however few there are. The model looks a tool up with <code>search_tools</code> when it needs one, then calls it through <code>execute_tool</code>.</p>
<p>A restricted tool is withheld from the tool list and cannot be called. Search names it, flagged restricted, with no schema. The same rule is checked again when a call runs. Search also has a relevance floor, so a weak match returns nothing instead of a tool from the wrong app. <a href="/blog/search-tools-ranking-floor-idf/">How that floor is calculated</a> is set out step by step.</p>
<h2 id="what-happens-when-someone-on-that-row-leaves">What happens when someone on that row leaves?</h2>
<p>Elaichi runs a preflight check before removing them, and the check refuses rather than guessing.</p>
<p>First, any private connection that a shared toolbox (a saved set of tools and accounts) still depends on blocks the removal until an admin transfers it to a member. A transfer goes to one member, never to a team or the organization. A private connection that nothing beyond the person depends on cannot be transferred and is deleted with them.</p>
<p>In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. The endpoint stops serving that person on the next call. A contractor whose last day was yesterday needs a different order of operations, which <a href="/blog/offboarding-when-the-agent-holds-access/">offboarding when the agent holds access</a> covers.</p>
<h2 id="what-does-the-audit-trail-answer-that-the-extension-log-cannot">What does the audit trail answer that the extension log cannot?</h2>
<p>Which account was reached, by whom, through which tool, and whether the call worked.</p>
<p>Elaichi keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The connection on each entry is the account the call actually reached, read from the execution and not from what was asked for. After a surprise change, that settles the usual first question: which of two Notion workspaces received the write. The <code>actor_kind</code> field is recorded, not inferred, and its value <code>ai_assistant</code> marks the Elaichi Agent. A call from ChatGPT or Claude is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named.</p>
<p>Each entry holds the one path argument that names the object, as the target id, and nothing else about the arguments. A compliance reviewer reads the trail from the Auditor seat, which is read-only and free.</p>
<h2 id="does-a-sanctioned-read-path-stop-people-pasting">Does a sanctioned read path stop people pasting?</h2>
<p>No. Governed read access removes the reason to paste, not the ability.</p>
<p>The six extensions stay installed until you change browser policy, and anyone who wants to paste still can. Narrow the browser as well, a job browser policy is good at. Microsoft's guidance for Edge is to manage extensions by the permissions they request and the websites they can reach (<a href="https://learn.microsoft.com/en-us/deployedge/microsoft-edge-manage-extensions">Microsoft's extension management guide</a>). A runtime block on hosts keeps extensions from reading or changing data on the sites you name. Staff can keep a writing assistant without it running on Salesforce or Zendesk. One measure without the other either starves people of a tool they will find anyway, or leaves an unmanaged surface next to a managed one.</p>
<p>One more limit belongs in the internal pitch. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. The endpoint still enforces RBAC per operation, OAuth scope limits and the <code>forbidden</code> classification, which no scope unlocks. It also redacts outputs and writes an audit row for each call that reaches execution.</p>
<aside class="cta cta-row" role="complementary" aria-label="Call to action"><p>The security page puts the credential model, sharing and per-person attribution in one place, written for the reviewer who signs off.</p><a href="/security/" class="cta-button">See the security page</a></aside>
<h2 id="when-is-the-extension-log-all-the-tooling-you-need">When is the extension log all the tooling you need?</h2>
<p>When you can name every person on that row and talk to each of them this week. At that size a control plane is premature.</p>
<p>Twelve people, one system, one assistant: a conversation, a sanctioned account and a browser policy get you further than a purchase. Elaichi has two plans, Gold and Black. Gold's USD list price is $15 per user per month, and <a href="/pricing/">the pricing page</a> shows the local price where one applies. Buying before you have a second client or a second team to govern means paying for an address model you are not using yet. <a href="/blog/when-you-dont-need-an-mcp-gateway/">When you don't need a gateway</a> sets out the point where that changes.</p>
<p>If the clients your people use already ship connectors of their own, <a href="/blog/elaichi-vs-native-ai-connectors/">one plane against many clients</a> is the comparison to read. The systems you can connect are listed in the <a href="/connectors/">connector catalog</a>, the per-team rollouts sit under <a href="/use-cases/">use cases</a>, and the rest of this thread continues in <a href="/blog/category/shadow-ai/">Shadow AI</a>.</p>
<h2>FAQ</h2><dl><dt><strong>What does a browser extension report prove about AI assistant use?</strong></dt><dd>It proves installation and requested access. Chrome's Apps & extensions usage report, for example, shows each extension's name and ID, how it was installed, how many browsers, profiles and devices carry it, and how many permissions it requested, with the websites it asked to read or change on its detail page. It does not show what was pasted, which account the person signed into, or any activity on a phone, an unmanaged laptop or the assistant's own web interface.</dd><dt><strong>Can any log show what an employee pasted into an AI assistant?</strong></dt><dd>Not the extension report, and not the system the data came from, because a paste happens on the device. Endpoint DLP is built for that: Microsoft Purview, for example, evaluates content at the moment it is pasted into a browser and can audit, warn or block. Identity provider grant lists, SaaS admin consoles and an assistant's admin console each show part of the connected access, and none of them shows prompt content.</dd><dt><strong>How long does a restriction change take to take effect in Elaichi?</strong></dt><dd>It takes about two minutes. Roles and restrictions pass through a short cache and then edge propagation, and the timing is the same on the MCP endpoint, the console and the REST surface. Grant revocation, member removal and suspension are different: they land on the next call, because the grant's revocation state is re-read from the organization store on every call.</dd><dt><strong>Does one organization-wide MCP endpoint mean everyone can reach every tool?</strong></dt><dd>No. In Elaichi the address is shared and the grant is what varies. A member sees only resources they own or that were explicitly shared with them, and no organization-level permission silently widens a listing. Restrictions then decide which connectors and which individual tools a role or a user may reach, and they are checked at every place a member can reach a connector or tool, including listing, connecting, advertising, executing, the final outbound-request check and opening a stored tool file.</dd><dt><strong>Should I block AI assistant extensions outright?</strong></dt><dd>Usually not on its own. Blocking moves the traffic to the mobile app, a personal browser profile or the assistant's web interface, all outside a managed browser console. Browser policy can instead limit extensions by the permissions they request and keep them off sensitive sites. Pair that with a sanctioned read path under read-only restrictions, so people have no reason to paste.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>shadow-ai</category>
    </item>
    <item>
      <title>An API gateway for MCP, or an MCP-native server?</title>
      <link>https://elaichi.ai/blog/api-gateway-with-mcp-vs-mcp-native/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/api-gateway-with-mcp-vs-mcp-native/</guid>
      <description>An API gateway for MCP fits when the tools are your own APIs, already behind it. For SaaS accounts your staff sign in to, an MCP-native server fits better.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> An API gateway for MCP, such as the MCP features in Kong, Tyk and Zuplo, puts an MCP face on APIs and MCP servers that already exist. That is the right call when the tools are your own services and your team already runs the gateway. Elaichi is an MCP-native server instead: it starts from the SaaS accounts your staff sign in to, authors most of its connectors itself, and serves them through one organization-wide MCP endpoint behind OAuth.</aside>
<h2 id="should-you-use-an-api-gateway-for-mcp">Should you use an API gateway for MCP?</h2>
<p>Use an API gateway for MCP when the tools your agents need are your own services and Kong, Tyk or Zuplo already sits in front of them. When the request names SaaS accounts instead, an MCP-native server fits better. Those apps are not behind your gateway, and putting them there would be your team's work. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.</p>
<p>The request usually arrives in that second form. Support asks for Claude to reach Zendesk. Finance asks for ChatGPT to read Xero. Your gateway vendor has just shipped an MCP feature, and switching it on looks like the shortest path.</p>
<p>The deciding question is narrower than a feature comparison. It is where the tools come from, and who holds the credential that calls them.</p>
<h2 id="how-does-a-gateways-mcp-feature-differ-from-an-mcp-native-server">How does a gateway's MCP feature differ from an MCP-native server?</h2>
<table>
<thead>
<tr>
<th>Question</th>
<th>API gateway with an MCP feature</th>
<th>MCP-native server (Elaichi)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Where the tools come from</td>
<td>APIs and MCP servers that already exist behind the gateway</td>
<td>SaaS accounts your staff sign in to</td>
</tr>
<tr>
<td>Who writes the tool definitions</td>
<td>Whoever builds the upstream API or MCP server</td>
<td>Elaichi, for 600+ connectors, and it owns the repair path</td>
</tr>
<tr>
<td>Who runs servers</td>
<td>Your platform team runs the gateway</td>
<td>Nobody on your side; one <code>POST /mcp</code> endpoint for every client</td>
</tr>
<tr>
<td>Identity on each call</td>
<td>Whatever your gateway policy accepts</td>
<td>A per-person OAuth grant</td>
</tr>
<tr>
<td>Control over arguments</td>
<td>Request policy you write at the gateway</td>
<td>Frozen parameters merged over the call, plus per-tool restrictions</td>
</tr>
<tr>
<td>When a change lands</td>
<td>Set by your gateway configuration</td>
<td>Grant revocation re-read on every call; role and restriction changes within about two minutes</td>
</tr>
</tbody>
</table>
<p>A gateway's MCP feature starts from endpoints you already operate and puts an MCP face on them. An endpoint here is one URL that accepts requests. An MCP-native server starts from the SaaS accounts your staff already sign in to, and serves tools for those accounts.</p>
<p>That difference decides most of what follows. If the upstream is your own service, the gateway already holds the policy, the identity model and the logs. If the upstream is Salesforce, Notion and Xero, something has to answer behind the gateway for each app: a server the vendor hosts, one you run, or one you build. Each is another address to front and another permission model to reconcile.</p>
<p>So the comparison is not which product governs better. It is which product's assumptions match the apps your people are asking for.</p>
<h2 id="what-are-the-mcp-features-in-kong-tyk-and-zuplo-built-for">What are the MCP features in Kong, Tyk and Zuplo built for?</h2>
<p>They are built for traffic to APIs and MCP servers that already exist (vendor pages checked October 2026). <a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk's documentation</a> describes an MCP Gateway inside an API management platform. It proxies and governs remote MCP servers, and it can generate an MCP proxy from a REST API that Tyk already manages. <a href="https://zuplo.com/mcp-gateway">Zuplo's MCP Gateway page</a> describes federating MCP servers behind one gateway with a built-in OAuth server. <a href="https://developer.konghq.com/ai-gateway/">Kong's AI Gateway documentation</a> describes AI MCP Server entities that expose existing APIs as tools an agent can call.</p>
<p>Read the three together and they share a starting point. Something already answers behind the gateway: your own REST API, an MCP server your team runs, or a remote MCP server somebody else runs. The gateway sits in that path and applies policy.</p>
<p>That is a good job to have when the upstream exists. When finance wants Xero inside ChatGPT, ask any gateway vendor who supplies the thing the gateway fronts, and who keeps it working when the app changes its API.</p>
<h2 id="when-should-you-keep-the-gateway-you-already-run">When should you keep the gateway you already run?</h2>
<p>Keep it when the tools your agents need are your own services and the gateway is already their front door. The reasoning is practical: you already have the parts that are expensive to acquire twice.</p>
<p>You have a deployment your platform team knows how to upgrade. You have rate limits and quotas that somebody has already tuned. You have request logs landing in the observability stack your on-call team reads at 3am. You have an auth setup that security has already reviewed. Adding MCP to the same estate keeps one policy engine and one set of dashboards.</p>
<p>A second control surface for internal APIs would mean two places to change a rule and two places to look after an incident. A gateway feature that does most of what you wanted is the better outcome. If the cost of running the server side yourself is the open question, <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">the cost breakdown for running MCP servers yourself</a> covers it. If the request is small and recent, it may be <a href="/blog/when-you-dont-need-an-mcp-gateway/">too early for any gateway at all</a>.</p>
<h2 id="where-does-an-mcp-native-server-start-instead">Where does an MCP-native server start instead?</h2>
<p>It starts from the SaaS accounts, not from your services. Elaichi connects each account a company uses once and serves the tools those accounts expose through one organization-wide MCP endpoint. That endpoint is <code>POST /mcp</code>: standard MCP over <a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/transports">Streamable HTTP</a>, JSON-RPC 2.0, stateless, behind OAuth. OAuth here is the sign-in handshake that issues a per-person grant instead of a shared key.</p>
<p>Clients point at that one address and sign in: Claude, ChatGPT, Cursor or any MCP client. Nothing is issued per person or per toolbox: no separate URL, no embedded token, and no MCP server to create, list or revoke. The address is fixed; the grant is what varies.</p>
<p>An admin adds the address once where the client allows it, and each member then connects with their own sign-in. In Claude Team and Enterprise, an owner adds it under Organization settings > Connectors, and members connect it under Customize > Connectors. On Claude Pro and Max, each person adds it under Customize > Connectors (<a href="https://support.claude.com/en/articles/11175166">Claude Help Center</a>). In Cursor, the admin MCP allowlist is Enterprise only, and adding a server to it does not push the server to anyone's machine (<a href="https://cursor.com/docs/enterprise/model-and-integration-management">Cursor docs</a>). The ChatGPT flow is in <a href="/blog/connect-elaichi-to-chatgpt/">connecting ChatGPT to Elaichi</a>, and <a href="/blog/elaichi-vs-native-ai-connectors/">one plane, many clients</a> compares the three side by side.</p>
<p>Elaichi also serves 600+ connectors. It authors and maintains most of them on its own infrastructure, and the rest are vendors' own MCP servers that it governs under the same rules. Companies do not run MCP servers for either kind. Connector credentials do not live in Elaichi either. Each account's secrets sit in a separate credential service, encrypted at rest, and that service owns token refresh. When a refresh fails, the connection is flagged <code>needs_reauth</code>, so the failure is visible instead of silent.</p>
<h2 id="which-five-questions-settle-the-choice">Which five questions settle the choice?</h2>
<p>Answer these five and the choice usually makes itself.</p>
<ol>
<li><strong>Where do the tools come from?</strong> Your own APIs point at the gateway. Third-party SaaS accounts point at a server that authors connectors for them.</li>
<li><strong>Who is the caller?</strong> A service account calling your API is a gateway problem. A named employee in Claude or ChatGPT needs a grant of their own.</li>
<li><strong>How many addresses does the rollout create?</strong> One organization endpoint is added once per client, and each person signs in. A per-team or per-member address is a spreadsheet somebody has to keep current.</li>
<li><strong>What happens when somebody leaves?</strong> Ask who revokes the access and how fast. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call, so the next call fails.</li>
<li><strong>What does the record say afterwards?</strong> The first question after an unexpected change is which account was touched.</li>
</ol>
<p>Elaichi's answers to the last two are specific. Role and restriction changes wait out a 60-second cache and then reach the edge, so they take effect within about two minutes. Grant revocation, member removal and suspension land on the next call. The audit trail keeps one entry for each connected-tool call that reaches execution (a call refused earlier writes none). Each entry records the connection the call actually reached, read from the execution rather than the request. A call from an MCP client is recorded under the person who signed in, with surface <code>mcp</code> and the OAuth client named. Claude, ChatGPT and Cursor are marked verified. The trail logs the one path argument that names the object, as the target id, and nothing else about the arguments.</p>
<h2 id="can-you-run-a-gateway-and-an-mcp-native-server-side-by-side">Can you run a gateway and an MCP-native server side by side?</h2>
<p>Yes. Split by who owns the upstream, not by team or by app. Internal services stay behind the gateway you already run. Third-party SaaS accounts go through the MCP-native server. One rule, applied once, and nobody has to remember which product governs which tool.</p>
<p>That split keeps each system on the work its design fits. The gateway keeps request-level policy over code you deploy. The MCP server keeps per-employee grants over accounts you do not deploy. The failure to avoid is governing the same tool in two places, because the rule that gets changed is the one somebody remembers.</p>
<p>On the Elaichi side, governance has three layers. Roles group 58 action strings, and each member holds exactly one role. Sharing is a grant of view, use or edit on a resource, and a member sees only resources they own or that someone shared with them. Restrictions decide which connectors and which individual tools a target may reach. Who a restriction can name is fixed: restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A rule aimed at a member can only narrow what their role allows, and never replaces or loosens a role rule. A block can match a tool's advertised name or the operation behind it, while an allow matches only the operation. <a href="/blog/block-matches-name-allow-matches-operation/">Why a block matches the label and an allow does not</a> gives the reason.</p>
<h2 id="what-are-the-limits-on-each-side">What are the limits on each side?</h2>
<p>Both sides have edges, and the honest ones are short. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call. What does hold on the Elaichi endpoint is per-operation role checks, the <code>forbidden</code> tool classification, output redaction, OAuth scope limits and audit logging of each call that reaches execution.</p>
<p>The region is chosen when the organization is created and cannot change, so an existing organization cannot move to another region later. Deleting an organization tears down the workspace and deletes every connector credential. Three stores keep residue, and the deletion names them: the audit history, the analytics events, and the credential service's organization, environment and installed-connector configuration rows. Never call it total erasure.</p>
<p>On the gateway side, take nobody's word for what a product lacks, ours included. Ask the vendor instead:</p>
<ul>
<li>Who writes and updates the tool definitions for each third-party app?</li>
<li>What identity does a tool call carry when an employee triggers it from Claude?</li>
<li>What does the log show about which account was reached?</li>
</ul>
<p>Price is part of the shape too. Gold lists at $15 per user per month, or $120 per user per year, in USD, and <a href="/pricing/">pricing</a> shows the price for your region. Black is the other plan. There is a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. Suspended members and free-seat roles are left out of the billable count, and the read-only Auditor seat is free, so a compliance reviewer does not cost a license.</p>
<p>If your answer to question one was your own APIs, stay on the gateway. If it was a list of SaaS names, start with <a href="/blog/what-is-an-mcp-gateway/">the four gateway shapes</a>, then browse the <a href="/connectors/">connector catalog</a>, the <a href="/use-cases/">team rollouts</a>, or the other <a href="/blog/category/comparisons/">gateway comparisons</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Is an API gateway for MCP the same as an MCP-native server?</strong></dt><dd>No. An API gateway that added MCP, such as Tyk's MCP Gateway, Zuplo's MCP Gateway or Kong AI Gateway, fronts APIs or MCP servers that already exist (vendor docs checked October 2026). An MCP-native server such as Elaichi starts from third-party SaaS accounts, authors most of the connectors for them, and serves them through one organization-wide MCP endpoint behind OAuth. The choice turns on where the tools come from.</dd><dt><strong>When should we keep the API gateway we already run?</strong></dt><dd>When the tools your agents need are your own services and the gateway is already the front door to them. You already have a deployment your platform team can upgrade, tuned rate limits, request logs in the observability stack your on-call team uses, and an auth setup security has reviewed. A second control surface for internal APIs means two places to change a rule and two places to look after an incident.</dd><dt><strong>Can we run an API gateway and an MCP-native server at the same time?</strong></dt><dd>Yes, and the clean split is by who owns the upstream. Internal services you deploy stay behind the API gateway. Third-party SaaS accounts go through the MCP-native server, which holds a grant per employee over accounts you do not deploy. Avoid governing the same tool in both places, because the rule that gets updated is the one somebody remembers.</dd><dt><strong>How fast does a permission change take effect in Elaichi?</strong></dt><dd>Role and restriction changes take effect within about two minutes, because they resolve through a 60-second cache plus edge propagation on every surface. Removal and suspension are faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, and the grant is re-read on every call, so the next call fails.</dd><dt><strong>Does Elaichi protect tool calls from prompt injection?</strong></dt><dd>No. The prompt-injection write gate lives in the Elaichi agent window and does not apply to a raw tool call, because an MCP server never sees a user prompt. What does hold on the endpoint is per-operation role checks, the forbidden tool classification, output redaction, OAuth scope limits and audit logging of each tool call that reaches execution.</dd></dl>]]></content:encoded>
      <dc:creator>Uday Gajavalli</dc:creator>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
    <item>
      <title>MCP gateway pricing: per seat vs per call</title>
      <link>https://elaichi.ai/blog/mcp-gateway-pricing/</link>
      <guid isPermaLink="true">https://elaichi.ai/blog/mcp-gateway-pricing/</guid>
      <description>MCP gateway pricing is metered per call, per task or per seat. Per call is cheaper at low volume; per seat is the bill a company can forecast.</description>
      <content:encoded><![CDATA[<aside><strong>TL;DR:</strong> MCP gateway pricing comes in three units. Composio bills tool calls, and Zapier MCP consumes two tasks from the plan's allowance for each successful tool call. Elaichi bills seats: Gold lists at $15 per user per month in USD, or $120 per user per year, and the Guest, Billing Admin and Auditor seats are free. The metered models are cheaper at low volume and harder to forecast as usage grows, so price both on a week of your own pilot data before choosing.</aside>
<p>Somebody in finance asks what the AI tooling line will cost next year. You go to answer and find the number depends on how many times an agent called a tool last month. A headcount number survives a budget review. A consumption number gets a follow-up question every quarter.</p>
<p>That gap is most of what MCP gateway pricing decides. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. The products that sit between those assistants and a company's apps come in several shapes, which <a href="/blog/what-is-an-mcp-gateway/">the gateway explainer</a> sorts out. The ones priced here bill in one of three units: the call, the task or the seat. Self-hosted gateways add a fourth answer, no license at all, and move the cost onto engineering time.</p>
<p>What follows prices each unit, names the costs that never reach an invoice, and says plainly where the metered models are the cheaper correct answer. It ends with a method for pricing them against each other on your own numbers.</p>
<h2 id="how-is-mcp-gateway-pricing-metered">How is MCP gateway pricing metered?</h2>
<p>By the call, the task or the seat. Each unit tracks something different: what the agents do, what they draw from an automation plan, or how many people hold access.</p>
<p>Composio bills tool calls. Its pricing page lists Hobby as free with 3 team members, Pro at $29 a month, and a custom Enterprise tier that names SSO, SCIM and customer-managed keys (<a href="https://composio.dev/pricing">Composio pricing</a>, checked September 2026). SSO is sign-in through the company's identity provider. SCIM keeps the user list in step with that provider.</p>
<p>Zapier MCP has no separate billing. Zapier's documentation says each successful tool call through your MCP server consumes two tasks, failed calls consume none, and those tasks count toward the plan's allowance (<a href="https://docs.zapier.com/mcp/features/usage">Zapier MCP usage</a>, checked September 2026). The bill moves with how many calls the agents complete, and a call that fails costs nothing.</p>
<p>Elaichi, a governed MCP control plane, bills seats. Gold costs $15 a month for each user, or $120 a year for each user on annual billing. Those are USD list prices, and the <a href="/pricing/">pricing page</a> shows the price for your region. Call volume does not change the number. A seat is an active membership in the organization, and three roles cost nothing.</p>
<p>Self-hosted gateways sit outside all three. Lunar.dev publishes an open-source version of its MCPX gateway (<a href="https://www.lunar.dev/">lunar.dev</a>, checked September 2026). Tyk makes proxies for remote MCP servers available on every Tyk Gateway license, and keeps upstream OAuth for its Enterprise Edition (<a href="https://tyk.io/docs/ai-management/mcp-gateway/overview">Tyk MCP Gateway</a>, checked October 2026). The license can be zero. The upgrades, the on-call rota and the credential rotation never are.</p>
<h2 id="per-seat-per-call-or-per-task-which-bill-can-you-forecast">Per seat, per call or per task: which bill can you forecast?</h2>
<p>The seat. A seat price is predictable and slightly wasteful, while a call or task price is efficient and hard to forecast. At company scale the forecast usually matters more, though not at every size.</p>
<p>A seat price is one multiplication: billable people times rate. You can write it down in August and it is still true in March, give or take hiring. The waste is real. You pay the same for the finance manager who runs two queries a month as for the support lead who runs two hundred a day. You also pay full rate for the person who connected a client once and forgot about it.</p>
<p>Consumption pricing inverts that. Thin usage costs almost nothing, which is a real advantage. The risk is that usage is not a decision anyone makes. An agent that polls a queue every few minutes, a workflow somebody discovers in week three, or one enthusiastic analyst can each move the number without a purchase order. If your controls sit downstream of an allowance, a busy month looks like an incident. A task meter behaves the same way at a different exchange rate.</p>
<p>So predictability comes down to who controls the volume. For a five-person company using an assistant occasionally, the metered plan almost certainly wins, especially when the automation account is already paid for. For sixty people across support, finance and sales, a seat line is easier to defend and easier to cap. The bill cannot outgrow the number of people in a billable role.</p>
<p>The table sets the four models against the same axes. The last column counts what an admin has to look after once everyone is connected: the web addresses an AI client calls, and the servers behind them.</p>
<table>
<thead>
<tr>
<th>Model</th>
<th>Billing unit</th>
<th>What raises the bill</th>
<th>Forecast at company scale</th>
<th>Cheaper when</th>
<th>Addresses and servers after rollout</th>
</tr>
</thead>
<tbody>
<tr>
<td>Per call: Composio</td>
<td>Tool calls; Hobby free with 3 team members, Pro $29 a month, Enterprise custom</td>
<td>More tool calls</td>
<td>Hard: volume follows agent behavior</td>
<td>Few people make few calls</td>
<td>One per team, per its MCP Gateway page</td>
</tr>
<tr>
<td>Per task: Zapier MCP</td>
<td>Tasks from the plan's allowance: two per successful call, none per failed</td>
<td>More successful calls</td>
<td>Hard: volume follows agent behavior</td>
<td>The account is already paid for and calls are few</td>
<td>One shared URL, with a server per member per client</td>
</tr>
<tr>
<td>Per seat: Elaichi</td>
<td>Active memberships at $15 per user a month, or $120 a year; Guest, Billing Admin and Auditor free</td>
<td>More people in billable roles</td>
<td>Easy: billable seats times rate</td>
<td>Many people use it every week</td>
<td>One for the organization</td>
</tr>
<tr>
<td>No license: open-source gateway you host</td>
<td>No license fee</td>
<td>Engineering hours for upgrades, on-call and credential rotation</td>
<td>Set by the rota, not the invoice</td>
<td>A platform team already runs services</td>
<td>Whatever your team deploys</td>
</tr>
</tbody>
</table>
<h2 id="when-is-per-call-pricing-the-cheaper-choice">When is per-call pricing the cheaper choice?</h2>
<p>At low volume, and sometimes by the whole bill. Below a certain number of calls per person, a meter charges less than a seat does, and the smallest teams can pay nothing at all.</p>
<p>Three people who need an assistant to touch two apps are the clearest case. Composio lists Hobby as free with 3 team members (<a href="https://composio.dev/pricing">composio.dev/pricing</a>, checked September 2026). No seat price beats zero. At that size nobody is governing anything; three colleagues are getting a tool.</p>
<p>A company that already pays for Zapier is the second case. Zapier MCP uses the same app connections and actions as Zaps (<a href="https://help.zapier.com/hc/en-us/articles/48308034391821-What-is-Zapier-MCP">what Zapier MCP is</a>, checked September 2026). If the operations team has already built Zaps across forty apps, those connections exist and the coverage is paid for. Adding MCP access then draws on a task allowance the company already buys. The question to ask is what happens at fifty users, and what happens when one of them leaves.</p>
<p>The third case is a company where most people are light users. A meter charges the person who runs four calls a month almost nothing. A seat charges that person full rate.</p>
<p>The crossover is a volume, not an opinion. Divide the monthly seat price by the vendor's price for one call. The result is the number of calls per person per month at which the two bills match. On Zapier MCP, the price of one call is the price of two tasks. Below the crossover the meter is cheaper. Above it the seat is, and the gap widens with every workflow that proves useful.</p>
<p>Seats start to earn their price when the work stops being connection setup and starts being governance. Governance is who may call a delete, and which of two Notion workspaces the agent wrote to. It also covers what happens to a contractor's access on their last day.</p>
<h2 id="what-counts-as-a-billable-seat-in-elaichi">What counts as a billable seat in Elaichi?</h2>
<p>An active membership in a billable role, with a minimum of one seat. Suspended members are excluded from the count, and three roles are free.</p>
<p>Org Owner, Org Admin, People Admin, Team Admin and Member are billable. Guest, Billing Admin and Auditor are free seat classes. Each member holds exactly one role, so each member sits in exactly one seat class. The three free roles are also the three without <code>tool:execute</code>, the permission that gates the MCP endpoint, so a free seat cannot call tools through it.</p>
<p>The Auditor seat matters most when the buyer is IT and the reviewer is not. Auditor is read-only and free. A compliance reviewer can read the audit log, the append-only record of who called which tool against which account, without consuming a license. Leave reviewers out of the seat estimate for that reason.</p>
<p>Elaichi has two plans, Gold and Black, and both are paid. Black is the second plan, and it has no published price yet; the pricing page offers a conversation instead of a rate. Beyond the in-app trail, export to your own Datadog comes with the Black plan, which is launching soon. In Elaichi, customer-managed keys in AWS KMS come with the Black plan, which is launching soon. A budget written today is therefore built on Gold. On Gold, the $120 annual price works out to $10 a month per seat, against $15 on monthly billing. Elaichi offers a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. If the trial ends without checkout, the workspace pauses. Plan-gated features lock and gated routes return a structured error. Nothing is deleted, and subscribing picks up where it left off. Current plan detail sits on the <a href="/pricing/">pricing page</a>.</p>
<h2 id="what-does-the-address-model-add-to-the-bill">What does the address model add to the bill?</h2>
<p>Admin hours rather than license fees. Every MCP address that exists after rollout is a thing to inventory, rotate and account for when somebody leaves, and the count depends on the vendor's design.</p>
<p>Elaichi serves one organization-wide MCP endpoint, <code>POST /mcp</code>, standard MCP over Streamable HTTP, behind OAuth. OAuth is the sign-in that hands a client a grant, the record of what that member may reach, instead of a token somebody pastes into a config file. Claude, ChatGPT, Cursor and any other MCP client point at the same address. No toolbox (a saved set of tools and accounts) gets its own URL, and no token is embedded in a client. Each member still connects once and signs in. What stays fixed is the address, and what varies is the grant.</p>
<p>For Zapier MCP, every client connects to the same URL, and each member gets a server per client. For most MCP clients the member signs in inside the client, and Zapier creates the server during that sign-in. Clients not on Zapier's list, and code you write, use a connection token instead. That token is long-lived, tied to one server, and grants whoever holds it the ability to run the server's tools, so Zapier's docs say to give each user their own server and token rather than sharing one (<a href="https://docs.zapier.com/mcp/overview/how-connections-work">how connections work</a>, <a href="https://docs.zapier.com/mcp/manage/rollout/overview">rollout overview</a>, checked October 2026).</p>
<p>Composio's MCP Gateway page says "each team gets its own MCP endpoint carrying only the tools it is permitted to use" (<a href="https://composio.dev/mcp-gateway">Composio MCP Gateway</a>, checked September 2026). That is one address per team rather than one per member.</p>
<p>Price the difference as admin hours. Ten endpoints means ten things to inventory, ten things to rotate and ten things to remember during an offboarding. Ask each vendor what happens to a departed member's server or token, and price the answer. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change, so a leaver's access ends on the next call. Changing what someone may reach is slower. Role and restriction changes take effect within about two minutes. A restriction is a rule that decides which connectors and which individual tools a target may reach. Both address designs get a fuller treatment in <a href="/blog/zapier-mcp-alternative/">the one-endpoint comparison</a> and in <a href="/blog/one-endpoint-vs-per-team-endpoint/">the per-team endpoint write-up</a>.</p>
<h2 id="how-do-you-read-a-catalog-number">How do you read a catalog number?</h2>
<p>Against your own list of apps and operations, not against another vendor's total. A total says how many apps a vendor lists. It does not say whether the eight or nine your teams run are covered, or whether the operations they need exist inside those connectors.</p>
<p>Composio's Connect docs describe an MCP server at <code>https://connect.composio.dev/mcp</code>. It gives an agent access to "1000+ apps" through seven meta-tools, with OAuth links approved in the browser (<a href="https://docs.composio.dev/docs/composio-connect">Composio Connect docs</a>, checked October 2026). Elaichi serves 600+ connectors. It authors, maintains and runs most of them on its own infrastructure, and the rest are vendors' own MCP servers it governs. Your company runs no MCP servers for either kind.</p>
<p>So run the comparison on your own list rather than on either total. Write down the apps, then the operations: create a ticket, read an opportunity, post to a channel, pull an invoice. Check each one against the vendor's own catalog page. A catalog of a thousand apps that misses your payroll system is worth less to you than a catalog of fifty that covers it.</p>
<p>A missing connector is a cost, so the escape hatch matters more than the total. In Elaichi you can author a custom connector from JSON config, or fork a public one and pull upstream changes through a review surface. That surface separates new tools, safe updates, config diffs, conflicts and upstream removals. Conflicts and destructive removals stay unchecked by default. You can also build a synthetic tool: a graph of steps that each call a connection's tool with templated arguments. Every step runs through the same restriction check as any other call, and the run is audited as one row. The current list is on the <a href="/connectors/">connector catalog</a>, and the feature-level comparison with one vendor is in <a href="/blog/elaichi-vs-composio/">the Composio write-up</a>.</p>
<h2 id="what-about-make-workato-tray-n8n-and-power-automate">What about Make, Workato, Tray, n8n and Power Automate?</h2>
<p>This post does not restate their prices. Each vendor's own pricing page on the day you read it is the only source worth quoting, and those pages move faster than any blog post: <a href="https://www.make.com/en/pricing">Make</a>, <a href="https://www.workato.com/pricing">Workato</a>, <a href="https://tray.ai/pricing">Tray</a>, <a href="https://n8n.io/pricing/">n8n</a>, <a href="https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing">Power Automate</a> (all checked September 2026).</p>
<p>Ask each of them the same five questions, and write the answers down with the date:</p>
<ul>
<li>The billing unit: a seat, a task, an operation or a workflow run.</li>
<li>Whether the MCP surface bills on the same meter as everything else, or separately.</li>
<li>Whether each member needs their own address or token, and who cleans that up when the member leaves.</li>
<li>Who authors and maintains the connectors, and what happens when an app changes its API.</li>
<li>Whether there is a read-only seat for an auditor, and whether it costs a license.</li>
</ul>
<p>The answers to those five decide the annual number more than the headline rate does.</p>
<h2 id="when-is-the-cheapest-correct-answer-to-buy-nothing">When is the cheapest correct answer to buy nothing?</h2>
<p>Sometimes the right purchase in this category is none. Three people, two connected apps and occasional use do not need a control plane or a gateway of any kind, metered or seated.</p>
<p>The native connectors inside the AI client may cover the whole job, and <a href="/blog/elaichi-vs-native-ai-connectors/">the native connector comparison</a> sets out where that stops working. The wider version of the question, with the signals that end the wait, is in <a href="/blog/when-you-dont-need-an-mcp-gateway/">the case for holding off</a>.</p>
<p>If a platform team already runs MCP servers and the argument is about engineering time rather than license fees, the cost model is different again. <a href="/blog/self-hosted-mcp-servers-vs-control-plane/">The self-hosting cost breakdown</a> is the right page for that.</p>
<p>Once the Elaichi trial ends, the product is a line item. If nobody in support, finance or legal is asking for governed access yet, that line item is early.</p>
<h2 id="how-much-does-it-cost-to-give-every-employee-ai-access">How much does it cost to give every employee AI access?</h2>
<p>The bill has two seat lines plus admin time. The first line is the AI client's own seat, whether that is ChatGPT, Claude or Microsoft 365 Copilot, priced on each of those vendors' own pricing pages. The second line is the access layer between the client and the company's apps, which is what this post prices.</p>
<p>The formula in plain words: take the people who will actually call tools, multiply by the client seat plus the access seat, then add the admin hours the address model creates. Headcount is not the multiplier. Reviewers who only read the audit log sit on free Auditor seats and never enter the first two terms.</p>
<p>Elaichi Gold at the USD list price gives the second line directly. The totals below assume every billable seat is on the same plan.</p>
<table>
<thead>
<tr>
<th>Billable seats</th>
<th>Monthly billing, per month</th>
<th>Monthly billing, over a year</th>
<th>Annual billing, per year</th>
</tr>
</thead>
<tbody>
<tr>
<td>50</td>
<td>$750</td>
<td>$9,000</td>
<td>$6,000</td>
</tr>
<tr>
<td>200</td>
<td>$3,000</td>
<td>$36,000</td>
<td>$24,000</td>
</tr>
<tr>
<td>1,000</td>
<td>$15,000</td>
<td>$180,000</td>
<td>$120,000</td>
</tr>
</tbody>
</table>
<p>Suspended members do not count, and neither do the free Guest, Billing Admin and Auditor seats. These are USD list prices; the <a href="/pricing/">pricing page</a> shows the price for your region. None of these figures include the AI client's own seats, which are billed by that vendor.</p>
<p>That is also the shape of the answer if you are replacing a task meter with a per-user line for a whole company. The access layer becomes one row in the budget that call volume cannot move.</p>
<h2 id="how-do-you-price-the-two-models-against-each-other">How do you price the two models against each other?</h2>
<p>Run the comparison on your own numbers rather than on list prices. With a week of pilot data it takes about an hour, and it settles the argument.</p>
<ol>
<li><strong>Count the seats that would hold a grant.</strong> Count the people who would sign in and call tools, not total headcount. Leave out reviewers who only read the audit log, because the Auditor seat is free.</li>
<li><strong>Price the seat column.</strong> Multiply the rest by $15 a month, or by $120 a year on annual billing.</li>
<li><strong>Measure a week of real usage.</strong> Run a one-week pilot and count successful tool calls per active person. Convert the count into each vendor's billing unit using its own pricing page.</li>
<li><strong>Project the consumption column.</strong> Multiply the weekly figure by 52, then double it, because usage rises once a workflow proves useful.</li>
<li><strong>Add the administrative cost to both columns.</strong> Price the setup for each joiner and the access removal for each leaver, including every address or token that has to be created and cleaned up. Add any connector your team would have to build.</li>
<li><strong>Compare at two headcounts.</strong> Run both totals at today's headcount and again at the headcount you plan for next year, so the decision survives hiring.</li>
</ol>
<p>A worked example shows where the conversion bites. Take a company of 60 in which 52 people will call tools and 8 will only review the audit log. At the USD list price, the seat column is 52 times $15, or $780 a month, which is $9,360 over a year. On annual billing it is 52 times $120, or $6,240 a year. The 8 Auditor seats cost nothing.</p>
<p>Now suppose the pilot shows 30 successful calls per active person in the week. That is 1,560 calls across 52 people, 81,120 over a year, and 162,240 once doubled. On a per-call plan, 162,240 is the figure to price. On Zapier MCP it becomes 324,480 tasks, because each successful call consumes two.</p>
<p>Price those figures on each vendor's own page on the day you run them, since rates move faster than this post. Steps five and six then settle the close calls. If the metered total still comes in under the seat column, buy the meter. That result is common at low volume, and it is the correct one.</p>
<p>For what separates these products beyond the bill, start from <a href="/blog/what-is-an-mcp-gateway/">the shapes MCP gateways come in</a>. The <a href="/use-cases/">team use cases</a> show what a first rollout looks like, and more head-to-heads sit under <a href="/blog/category/comparisons/">comparisons</a>.</p>
<h2>FAQ</h2><dl><dt><strong>Is per-call or per-seat MCP gateway pricing cheaper?</strong></dt><dd>Per-call pricing is cheaper at low volume. A few people making a few calls pay little, and a plan with no charge can cover the smallest teams outright. Per-seat pricing is flat and easier to forecast, but a light user costs the same as a heavy one. To find the crossover, divide the monthly seat price by the vendor's price for one call. The result is the number of calls per person per month at which the two bills match. Below it the meter is cheaper, and above it the seat is.</dd><dt><strong>Does Elaichi charge per tool call?</strong></dt><dd>No. Elaichi bills per seat, and call volume does not change the bill. Gold lists at $15 per user per month in USD, or $120 per user per year, and the pricing page shows the price for your region. Billable seats are active memberships, minimum one. Suspended members are excluded from the count, and the Guest, Billing Admin and Auditor roles are free seat classes, so a read-only compliance reviewer does not consume a license.</dd><dt><strong>How does Zapier MCP charge for tool calls?</strong></dt><dd>Zapier's documentation says there is no separate billing for Zapier MCP. Each successful tool call through your MCP server consumes two tasks, failed calls consume none, and those tasks count toward the plan's allowance (https://docs.zapier.com/mcp/features/usage, checked September 2026).</dd><dt><strong>How does Composio price tool calls?</strong></dt><dd>Composio's pricing page makes tool calls the billing unit. It lists Hobby as free with 3 team members, Pro at $29 a month, and a custom Enterprise tier that names SSO, SCIM and customer-managed keys (https://composio.dev/pricing, checked September 2026).</dd><dt><strong>What happens when an Elaichi trial ends without payment?</strong></dt><dd>Elaichi has two plans, Gold and Black, and both are paid. It offers a 14-day trial, no credit card to start. Checkout does collect a card, and it sets the paid trial to the remaining days rather than granting a fresh 14, so it is one continuous trial rather than two. If the trial ends without checkout, the workspace pauses: plan-gated features lock and gated routes return a structured error. Nothing is deleted, and subscribing picks up where it left off.</dd></dl>]]></content:encoded>
      <dc:creator>Raajshekhar Rajan</dc:creator>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
      <atom:updated>2026-10-10T00:00:00.000Z</atom:updated>
      <category>comparisons</category>
    </item>
  </channel>
</rss>
