Skip to content

SaaS Toolkit Routing Registry

SaaS Toolkit Routing Registry

Canonical lookup for every SaaS toolkit the platform touches → which MCP server handles it for each tenant. Any session (Claude Code, Cursor, Windsurf, VS Code, Codex CLI) reads this file when deciding how to satisfy a multi-toolkit request such as “pull Kahuna GTM + Analytics + HubSpot”.

This file also doubles as the ADR-058 Path 2 audit trail for toolkits Composio doesn’t cover (those land with vendor = PIPEDREAM or CF_WORKER).

One grep away from the answer. grep -i googletagmanager docs/composio/toolkit-registry.md returns the row that tells you which MCP to call and with which tenant identifier.

Registry

toolkit_slugvendormcp_server (ascend)mcp_server (kahuna)tool_prefixstatusnotes
hubspotCOMPOSIOcomposio-ascendcomposio-kahunaHUBSPOT_*LIVETenant routing via user_id={slug}. Lifecycle dates: use hs_v2_date_entered_{stage_id} only.
salesforceCOMPOSIOcomposio-ascendcomposio-kahunaSALESFORCE_*LIVESOQL via SALESFORCE_EXECUTE_SOQL_QUERY. Kahuna prod v66.0.
googleadsCOMPOSIOcomposio-ascendcomposio-kahunaGOOGLEADS_*LIVEv24. MCC routing: login-customer-id header = MCC, path = sub-account CID.
googleanalyticsCOMPOSIOcomposio-ascendcomposio-kahunaGOOGLEANALYTICS_*LIVEGA4 Data API v1beta only. Kahuna 273714189, Ascend 503817619.
googlesuperCOMPOSIOcomposio-ascendcomposio-kahunaGOOGLESUPER_*LIVEUnified Google Workspace (Drive, Sheets, Docs).
gmailCOMPOSIOcomposio-ascendcomposio-kahunaGMAIL_*LIVESearch threads, send, label.
googlecalendarCOMPOSIOcomposio-ascendcomposio-kahunaGOOGLECALENDAR_*LIVEEvents, free/busy, suggest time.
googletagmanagerPIPEDREAMpipedream-gtm-ascendpipedream-gtm-kahunaPIPEDREAM_GTM_*LIVEPath D per ADR-061. Composio does not cover GTM. Ascend connect verified 2026-05-20 (apn_JjhBPDA); Kahuna connect verified 2026-05-20 (apn_AVhav9D). Project proj_ELsVB0b. Both tenants share one Google login (mishaal@ascendgtm.net) and one GTM account (4703167523 — named “Kahuna” but hosts both containers); tenant routing keys off container_id — ascend→GTM-KXTJZ8QD (ascendgtm.net), kahuna→GTM-NFPWVVL (kahunaworkforce.com). Authorized scopes: tagmanager.readonly, tagmanager.edit.containers, tagmanager.publish (covers ~all version operations via workspaces). tagmanager.edit.containerversions not exposed by Pipedream’s stock GTM OAuth app — defer to custom-OAuth-client ADR if versions.live / versions.undelete strictly needed. Container mapping authoritative in this file until tenant_config:{tenant}.gtm KV is wired. Discovery recipe: manual-googletagmanager.md. Capability index: docs/tools/pipedream-googletagmanager/capability_registry.yaml.
slackCOMPOSIOcomposio-ascendSLACK_*LIVEAll scopes granted. Ascend-only (no Kahuna Slack connection).
gongCOMPOSIOcomposio-kahunaGONG_*LIVEBasic Auth, us-58396.api.gong.io. Kahuna-only.
apolloCOMPOSIOcomposio-ascendAPOLLO_*LIVEMixed people / company search, bulk enrich.
semrushCOMPOSIOcomposio-ascendcomposio-kahunaSEMRUSH_*LIVEDomain analytics + keyword research.
linkedinCOMPOSIOcomposio-ascendcomposio-kahunaLINKEDIN_*LIVEOrganic posts + profile.
linkedin_adsCOMPOSIOcomposio-kahunaLINKEDIN_ADS_*LIVEKahuna-only (paid LinkedIn).
gammaCOMPOSIOcomposio-ascendcomposio-kahunaGAMMA_*LIVE2 tools only: GAMMA_GENERATE_GAMMA, GAMMA_GET_GAMMA_FILE_URLS. No list/search — cannot enumerate existing decks.
quickbooksCOMPOSIOcomposio-ascendQUICKBOOKS_*LIVERealm 9341455490822583. Always pass account explicitly (not “default”).
vercelCOMPOSIOcomposio-ascendVERCEL_*LIVEDeployments + project management.
perplexityaiCOMPOSIOcomposio-ascendPERPLEXITYAI_*LIVEWeb-augmented LLM.
aws (Bedrock / SES / Textract)V5_CALL_APIascend-gatewayascend-gatewayaws_*LIVEFrozen fallback worker. Tools: llm_invoke, aws_bedrock_invoke, aws_ses_send, aws_textract.
anthropicV5_CALL_APIascend-gatewayascend-gatewayclaude / llm_invokeLIVEThrough AI Gateway (invariant 12). Frontier judges + user-facing only — background calls default to DeepSeek.
web_fetchV5_CALL_APIascend-side-channelascend-side-channelweb_fetch / perplexity_searchLIVESSRF-safe HTTP fetch, Jina markdown mode.
arbitrary_httpV5_CALL_APIascend-gatewayascend-gatewaycall_apiLIVEGeneric HTTP escape hatch. Use ONLY for one-off authenticated calls with no registry row. Undocumented SaaS does NOT belong here — file under ADR-058 Path 2 → Pipedream.

