feat(mcp): add Rippling integration as a shimmed MCP preset#5
Open
aidenybai wants to merge 3 commits into
Open
feat(mcp): add Rippling integration as a shimmed MCP preset#5aidenybai wants to merge 3 commits into
aidenybai wants to merge 3 commits into
Conversation
Lets users add Rippling with `/mcp-add rippling <api-key>` and have it appear to the agent as `mcp_rippling_*` tools, indistinguishable from a real MCP server. Under the hood Pookie hosts the tools locally and calls Rippling's REST API directly — no MCP transport, no proxy server. The shim mechanism is generic: presets gain an optional `shim` field, and `tryRegister` / `openMcpTools` short-circuit to a local toolset builder for shim configs. Future built-in HR/finance/etc. integrations can drop into `server/mcp/shims/` without changing the agent or MCP wiring. Rippling tools cover companies, employees, leave types, leave balances, and leave requests (14 tools total). 401/403 from Rippling map to a structured tool error with regen instructions instead of leaking a stack trace.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c2be9bc. Configure here.
Hardens the shim path against context-window blowups, makes the agent guidance accurate for token-only presets, and adds the integration-glue tests the original PR was missing. - Project list endpoints (list_employees, list_employees_including_terminated, list_leave_requests) before handing the JSON to the model. Drops photo blobs, workSchedule, customFields, per-day breakdowns, and timestamp metadata — fields the agent rarely needs at list level and that can push a single call past 50k characters. - Trim the search subagent's view of the Rippling toolset: drop list_employees_including_terminated, list_leave_balances, and get_leave_balance from `searchTools`. The main agent can still call them when the user is explicit. - Map AbortController-driven timeouts to a structured tool error (`code: rippling_timeout`) instead of leaking "This operation was aborted" to the model. - System reminder now flags `authType: "token"` presets with a "(requires API key)" tag and the correct invocation (`/mcp-add rippling <api-key>`), so the agent stops telling users to run a command that immediately rejects them. - Replace the hard-coded `app.rippling.com/developer/apiKeys` URL with a stable Rippling developer docs link, captured in a single constant used by both the preset registry and the shim's error messages. - Warn admins when adding any shim preset at `--global` scope that the shared API key gives every workspace member visibility limited only by the key's own data scopes. - Extract `partitionShimConfigs` and `tryRegisterShim` into pure exported helpers, and cover them with tests for: alias resolution (rippling_finance), missing-token error path, fall-through for non-shim configs, and 401-on-validate. - Cleanup: hoist shared `RIPPLING_RESULT_SCHEMA`, drop unused `RipplingRequestError` interface, tighten `summarizeArrayLength` into `formatArrayOutput`.
Bugbot flagged that `RipplingShimValidationResult` (in rippling.ts) was structurally identical to `McpShimValidation` (in shims/index.ts). Two copies of the same shape risk drifting apart as the contract evolves. Extract `McpShim` and `McpShimValidation` into `shims/types.ts` so both the registry (`index.ts`) and individual shims (`rippling.ts`) import the single canonical definition. `index.ts` re-exports them so existing import sites keep working unchanged.
aidenybai
added a commit
that referenced
this pull request
May 7, 2026
Closes the four actionable findings from the review pass: #1 (medium) -- detection-source mismatch between auto-react and system reminder. The auto-react in handleSlackMessage previously only inspected [currentMessage, ...skippedMessages], so a uwu/owo/meow that arrived as a Redis-drained follow-up mid-turn (round 2+) flipped pet-mode on in the system reminder but never got its cat reaction. Auto-react bookkeeping now lives at the turn scope in handleSlackMessage with a single \`petAutoReacted\` flag and a \`tryPetAutoReact(candidates)\` helper called both on round 0 input AND after each Redis drain. To keep the messageId attached, drainFollowUps now returns the full QueuedFollowUp[] (text + messageId) instead of \`string[]\`; callers that only need text \`.map((f) => f.text)\`. The downstream followUpMessages -> system reminder pipeline is unchanged. #2 (low) -- belt-and-suspenders: findUwuTriggerMessage now filters out candidates with empty \`id\` so a malformed Slack message with text but no ts can't trigger a 400 from reactions.add. #5 (low) -- test coverage: resolveSlackEmojiShortcode now has cases for the bare cat emojis (🐱 → cat, 🐈 → cat2), skin-tone modifiers (👍🏻 / 👍🏿 → +1), and the bare-codepoint heart without its variation selector (\\u2764 → heart). #6 (low) -- tracing observability: stamp \`pookiebot.uwu_mode: true\` when the per-round detection lights up, plus \`pookiebot.uwu_trigger_message_id\` when the auto-react fires. Consistent with existing \`pookiebot.dropped_card\` etc. attributes. #7 (doc nit) -- the \`already_reacted\` comment now reflects Slack's exact-emoji semantics: that branch only fires when the SAME shortcode is already on the message, so reporting success there is genuinely correct (the user-facing reaction state matches what the model wanted). Tests: - thread-lock tests rewritten for the QueuedFollowUp[] return shape - agent-follow-ups mocks updated to mock objects with messageId - four new resolveSlackEmojiShortcode cases for #5 - 281 total tests passing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
ripplingMCP preset that the user adds with/mcp-add rippling <api-key>(same UX as Linear PAT, GitHub PAT, etc.) — Pookie validates the key againstGET /platform/api/companies/currentand reports the connected tool count.mcp_rippling_*tools that are indistinguishable from real MCP tools, but Pookie hosts them locally and calls Rippling's REST API directly — no MCP transport, no proxy server. 14 tools cover companies, employees, leave types/balances/requests.shimfield, andtryRegister/openMcpToolsshort-circuit to a local toolset builder for shim configs. Future built-in HR/finance/etc. integrations drop intoapps/api/server/mcp/shims/with zero changes to the agent or MCP wiring.What's where
apps/api/server/mcp/presets.ts—McpPreset.shim?: string,resolveShimName(...), plus theripplingpreset entry (token auth, search-tool list, regen URL).apps/api/server/mcp/shims/rippling-client.ts— bearer-auth REST client with timeout + structuredRipplingApiError+probeRipplingToken.apps/api/server/mcp/shims/rippling.ts—buildRipplingTools(token)andvalidateRipplingShim(token). 401/403 map to a structuredtoolErrwith regen instructions instead of leaking a stack.apps/api/server/mcp/shims/index.ts—resolveShim(name)registry.apps/api/server/mcp/client.ts— short-circuits intryRegisterandopenMcpToolswhen a config resolves to a shim.Tools exposed (
mcp_rippling_*)get_current_company,get_current_user,get_departments,get_work_locations,get_teams,get_levels,get_company_leave_types,get_custom_fields,list_employees,list_employees_including_terminated,get_employee,get_leave_balance,list_leave_balances,list_leave_requests.Test plan
pnpm typecheckcleanpnpm lintclean (0 warnings, 0 errors across 172 files)pnpm test— 229/229 pass (was 221 before; +8 new shim tests covering preset wiring, full toolset shape, URL/auth/pagination, 401 → tool-error mapping with regen instructions, query-param forwarding withoutundefinedstrings, andvalidateRipplingShimhappy-path + 401 path)/mcp-add rippling <key>in a real workspace, verify tool count appears in/mcp-listmcp_rippling_list_leave_requestsNote
Medium Risk
Adds a new token-based integration that calls an external HR API and changes MCP tool loading/registration flow to support shimmed servers, so errors or token handling could impact tool availability and data exposure (especially at global scope).
Overview
Adds a shim framework for MCP presets so some integrations can expose
mcp_<server>_*tools without opening an MCP transport:tryRegisternow validates shim tokens andopenMcpToolspartitions configs into shim vs transport, registering shim-built tools locally.Introduces a new Rippling preset as a token-based shim, including a REST client with timeout/error mapping and a 14-tool HR/leave toolset (with model-output compaction for large list responses) plus token probing/validation.
Updates UX: system reminders now show the exact
/mcp-addinvocation per preset (including<api-key>for token presets),/mcp-addwarns when adding a shim preset at global scope, and new tests cover shim partitioning/registration and Rippling tool behavior.Reviewed by Cursor Bugbot for commit bd26645. Bugbot is set up for automated code reviews on this repo. Configure here.