Skip to main content

Building a MCP server that lets agents communicate in their native language: code.

A purple hub-and-spoke diagram showing a central app logo connected to six AI tool icons on a dark magenta background.

We launched today, a new capability that allows any AI tool to take action in Rippling. Beyond just fetching records, it also enables agents to perform complex tasks and execute code to get those tasks done.

Building a poorly designed MCP server is easy. Just ask a coding agent to read your API docs, and you’ll have one running in minutes. And many companies did exactly that: they wrapped their existing APIs as tools and announced their new MCP server. But when we tested this approach, we quickly realized that the architecture was all wrong for the kind of work that people actually want their agents to perform on their behalf.

APIs were designed and built for human developers. A good API exposes hundreds of endpoints and thousands of fields and parameters that are broad on purpose so a developer can assess what is available to then write code that only uses what they need. The cost of all that surface area is paid once at build time.

Agents are different. They figure out how to solve a problem each time they go to solve it, like groundhog day. They do that by reading instructions and tool definitions. So when APIs are wrapped as MCP tools, the agent is drowned in context every time it uses the MCP. The agent can’t just request what it needs. For example, if asked the simple question “is anyone on my team out of the office today,” it has to muddle through a lot of extraneous data in search of the specific endpoints it needs to answer the question: managers, employees, leave types, leave requests, and more. All this to ultimately just say, “No, not today.”

That is an enormous amount of work for a one-word answer, and the agent pays for it on every request. You don’t realize how expensive poor MCP design is until your AI bill arrives at the end of the month.

We built our MCP to avoid this problem. Rather than force agents to speak in APIs built for human software developers, we let them communicate in their native language: code. The same task that once drowned an agent in context now costs 98% fewer tokens.

Our first use case

For our own Rippling employees, one of the most popular apps internally is Product Launch Tracker ( the “PLT”): a Rippling Custom App built to let the R&D department track and communicate product roadmap and timeline updates. Keeping PLT up-to-date is crucial to our company’s ability to execute across teams. The request to make the PLT available in our employees’ AI tools became one of the top feature requests across all departments, so we used it as the first use case to design the Rippling MCP.

Consider this prompt:

“I’m preparing for a launch review meeting today. Which product launches owned by my team need attention in the next 30 days? Consider launch date, confidence, development stage, and whether the owner is out today. Rank them by urgency.”

To answer this question, an agent must:

  • Find out who I am.

  • Find my direct reports.

  • Find the product launches each report owns that are due within 30 days.

  • Retrieve each launch’s target date, confidence, development stage, and last update.

  • Check whether each owner is out today.

  • Join the results, flag urgency, and rank the launches.

Designs we considered

We first had to decide what the agent should see. We considered three designs:

  • One MCP tool per API. APIs already work for human developers, so exposing each as a tool is the simplest design. But every tool definition consumes session context. Dependent calls require separate model turns, and each wrong call wastes one. Progressive disclosure can defer tool definitions, but it does not shrink response payloads. One large JSON response can consume more context than the entire tool catalog. Rippling has 238 APIs spanning the platform including HR, IT, Time, and Payroll. 58 new endpoints were added so far in 2026 alone. Given our scale of APIs, we ruled this option out.

  • Workflows exposed as MCP tools. A workflow bundles several APIs into a single tool, reducing round trips for a given task. For example, one workflow could fetch a team’s vacation balances given its manager. But when no workflow matches the request, the agent must combine workflows or fail. Supporting more use cases means adding more tools, eventually recreating the tool-bloat problem. At Rippling’s breadth, this makes it nearly impossible to predict every workflow in advance. Because of this, we ruled out workflows as the primary interface.

  • Code Mode. Cloudflare popularized in September 2025 and introduced a in February 2026. In Cloudflare’s implementation, the agent uses a search tool to find available API functions, and an execute tool to run a program that calls them. This was the obvious fit for Rippling. Our products share a data and permissions model, so useful workflows often cross product boundaries. Code Mode lets the agent compose those capabilities in ways we could not predict in advance while keeping intermediate API responses out of the model’s context.

How we implemented Code Mode

Today, the Rippling MCP exposes one code tool. Its description lists the typed codemode.* functions the connected user is authorized to call. The model writes a JavaScript program against those functions, and the entire program runs inside a fresh Cloudflare Dynamic Worker isolate, where it chains calls and processes intermediate data. This keeps the number of MCP tool calls fixed. More importantly, the intermediate responses remain inside the isolate during execution which means only the program’s result returns to the model.

While Cloudflare’s Code Mode implementation supports a search and execute tool, we found that agents performed better using just one code tool with a MCP server supporting 31 functions. A search tool becomes valuable as the function catalog grows and we will add one when the catalog is large enough to warrant it.

Using the same example prompt from above, the following code is generated by GPT-5.6 Sol on Medium: “I’m preparing for a launch review meeting today. Which product launches owned by my team need attention in the next 30 days? Consider launch date, confidence, development stage, and whether the owner is out today. Rank them by urgency.”