Status values

statusmeaning
LIVEConnected and verified end-to-end. Safe to call.
PENDINGConnection ID exists or vendor onboarding incomplete (e.g. consent pending).
WONT-FIXProvider assessed and deprioritized. Will not integrate.

Vendor values

vendormeaningwhen to choose
COMPOSIONative Composio toolkit, OAuth managed end-to-endFirst-choice for any OAuth SaaS provider Composio covers.
PIPEDREAMPipedream Connect (sanctioned gap-fill per ADR-061)OAuth SaaS Composio does NOT cover. Default fallback before reaching for V5_CALL_API.
V5_CALL_APIV5 Worker call_api / direct platform toolsAWS, LLM (Anthropic / DeepSeek / Gemini / xAI / OpenRouter), arbitrary HTTP with no other route, web_fetch.
CF_WORKERPersistent CF Worker built for one providerOnly when Pipedream also lacks the toolkit AND traffic justifies a custom worker. Requires an ADR.
NATIVE_MCPDedicated MCP server (e.g. github, mem0, cloudflare-api)When the provider ships an official MCP we trust.

Adding a row

  1. Find the toolkit’s row OR add a new one with the recipe from docs/composio/missing-toolkit-runbook.md.
  2. Pick vendor based on the table above.
  3. Fill mcp_server (ascend) / mcp_server (kahuna) from the corresponding row in .mcp.json if the tenant is not connected.
  4. Set tool_prefix to the literal prefix of the MCP tool names ({TOOLKIT}_{ACTION} for Composio, PIPEDREAM_{TOOLKIT}_* for Pipedream).
  5. Run npm run check:pre-commit — check 25 enforces this row exists for every MCP server in .mcp.json.
Terminal window
git add docs/composio/toolkit-registry.md
git commit -m "docs(routing): record {toolkit} routing (vendor={vendor})"

Multi-toolkit queries

When a single user ask spans multiple toolkits (e.g. “pull GTM + Analytics + HubSpot for kahuna”):

  1. Decompose the ask per toolkit.
  2. Look up each toolkit in the registry above → identify vendor and mcp_server ({tenant}).
  3. Fan out in parallel — one assistant message with N MCP tool calls. See .claude/rules/parallelization.md.
  4. Pass the tenant identifier on every call:
    • Composio → user_id={slug} (ascend or kahuna).
    • Pipedream → external_user_id={slug}.
  5. Aggregate in the session, never in any vendor — none of the MCPs federate.

Worked example — “pull Kahuna GTM + Analytics + HubSpot”

ToolkitRegistry row saysCall shape
googletagmanagerPIPEDREAM, pipedream-gtm-kahunamcp__pipedream-gtm-kahuna__* — GTM v2 endpoint via Pipedream proxy, external_user_id=kahuna
googleanalyticsCOMPOSIO, composio-kahunamcp__composio-kahuna__GOOGLEANALYTICS_RUN_REPORT({ user_id: "kahuna", property_id: "273714189", ... })
hubspotCOMPOSIO, composio-kahunamcp__composio-kahuna__HUBSPOT_HUBSPOT_LIST_CONTACTS({ user_id: "kahuna", ... })

All three issued in one parallel batch. The session aggregates the three responses.

Discoverability

Run discover_apis({query: "list GTM tags"}) (V5 Worker) — it returns gtm_list_tags from docs/tools/pipedream-googletagmanager/capability_registry.yaml alongside Composio’s HubSpot/GA4 rows. Semantic discovery is the unified entrypoint across vendors.

Drift CI

scripts/checks/25-toolkit-registry-routing.ts enforces:

  1. Every MCP server in .mcp.json with name composio-* or pipedream-* has at least one row referencing it.
  2. Every row with vendor != WONT-FIX lists an mcp_server that exists in .mcp.json.
  3. Every docs/tools/*/capability_registry.yaml matches a row whose toolkit_slug field is present.

Drift fails npm run check:pre-commit.