What the HR team is asking for
HR opens Claude and asks who reports to whom, which hires start on the first, how many people are on leave in March. The answers sit in Rippling. Nobody in the room wants a model one token away from running payroll. Rippling MCP access for HR team members has one shape that survives review: reads shared, the termination and payroll-run tools blocked outright, and an audit trail that shows nobody ran one.
MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps Elaichi serves Rippling's tools through one organization-wide MCP endpoint, POST /mcp, behind OAuth (the sign-in flow that hands a client a scoped grant instead of a password). Claude is pointed at that single address through its own admin console. There are no per-toolbox URLs and no tokens pasted into a config file. Rippling is one of 450+ connectors Elaichi authors, maintains and serves from its own infrastructure.
How to scope Rippling MCP access for HR team members
Connect Rippling once, give the HR people one role, then write block rules against that role. The order matters, because a rule written before the connection exists has nothing to pin against.
- Connect the Rippling account. 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
needs_reauthrather than failing quietly. - Share the connection with the HR team, with
use. Sharing is one building block: a grant ofview,useoreditto a user, a team or the whole organization. A member sees only what they own or what was explicitly shared with them, and no organization-level permission widens that listing, owners and admins included. - Check the role. Every member carries exactly one role, enforced by a unique index, so the HR role is a complete persona rather than a bolt-on. Members need
tool:execute, which gates the whole endpoint ahead of every other check. Without it,tools/listcomes back empty and a call returns an in-band error naming the permission. - Write the restrictions. A restriction is a rule about which connectors and which individual tools a target may reach. Targets are
roleoruseronly. restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything: the default is the absence of any rule, which means allow-all. - Point Claude at
POST /mcpfrom the Claude admin console and have the HR team sign in.
If the HR group already exists in your identity provider, SCIM v2 can provision the members and map that group to the HR role, so step 3 stops being a manual task.
One caution on step 4. A user-targeted rule replaces role rules entirely instead of layering on top of them. If you later write a rule for one HR manager, the role's blocks stop applying to that person. Write the exception as a copy of the role rules plus the change, or leave it at the role.
Why block the payroll tools instead of allowlisting the reads
Block rules are the right shape here because the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Add one allow rule naming three read tools and every other tool on the connector disappears, including the reads you forgot. An allow rule naming nothing denies everything, which is the strictest rule the system can express and a real trap.
Blocks and allows both union within the winning layer, and blocks always beat allows. A block list is therefore additive and safe to extend as the catalog grows.
There is a second reason for HR specifically. A block matches on the tool name or on the pinned canonical operation, while an allow matches on the pinned operation only. A tool's advertised name can be changed by whoever edits the connector's documentation, so the name is a token the governed party controls. Blocking catches both the label and the operation underneath it. The name versus pinned operation asymmetry is worth reading before you write a long rule set.
The OAuth scope ladder is a second constraint on the same call. A connected tool whose method is a delete needs mcp:destructive, and a tool classified forbidden is reachable under no scope at all.
Does HR see the blocked tools in the Claude tool list?
No. Enforcement runs at four points against the same resolver, browse, connect, advertise and execute, plus a final check on the fully substituted outbound URL, plus a final check on the fully-substituted outbound URL. A tool withheld by a restriction is never advertised, so the model does not know it exists and cannot be talked into asking for it.
The list HR does see is shorter than the raw tool count for a second reason. Past a threshold of 30 tools, the connected tools collapse behind two meta-tools, search_tools and execute_tool. The threshold counts catalog operations and connected tools together, and the control-plane catalog alone is dozens of operations, so one connected app is normally enough to trip it. Collapse is the normal case.
Two details keep this honest. Tools withheld by a restriction are excluded from the count, because they were handed to nobody. And execute_tool is only a naming indirection: it unwraps to the same name and arguments and falls through the identical gates, with no separate execution path and no privilege in it.
Search ranking is purely lexical, over tool name, description and connector label, with a relevance floor. A tool has to account for at least half the query's own IDF-weighted mass to be returned at all. 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 reasoning behind the floor is written up separately.
Freezing the arguments HR should not get to choose
Frozen parameters fix an argument before the model ever sees it. They are a per-entry map over the tool's flattened argument space, with two effects. Frozen keys are stripped from the advertised schema, so the model cannot supply them. Frozen values are merged over caller arguments at execution, so passing the key anyway cannot un-freeze it.
The full precedence is entry defaults, then caller and model arguments, then frozen parameters. For an HR setup the usual use is a filter you want held constant on every read, so a question about one population cannot quietly return another. Freeze it once on the toolbox entry, which is the saved set of connected tools a client is pointed at, and the model only ever sees the arguments you left open.
Proving nobody ran a termination or payroll tool
The audit trail records one entry per tool-call attempt, succeeded or failed, and both name the account. The recorded connection is the account actually reached, taken from the execution rather than from the intent. That is the first thing you want when an unexpected change shows up in a second Rippling environment.
Per call, the record carries the operation and tool, the connection, the classification, whether it was approved, the outcome, and an error code only. Argument names and counts are logged. Argument values never are.
actor_kind is a field, not an inference. Its values include user, system, staff, scim, api_token and ai_assistant, so whether an action was taken by an AI is recorded at the point of action rather than guessed later from a user agent. That turns "did an assistant run payroll" into a filter instead of an argument.
Two design details matter when the log leaves the product. There is one log tenant per organization, enforced in the type system rather than by a WHERE clause, because a dropped clause leaks while a wrong tenant simply returns nothing. And two error strings exist per failed call. The one returned to the caller comes from the third party's response body. The one written to the trail is never derived from the request or the response, because audit records are org-visible and get fanned out to whatever SIEM you configure.
To produce the evidence: filter the trail by connection, action kind and time range. It is append-only, newest-first, cursor-paginated and filterable by free text, category and actor. A departed member renders as "Former member" rather than vanishing. Give the reviewer the Auditor role, a free read-only seat that lacks tool:execute, so no tool call is possible from it. Export forwards the trail to your own destination; Datadog is implemented, while Splunk HEC and Microsoft Sentinel are accepted but not yet delivering. The trail is eventually consistent, so pull the report after the fact rather than mid-call.
Does the employee data stay in the EU?
It depends on the region, and the region is chosen once at organization creation from eu, us and apac. The eu and us regions are hard residency, a jurisdiction-pinned store where compute and storage both stay put. The apac region is a placement hint only. It is best-effort, and not a residency guarantee, so do not write it into a works council commitment.
Region also selects which regional log instance the organization's audit trail lands in. For an HR rollout that matters as much as the connection itself, because the trail carries employee-adjacent metadata even though it never carries argument values.
What this setup does not prove
The restriction governs the MCP path and nothing else. Someone who signs into Rippling's own web application 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.
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: permissions per operation, the forbidden classification, output redaction, OAuth scope limits and full audit logging.
Timing is the fact most often stated wrongly. A role or restriction change takes effect within about two minutes, through a 60 second cache plus edge propagation, on MCP, console and REST alike. Only grant revocation, member removal and suspension are effective on the next call. Tell the HR lead two minutes.
When a control plane is not worth it yet
If you have one HR person, one Rippling login and no other connected app, none of this earns its maintenance. A shared browser session managed in a password manager is a smaller problem than a control plane nobody owns. The same holds when the AI client only needs a read-only handbook and touches nothing that can change state.
The case for holding off on a gateway is real, and worth reading before a rollout rather than after. Governance starts paying when a second system joins, when more than one person holds the credential, or when someone outside HR has to be able to answer what the assistant did.
The day someone leaves the HR team
removing or suspending a member revokes every live grant in the same transaction as the membership change, and revoked_at is re-read from the organization store on every single call. For removal and suspension, the next call fails.
Removal also runs a preflight. Personal connections referenced by a toolbox entry must be resolved first, transferred to the organization, a team or another member, or deleted, or the removal is refused. Unreferenced personal connections are cleaned up. A private connection is not transferable at all: a credential only its owner could ever use does not become somebody else's because its owner left. Delegated toolbox entries surface as a non-blocking warning, and re-pinning is the fix rather than a credential decision.
A move sideways, from HR into a narrower role, is a role change. Budget about two minutes for it rather than the next call.
For the equivalent setup on the revenue side, see how a sales team gets scoped Salesforce access in ChatGPT. For the harder version of the same offboarding question, read the contractor access walkthrough. The full catalog is at /connectors/, and the other eleven teams are mapped at /use-cases/.