It hands back only the answer:

Code Mode lets the agent customize what the Rippling MCP returns. The first benefit we see from the response is the ability to create derived and calculated fields. Fields such as “team_size” and “upcoming_launches” and “owners_out_today” are all fields the agent invented through writing code.

The second benefit is efficiency. The MCP server returned a payload that equates to 204 tokens (based on OpenAI’s tiktoken library using the o200k_base encoding). To get the same answer using the one tool per API design, it costs 11,071 tokens. Code mode performs the same work using 98% fewer tokens.

One MCP Tool per API

Code Mode

Model turns (call + result)

22

1

Function executions

22

22

Records returned to the model

57

3

Field value pairs returned to the model

776

13

Payload returned to the model (bytes)

32,207

727

Payload returned to the model (tokens)

11,071

204

A product for agents built by agents

API endpoints and fields should have descriptions, but many don’t. While developers can work around it, agents cannot with MCPs. The MCP server instructions and tool definitions are not optional docs, they are the product. And they are what make a great MCP server.

We started out writing the instructions and tool definitions by tying it back to value proposition statements that could be understood by a human developer. But having a human guess the best way to teach agents when to use the lookup_direct_reports function quickly did not work. The MCP server is a product built for agents to consume, so we trusted agents to write the server instructions and tool definitions.

We treated our external text surfaces like code and built a mocked end-to-end evaluation harness. We initially created a golden data set of 50+ test cases. Each case pairs a user prompt with a reference answer, stubbed API responses, and the expected code to execute.

For example:

Prompt: What is the average tenure of Michael Mitchell's team?

Expected answer: Michael Mitchell has one direct report; average team tenure is 7.25 years (Tammy Smith, start date 2019-04-01).

Expected code:

Based on the AI clients our customers most commonly use, we created a text matrix by client, model, and reasoning setting.

Harness

Model

Reasoning

Claude

Haiku 4.5

medium

Claude

Haiku 4.5

high

Claude

Sonnet 4.6

medium

Claude

Sonnet 4.6

high

Claude

Opus 4.8

medium

Claude

Opus 4.8

high

Codex

GPT 5.4

medium

Codex

GPT 5.4

high

Codex

GPT 5.4 Mini

medium

Codex

GPT 5.4 Mini

high

Codex

GPT 5.5

medium

Codex

GPT 5.5

high

Cursor

Composer 2.5

n/a

We ran every case in a clean context. The agent received nothing else except its baseline system prompt, our MCP server instructions, and our tool description. Because the API responses were stubbed, every agent faced the same scenario with the same data. We measured how well the agent used our single code tool with mock servers.

We built a judge to score each run. For every case, the judge used the reference answer, the stubbed responses the agent should have used, and the agent’s full transcript to assign a score. Each agent’s score was out of 100 across four categories:

  • Function selection: Did the agent choose the right codemode.* functions?

  • Function path: Did the agent choose the most optimal path to sequence function calls?

  • Invocation correctness: Did the generated JavaScript program run and pass the right values to the right parameters?

  • Final answer: Was the final result actually correct?

The performance results were passed to an optimizer LLM. It triaged the failures, proposed edits to the text, reran evals, and measured what changes improved performance. We ran this in a loop. Changes that lifted scores across all harness, model, and reasoning configurations we kept. Changes that only helped one model, we discarded.

As our performance scores began to improve, our eval harness exposed operational failures. The agent would write a semantically correct program, but the program would exceed the sandbox’s 60-second execution budget and timeout. For example, one eval prompted the agent to save five meeting action items into a new custom object. The program it wrote was correct (create the object, read its schema, write five custom records), but it chained every call in sequence:

While every call was valid, the plan ran past the 60 second timeout. Nothing told the agent how much time each function costs, so it guessed wrong. So we put p95 latency in every function description and taught the agent the math: sequential adds, parallel costs only the slowest call, 60s is the ceiling. Now it runs the five writes in parallel: 47.5 seconds collapses to 9.5 seconds, and splits across calls when a job won't fit. After we exposed p95 latency per function, production sandbox timeouts dropped by 70%.

We also kept seeing poor performance using Claude. Our eval harness ultimately surfaced something no wording could fix: clients don't read the text the same way. Notably, Claude Code only looked at the first 2,048 characters of our tool description when deciding whether to use the tool at all. Our full description ran past the 2KB limit. The routing rules that made programs correct were present and accurate, but completely invisible at the moment Claude decided whether Rippling was relevant. Its evals kept failing.

We did not replace the full description with shorthand. Instead, using our eval harness we were able to generate a compressed 2,000 character action header before the detailed guidance in our code tool. It expresses the most important capabilities, constraints, and state transitions with function names, arrows, and operators rather than prose. A few examples include:

Detailed guidance (prose)

Action header (compressed)

