{"templateId":"markdown","sharedDataIds":{},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Fin Operator MCP","projectTitle":"Intercom and Fin Developer Platform","description":"Faster resolutions, higher CSAT, and lighter support volumes with the only platform to combine the power of automation and human customer support.","siteUrl":"https://developers.intercom.com","image":"/assets/og-image.9c9ef3a6cedbceee0e1d52fae2ffcce97f5a189639cf24e473331da9ad02c5f8.b1bff462.png"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"fin-operator-mcp","__idx":0},"children":["Fin Operator MCP"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"'Fin Operator MCP' is currently in closed beta"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Access is enabled per workspace. Please reach out to your accounts team to discuss access and tailored, hands-on support."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Operator is Fin's internal AI agent. The Fin Operator MCP server lets an AI client ask Operator to do work inside your Fin workspace and read the answers back, without you moving between the two products."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Availability"},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["US-hosted workspaces only. EU-hosted workspaces are not supported yet."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Claude (claude.ai, Claude Desktop, Claude Code, and Claude Mobile once connected) is the only supported client at the moment."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"what-it-does","__idx":1},"children":["What it does"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your client asks Operator something in plain language, Operator does the work, and hands back the answer plus any changes it suggests. Operator already knows your workspace, so you can:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ask why Fin missed resolutions over a period"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Investigate a specific conversation"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ask Operator to propose configuration changes"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Proposed changes are reviewed and applied from the client, without leaving it."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Reviewing proposals"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Proposals are not applied until ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apply_proposals"]}," is called. Review each one with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_proposal_details"]}," before you apply it — some changes cannot be undone."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-it-works","__idx":2},"children":["How it works"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Fin hosts a remote MCP server that follows the authenticated remote MCP specification (",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization"},"children":["docs"]},"), with Dynamic Client Registration and PKCE."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Connection URL:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://fin-operator-mcp.intercom.workers.dev/mcp"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Operator turns run asynchronously: a request returns as soon as Operator accepts the work, and the client collects the answer with a later call."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When a client calls a tool:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The client connects to the Fin Operator MCP server and completes the OAuth flow"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["We check if the workspace is enabled for the beta and that the teammate has permission to use Operator"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The tool runs as that teammate, inside that workspace"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Answers, and any proposed changes, are returned to the client"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"setting-things-up","__idx":3},"children":["Setting things up"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"claudeai-and-claude-desktop","__idx":4},"children":["claude.ai and Claude Desktop"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Who does which step"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["On Claude Team and Enterprise plans, only an Owner or Primary Owner can add a custom connector, and they only need to do it once for the organization. If you are not an owner, ask yours to run steps 1–3 below, then start from step 4 yourself. On individual plans you do all the steps."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Adding the connector — an organization owner on Team and Enterprise plans, or you on an individual plan:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Open Claude's ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Connectors"]}," settings and choose ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Add custom connector"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Give the connector a name, e.g. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Fin Operator"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Paste the connection URL: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://fin-operator-mcp.intercom.workers.dev/mcp"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Connecting to it — every person who wants to use Operator does this for themselves:"]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":4},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Choose ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Connect"]}," on the connector. Claude registers itself with the server and sends you to an authentication page."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Sign in to your Fin workspace if you are not already, and approve the consent screen. It names the workspace you are connecting and the two permissions being granted (see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#oauth-scopes"},"children":["OAuth scopes"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You are returned to Claude and the connector shows as connected, listing the six Operator tools."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each person authorizes as their own teammate profile, so the connector being shared does not mean the access is."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The same connection then works from Claude Mobile — connectors are attached to your Claude account, not to one device, so there is nothing to set up again there."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"claude-code","__idx":5},"children":["Claude Code"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"claude mcp add --transport http fin-operator https://fin-operator-mcp.intercom.workers.dev/mcp\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Then run ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/mcp"]},", select ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fin-operator"]},", choose ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authenticate"]},", and approve the Intercom consent screen."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By default the server is added in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["local"]}," scope: available to you throughout the project you ran the command in, but not in your other projects. To make it available in every project, add it with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user"]}," scope instead:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"claude mcp add --scope user --transport http fin-operator https://fin-operator-mcp.intercom.workers.dev/mcp\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Corporate allowlists"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If your organization restricts which connectors Claude may use, ask whoever administers it to allow ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://fin-operator-mcp.intercom.workers.dev/mcp"]},". On Claude Team and Enterprise plans this is an organization owner action."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"available-tools","__idx":6},"children":["Available tools"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Fin Operator MCP server provides ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["6 tools"]},"."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"send_operator_message","__idx":7},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["send_operator_message"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Send a message to Operator."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Returns as soon as Operator accepts the turn — it does ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["not"]}," wait for the answer. The turn keeps running in Intercom; collect the answer with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," using the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]}," from the response. Once a turn has been accepted, never re-send the same message to retry."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]}," (required): the message to send to Operator"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]},": continue an existing conversation. Omit to start a new chat. Use one chat per topic."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Status in the response envelope:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["working"]},": Operator accepted the turn and is running it. Turns normally take one to three minutes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},": the error text opens with a code (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rate_limited"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_busy"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["usage_limit"]},", …) when the turn definitively never started. A bare ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error:"]}," means the turn may have started anyway — check the chat in Intercom via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_url"]}," before retrying."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"get_operator_response","__idx":8},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["get_operator_response"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Read the latest response from an Operator chat. Never starts new work and never waits — it returns the chat's current state immediately."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]}," (required): the chat to read, which is the UUID at the end of an Operator chat URL"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Status in the response envelope:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["complete"]},": the latest turn finished; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["answer_text"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tool_outputs"]}," are final"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["working"]},": the turn is still running — check again shortly"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["needs_approval_in_ui"]},": Operator is waiting for teammate input or confirmation in Intercom (open ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_url"]}," to respond)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},": the turn failed — check the chat in Intercom via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_url"]}," rather than calling again"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Proposals are returned only once the turn is known to have stopped writing. Until then ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals"]}," is empty and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals_withheld"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},": an empty array does not mean the turn proposed nothing."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"get_proposal_details","__idx":9},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["get_proposal_details"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Show what a pending proposal would change, as a diff, plus anything blocking it. Read-only, and costs no Operator credits."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]}," (required): the chat whose proposals to describe"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposal_ids"]},": proposals to describe. Omit to describe every pending proposal on the chat."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["detail"]},": ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["summary"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["diff"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["full"]},". Omit to get ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["diff"]}," for a single proposal and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["summary"]}," for several."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A chat with more than 20 pending proposals is described 20 at a time."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"apply_proposals","__idx":10},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["apply_proposals"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apply Operator proposals to the workspace's live configuration. This creates, updates or deletes real objects, and some of it cannot be undone. It runs the same code path as the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Apply"]}," button in Intercom."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]}," (required): the chat whose proposals to apply"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals"]}," (required): up to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["5"]}," proposals per call, each with:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposal_id"]}," (required): from the response envelope's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals"]}," array"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apply_mode"]},": one of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apply"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["draft"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["release"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["publish"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["destroy"]},". Omit to apply in the proposal's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["default_apply_mode"]}," — a new entity lands as a draft, and an edit keeps the entity's publication state. Set it only when a human explicitly chose a mode, and only to a mode listed in that proposal's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["supported_apply_modes"]},"."]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"reject_proposals","__idx":11},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["reject_proposals"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Discard proposals. Nothing in the workspace changes."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]}," (required): the chat whose proposals to reject"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposal_ids"]}," (required): up to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["20"]}," proposal IDs per call"]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"ping","__idx":12},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["ping"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Connectivity check. Returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pong"]}," with the authenticated workspace and teammate."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]},": optional message to echo back"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"tool-annotations","__idx":13},"children":["Tool annotations"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The five tools that do work are published with MCP ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://modelcontextprotocol.io/specification/2026-07-28/schema#toolannotations"},"children":["tool annotations"]}," — hints that tell the client how careful it should be with a tool, before it ever calls it. Claude uses them to decide what it can run freely, what it should confirm with you, and what to show you first. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ping"]}," carries none: it only reports who you are connected as."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Tool"},"children":["Tool ",{"$$mdtype":"Tag","name":"img","attributes":{"width":"420/"},"children":[]}]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Read‑only"},"children":["Read‑only"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Destructive"},"children":["Destructive"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Idempotent"},"children":["Idempotent"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Open‑world"},"children":["Open‑world"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send_operator_message"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_proposal_details"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apply_proposals"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["true"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reject_proposals"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["false"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The columns are the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["readOnlyHint"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["destructiveHint"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["idempotentHint"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["openWorldHint"]}," fields of each tool's annotations."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["What the hints are saying:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_proposal_details"]}," are read-only and idempotent."]}," Calling them again has no additional effect, so Claude can reach for them without asking you. This is deliberate: it makes showing you a diff cheaper than applying a change. Idempotent does not mean the answer is fixed — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," reports the chat's current state, so the status and proposals do change as a turn progresses."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apply_proposals"]}," is destructive and open-world."]}," It writes to live workspace configuration and some of it cannot be undone, so clients that gate on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["destructiveHint"]}," will ask you to confirm before it runs. Treat a client that applies without asking as misconfigured."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send_operator_message"]}," is also marked destructive and open-world."]}," It does not write configuration itself, but it starts an Operator turn that acts on your workspace and consumes Operator usage, so it is not a free retry. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["openWorldHint"]}," is what tells the client the effect reaches outside its own state."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reject_proposals"]}," is neither read-only nor destructive."]}," Discarding a suggestion changes nothing in the workspace, so it needs no confirmation, but it is not read-only either — the proposal is gone afterwards."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["readOnlyHint"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["destructiveHint"]}," are separate on purpose: applying a change and discarding one are different decisions, which is why the two are separate tools rather than one tool with a flag."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Annotations are hints, not enforcement. The authorization described in ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#how-permissions-work"},"children":["How permissions work"]}," is what actually decides whether a call is allowed."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"a-typical-workflow","__idx":14},"children":["A typical workflow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["1. Ask Operator something"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"send_operator_message\",\n  \"arguments\": {\n    \"message\": \"Why did Fin's resolution rate drop last week?\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response carries ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status: \"working\""]}," and a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_id"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["2. Collect the answer"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"get_operator_response\",\n  \"arguments\": { \"chat_id\": \"b0c1d2e3-...\" }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Turns normally take one to three minutes, so do not call this back-to-back. While the status is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["working"]},", do something else and check again — repeated immediate calls are rate limited."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["3. Review anything Operator proposed"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"get_proposal_details\",\n  \"arguments\": { \"chat_id\": \"b0c1d2e3-...\", \"detail\": \"diff\" }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["4. Apply or reject"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once a human has reviewed a specific proposal and confirmed it:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"apply_proposals\",\n  \"arguments\": {\n    \"chat_id\": \"b0c1d2e3-...\",\n    \"proposals\": [{ \"proposal_id\": \"p_123\" }]\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Quote numbers and data from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tool_outputs"]}," verbatim rather than re-deriving them."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-permissions-work","__idx":15},"children":["How permissions work"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once a workspace is enabled for the beta, teammate-level permissions apply through the MCP in exactly the same way they do for Operator in the product. Any teammate who can use Operator in Intercom can use it through the MCP too: there is nothing extra to grant them and no seat upgrade involved. A refused call names the specific permission required."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Concretely, every tool call is authorized on:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The workspace having Operator, and being enabled for the Fin Operator MCP beta on top of it — this gate is per workspace, not per teammate, and a teammate with Operator access in a workspace that is not enabled for the beta is still refused"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A teammate-scoped token — the OAuth flow must be completed by a teammate"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The teammate's ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Operator access"]}," permission in that workspace"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Completing the OAuth flow on its own grants nothing. A teammate in a workspace that is not in the beta can hold a valid connection and still get nothing back."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oauth-scopes","__idx":16},"children":["OAuth scopes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The consent screen asks for two scopes:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use Fin Operator"]}," — permission to send work to Operator. Every tool call is authorized on this scope; a connection without it is refused before anything runs."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Read one admin"]}," — lets the server read your teammate record once, while you are connecting, to record who authorized. Tool calls are attributed to you by the connection itself, not by this scope."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Neither scope grants direct access to conversation or contact data. Operator reads what it needs inside Intercom under the connecting teammate's own permissions."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use Fin Operator"]}," is a private scope: it is only available to the app packages Intercom ships for Operator and cannot be requested by an app you build in the Developer Hub."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"rate-limits","__idx":17},"children":["Rate limits"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Requests are limited to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["60 per minute per token"]},", shared across all six tools: polling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," spends the same budget as reading proposal details. Ordinary interactive use sits well below this."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A throttled call is returned as a rate limit, telling the client to slow down rather than failing opaquely. The usual cause is polling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," in a tight loop."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Operator's own usage limits also apply, and are reported as a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["usage_limit"]}," error code from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send_operator_message"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"debugging-and-troubleshooting","__idx":18},"children":["Debugging and troubleshooting"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Check the connection works"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ping"]},". It returns the workspace and teammate the connection is authenticated as, which is the quickest way to confirm you are connected to the workspace you expect."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Common problems"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["\"Operator MCP is not enabled for this workspace\""]}," — the workspace is not in the beta. Contact your accounts team."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["Missing permission errors"]}," — the teammate needs Operator access in that workspace, granted the same way as for Operator in the Intercom UI."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["A turn seems stuck"]}," — open ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["chat_url"]}," from the response and look at the chat in Intercom. Do not re-send the message."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["Empty ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals"]}," array"]}," — check ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["proposals_withheld"]},". If it is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},", the turn is still writing; call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_operator_response"]}," again."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["Authentication problems in Claude Code"]}," — re-run ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/mcp"]},", select ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fin-operator"]},", and authenticate again."]}]}]},"headings":[{"value":"Fin Operator MCP","id":"fin-operator-mcp","depth":1},{"value":"What it does","id":"what-it-does","depth":2},{"value":"How it works","id":"how-it-works","depth":2},{"value":"Setting things up","id":"setting-things-up","depth":2},{"value":"claude.ai and Claude Desktop","id":"claudeai-and-claude-desktop","depth":3},{"value":"Claude Code","id":"claude-code","depth":3},{"value":"Available tools","id":"available-tools","depth":2},{"value":"send_operator_message","id":"send_operator_message","depth":4},{"value":"get_operator_response","id":"get_operator_response","depth":4},{"value":"get_proposal_details","id":"get_proposal_details","depth":4},{"value":"apply_proposals","id":"apply_proposals","depth":4},{"value":"reject_proposals","id":"reject_proposals","depth":4},{"value":"ping","id":"ping","depth":4},{"value":"Tool annotations","id":"tool-annotations","depth":2},{"value":"A typical workflow","id":"a-typical-workflow","depth":2},{"value":"How permissions work","id":"how-permissions-work","depth":2},{"value":"OAuth scopes","id":"oauth-scopes","depth":3},{"value":"Rate limits","id":"rate-limits","depth":2},{"value":"Debugging and troubleshooting","id":"debugging-and-troubleshooting","depth":2}],"frontmatter":{"excludeFromSearch":true,"title":"Fin Operator MCP","description":"Connect Claude to Operator, Fin's internal AI agent, over the Model Context Protocol","seo":{"title":"Fin Operator MCP"}},"lastModified":"2026-08-14T10:29:44.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/guides/fin-operator-mcp","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}