Use lookup_me or lookup_person as the starting profile, then follow the returned manager ID with lookup_person until the manager is missing; a missing manager means the chain ends there.

reporting = me → lookup_person til mgr missing

To request time off, resolve the requester with lookup_me, fetch their leave types and current balance, then call request_time_off with worker_id set to the requester's own id — check the balance first, never pass a literal worker_id.

lookup_me → search_leave_types → lookup_time_off_balance({worker_id:me.id}) → request_time_off({worker_id:me.id}); balance first

Before creating a draft hire, resolve the department, manager, location, and employment type in the same call; search_work_locations returns locations, not employees, so pass the returned location_id, never a raw location string, and never hardcode IDs.

create_draft_hire: same call resolve dept/manager/location/type; search_work_locations → location_id, no raw location; no hardcoded IDs

Shipping the action header improved Claude Code performance by 41% while not impacting Codex or Cursor.

Letting agents write code safely

Letting an agent write and run its own code against your company's system of record should give you pause. It is arbitrary code, generated on the fly, touching the same HR, IT, Finance, and people data everything else in Rippling depends on. That is why we designed the model to have room to work, but no authority of its own.

Each program runs inside an isolated Cloudflare Worker with no credentials and no network access. It cannot call out to the internet, read a secret, or touch a Rippling system directly. The only thing it can do is call the specific codemode.* functions we hand it for that request.

Which functions it gets is decided before a single line runs. Rippling reads the connected user's own policy and grants the isolate only the functions that person's role is allowed to call. If that permission set is missing or invalid, nothing runs at all. Being handed a function is not the same as bypassing a check. When the program calls one, the request leaves the isolate to a host that holds the token, and Rippling enforces the same scopes and field-level permissions that govern every other surface.

We also control how hard an agent can push. Because agent traffic is machine-scale and bursty, the server runs at the edge, where rate limiting and abuse control are applied, and every program runs under a hard sixty-second budget.

The result is a simple division of labor: the model proposes the work, and Rippling decides what is allowed. It is the same Object Graph permission model you already trust, now applied to the agent acting on your behalf.

The work ahead

An efficient and effective framework for the Rippling MCP Server lays the foundation for a lot of capability expansion in the future. As we add more functions to our MCP catalog, the same design lets agents take on more of the work that actually runs a company.

You can try the Rippling MCP with your AI tool of choice here:

Disclaimer

Rippling and its affiliates do not provide tax, accounting, or legal advice. This material has been prepared for informational purposes only, and is not intended to provide or be relied on for tax, accounting, or legal advice. You should consult your own tax, accounting, and legal advisors before engaging in any related activities or transactions.

Author

A smiling man wearing a gray blazer and white shirt, standing in front of a red brick wall outdoors.

Callen Raveret

Product Lead Platform & Ecosystem

Explore more

Rippling AI Governance hub connecting multiple app integrations like Google, Slack, and GitHub with employee data fields below.

Introducing Rippling AI Governance: Get your AI house in order

Rippling AI Governance connects AI activity to the employee graph, helping companies control AI usage and spend, secure access to models and tools, and manage agent identity, all in one platform.

Three keyboard keys with lightning bolt icons on purple background, center key glowing pink with circuit lines.

Corroding the Monolith: Building a Rust-Native MongoDB Client for Python with AI-First Development

Discover how Comyar leveraged Rust, PyO3, and an AI-first workflow to build mongoxide, a native MongoDB client for Python.

Abstract illustration of a cube

How Rippling learned to work differently

Discover how Rippling’s Head of AI created a “treat it as your intern” policy that increased adoption for organization-level wins.

Hand holding a floating code tile on burgundy.

Code ownership at Rippling

Rippling built a custom service catalog to boost reliability for a scaling engineering team. Dive into this innovative approach to code ownership.

Orange cube at the center of a purple three-dimensional network grid.

Rippling's Gunicorn pre-fork journey: 70%+ memory savings and a 30% cost reduction

Rippling’s engineering team used a Gunicorn pre-fork strategy to cut memory use by 70% and reduce costs by 30% — improving speed, reliability, and scalability.

AI Spend Console dashboard showing metrics, a bar chart of monthly AI spend by vendor, and a scatter plot of AI spend vs. PR change rate.

From unchecked AI spend to complete control: How Rippling built AI Spend Console

AI Spend Console gives CFOs and CTOs a clear view of AI spend, connects it to business outcomes, and governs the use of approved LLMs.

AI for IT Teams: 4 Workflows That Actually Save Time (With Prompts)

AI for IT Teams: 4 Workflows That Actually Save Time (With Prompts)

IT teams get the most from AI by mapping specific prompts to specific repeatable workflows. Here are four that actually work — with the prompts to run them.

Repeating pixelated hand cursor pattern on gray

Building Editors in React Applications

Learn how to build efficient and user-friendly editors in React applications with insights from Rippling's development team.