GrowSurf MCP Server
OfficialThis server lets AI agents build, configure, and manage GrowSurf referral and affiliate programs, including participants, rewards, analytics, webhooks, and integration guidance.
Create, update, clone, and list programs (campaigns) and read their configuration (design, emails, options, installation)
Manage rewards: create, update, delete, and list campaign rewards, with commission structures and tax valuation
Manage participants: add, update, bulk-delete, email, fetch analytics and activity logs, and set affiliate status
Trigger referral credit (with optional delay) and cancel delayed triggers; record affiliate sales and refunds
Read program analytics, including totals, time series, email metrics, status counts, engagement, and activation cohorts
Manage program webhooks: create, update, delete, list, and send test events
Generate integration guides, mobile SDK guidance, API library snippets, and client-side embeddable snippets
List integrations and provide dashboard connect links; capture temporary preview screenshots
Helpers: compute participant auto-auth HMAC hash, normalize webhook payloads, and generate idempotency keys
Provides native Android SDK implementation guidance for integrating GrowSurf referral tracking, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.
Provides native iOS SDK implementation guidance for integrating GrowSurf referral tracking, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.
Supports connecting Mailchimp to GrowSurf for syncing signups and contacts, with integration status and a dashboard connect link.
Supports connecting PayPal to GrowSurf for payouts and payment processing, with integration status and a dashboard connect link.
Supports connecting Resend to GrowSurf for email delivery, with integration status and a dashboard connect link.
Supports connecting Stripe to GrowSurf for payment processing and referral-related payment data, with integration status and a dashboard connect link.
Supports connecting Wise to GrowSurf for affiliate payouts, with integration status and a dashboard connect link.
Supports connecting Zapier to GrowSurf for workflow automation, with integration status and a dashboard connect link.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GrowSurf MCP ServerCreate a referral program for my fitness app with a 20% discount reward."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
GrowSurf MCP Server
The official GrowSurf command-line interface (CLI) and open-source Model Context Protocol (MCP) server for implementing GrowSurf referral and affiliate programs with guided steps and safe REST API wrappers.
Connect it to an AI agent and, in plain language, the agent can create a referral or affiliate program, configure rewards, install tracking, add and manage participants, and read analytics, all backed by the GrowSurf REST API.
MCP is optional. Any action-capable agent that can send HTTPS requests can start with GrowSurf's client-neutral REST workflow at https://growsurf.com/agent-start.md.
Learn more about GrowSurf at https://growsurf.com
Start with direct REST at https://growsurf.com/agent-start.md
Read the OpenAPI contract at https://growsurf.com/openapi.json
Read the Arazzo workflow at https://growsurf.com/arazzo.yaml
Learn about optional MCP setup at https://docs.growsurf.com/build-with-ai#optional-connect-mcp
Who is this for
This MCP server is for:
Developers using MCP-compatible tools (Claude Code, Codex, Cursor, Copilot, and other MCP clients)
Teams that want guided, AI-assisted GrowSurf integrations
This MCP server is NOT for:
Browser-only users who want a local stdio install. ChatGPT web and Claude.ai use the hosted remote connector at
https://mcp.growsurf.com. Claude Desktop can use either the local stdio server or the hosted connector. See the full client list and setup at https://docs.growsurf.com/build-with-ai#optional-connect-mcp.
Related MCP server: agentfuse-mcp
What you get
Guided Integration:
Universal Code install
Native iOS/Android SDK implementation guidance
Native GrowSurf Window guidance
Signup flow
Qualifying action flow
Affiliate sale / transaction tracking
Webhooks
Agent Recipes:
MCP prompts for creating referral programs, creating affiliate programs, advising on program design, troubleshooting referral tracking, embedding the widget, listing and fetching programs and participants, configuring rewards, wiring webhooks, and reading analytics
Installable Agent Skill bundle at
skills/growsurf-agent-toolkitSteering to review starter Design, Emails, Options, Installation, rewards, and GrowSurf Window content before patching
One-shot program-creation eval prompts and acceptance checks for starter content and configuration review
Happy‑Path REST API Wrappers:
Create an account and get an API key with no existing credentials
Read and rename the bound team, request team verification, and resend the team owner's verification email
List and get campaigns
Get campaign analytics (totals, time series, email metrics, participant engagement activity, and activation cohorts)
Create, update, and clone programs (campaigns)
List, create, update, and delete campaign rewards
List, create, update, and delete Program Resources, including a safe one-time FILE preparation flow
Get/update Design, Emails, Options, and Installation config
Capture temporary GrowSurf preview screenshots when the user explicitly asks for visual proof
List, create, update, delete, and test program webhooks
List, get, and add participants
Update a participant, email a participant, and get a participant's analytics and activity logs
Trigger referral credit (for referral programs), with optional delayed award (1-90 days)
Cancel a pending delayed referral trigger (for referral programs)
Record affiliate sale/transaction (for affiliate programs)
Create mobile participant tokens for signed-in native app users
Official API Library Snippets:
TypeScript
Python
PHP
Ruby
Java
Helpers:
Compute participant auto-auth HMAC hash
Normalize webhook payloads
Generate best‑effort idempotency keys for webhook deduplication
Requirements
Node.js 22+
A GrowSurf account for hosted OAuth
A GrowSurf API key for local stdio setup or manual API-key remote setup. A scoped key works as long as it has access to the tools and programs you want the agent to use.
A campaign (program) ID for campaign-scoped tools. Set
GROWSURF_CAMPAIGN_IDas the default, pass acampaignIdargument to target a specific program, or callgrowsurf_list_campaignsto find available programs. For a newly created program, pass theidreturned bygrowsurf_create_campaignto the other tools.Static guidance/snippet tools can run without credentials
Exception:
growsurf_create_accountneeds no API key. Call it only after the authorized owner approves account creation and accepts GrowSurf's Terms of Service and Privacy Policy. The account starts a 14-day Business trial without a credit card and returns its API key once. A lost key cannot be recovered through the API, so use this only if you can store a secret past the current conversation; otherwise have the owner connecthttps://mcp.growsurf.comand sign in. Pause for owner email verification before protected calls. Unverified accounts are deleted after 7 days. Team-level tools do not need a campaign ID.Every listed tool publishes standard MCP read-only, destructive, idempotent, and open-world safety hints. Scoped business actions stay available; API-key rotation is intentionally not an MCP tool. Rotate keys in GrowSurf Settings or through a direct REST/SDK client.
Official CLI
The npm package installs the growsurf-mcp command. Run it without a global install:
npx -y @growsurfteam/growsurf-mcpThe CLI starts GrowSurf's local stdio MCP server. Set GROWSURF_API_KEY for API-backed actions and GROWSURF_CAMPAIGN_ID for a default program. Public developer resources and static integration guidance work without credentials.
Inspect the installed command without starting the stdio server:
npx -y @growsurfteam/growsurf-mcp --help
npx -y @growsurfteam/growsurf-mcp --versionSupported MCP Hosts
For an MCP-compatible host, use GrowSurf's hosted OAuth endpoint at https://mcp.growsurf.com when the host supports remote Streamable HTTP with OAuth. Use the local npx server when the host needs a stdio process or manual API-key setup. No GrowSurf account yet? After owner approval, an agent can connect to https://mcp.growsurf.com/onboard with no credentials and call growsurf_create_account.
The GrowSurf MCP server works with any MCP-compatible host. The examples below cover a few config-based and CLI hosts. For the complete, current list of supported clients (including ChatGPT web, Claude.ai, Claude Desktop, GitHub Copilot, Gemini CLI, Devin Desktop, and Cline) with step-by-step setup, see https://docs.growsurf.com/build-with-ai#optional-connect-mcp.
Cursor
Claude Code (CLI-based)
Antigravity
Codex (CLI-based)
Cursor
Open or create Cursor's global MCP configuration at
~/.cursor/mcp.json.Add a server named
growsurfwith the hosted OAuth endpoint:
{
"mcpServers": {
"growsurf": {
"type": "http",
"url": "https://mcp.growsurf.com"
}
}
}For local stdio instead, use:
{
"mcpServers": {
"growsurf": {
"command": "npx",
"args": ["-y", "@growsurfteam/growsurf-mcp"],
"env": {
"GROWSURF_API_KEY": "YOUR_API_KEY",
"GROWSURF_CAMPAIGN_ID": "YOUR_CAMPAIGN_ID"
}
}
}
}Claude Code (CLI-based)
Open your terminal and connect Claude Code to the hosted OAuth endpoint:
claude mcp add --transport http --scope user growsurf https://mcp.growsurf.com
claude mcp login growsurfFor local stdio instead, install the server directly into Claude Code:
claude mcp add growsurf \
-e GROWSURF_API_KEY=your_api_key \
-e GROWSURF_CAMPAIGN_ID=your_campaign_id \
-- npx -y @growsurfteam/growsurf-mcpAntigravity
Open Antigravity.
Click the … menu in the panel to the right and select MCP Servers.
Click Manage MCP Servers > View raw config.
Recommended: in the
mcp_config.jsonfile, add the hosted OAuth endpoint:
{
"mcpServers": {
"growsurf": {
"serverUrl": "https://mcp.growsurf.com"
}
}
}Save the config, open Settings > Customizations, and select Authenticate for GrowSurf.
For local stdio instead, use:
{
"mcpServers": {
"growsurf": {
"command": "npx",
"args": ["-y", "@growsurfteam/growsurf-mcp"],
"env": {
"GROWSURF_API_KEY": "YOUR_API_KEY",
"GROWSURF_CAMPAIGN_ID": "YOUR_CAMPAIGN_ID"
}
}
}
}Codex
Recommended: connect Codex to the hosted OAuth endpoint:
codex mcp add growsurf --url https://mcp.growsurf.com
codex mcp login growsurfOr create or edit ~/.codex/config.toml:
[mcp_servers.growsurf]
url = "https://mcp.growsurf.com"For local stdio instead, add the following:
[mcp_servers.growsurf]
command = "npx"
args = ["-y", "@growsurfteam/growsurf-mcp"]
[mcp_servers.growsurf.env]
GROWSURF_API_KEY = "YOUR_API_KEY"
GROWSURF_CAMPAIGN_ID = "YOUR_CAMPAIGN_ID"Or configure local stdio from the CLI:
codex mcp add growsurf \
--env GROWSURF_API_KEY=YOUR_API_KEY \
--env GROWSURF_CAMPAIGN_ID=YOUR_CAMPAIGN_ID \
-- npx -y @growsurfteam/growsurf-mcpConfiguration
Set the following environment variables when running the MCP server:
GROWSURF_API_KEY(optional for startup; required for API-calling tools. Use a key with the scopes and program access those tools need)GROWSURF_CAMPAIGN_ID(optional; the default program for campaign-scoped tools. A tool'scampaignIdargument overrides it, so a single server can operate on any of your programs)GROWSURF_API_BASE_URL(optional; defaults tohttps://api.growsurf.com/v2. Useful for local or hosted MCP gateways that should call a different GrowSurf API origin)GROWSURF_UPLOAD_ALLOWED_ORIGINS(required only for FILE Resource uploads; a comma-separated private allowlist of exact HTTPS origins accepted from GrowSurf upload tickets. Wildcards and URL paths are rejected)GROWSURF_PARTICIPANT_AUTH_SECRET(optional; used by the hash helper)GROWSURF_WEBHOOK_TOKEN(optional; used for your own webhook URL token scheme)
Run with npx
After publishing this package, customers can run:
npx @growsurfteam/growsurf-mcpFor local development in this repo:
npm install
npm run build
node dist/cli.jsMCP tools
Every tool declares an MCP output schema and returns structuredContent, so hosts know each tool's result shape. REST tools return the API response (plus a JSON text block for older clients); the guidance and snippet tools return their markdown document under markdown.
Program, reward-configuration, options, and participant reads also include a rewardEvidence object in structuredContent. It records what this response establishes about approval policy and automatic fulfillment marking. Delivery remains unknown without the relevant fulfillment records. This assessment applies to this response only; combine it with other evidence. The API fields and original JSON text remain unchanged.
Guided Integration
growsurf_integration_guideStep-by-step guidance for implementing a GrowSurf referral or affiliate program.growsurf_mobile_sdk_guideNative iOS/Android SDK guidance for attribution,shareUrl,trackShare, and the native GrowSurf Window.growsurf_api_library_snippetsOfficial REST API library snippets for TypeScript, Python, PHP, Ruby, and Java.growsurf_list_integrationsList every integration the program can connect, each withconnected,enabled,autoDisabled, and the dashboardconnectUrl. Check this before acting on an integration.growsurf_get_integration_connect_linkGet a dashboard link that opens a specific integration's connect panel (Stripe, PayPal, Tango Card, Mailchimp, and many more). Hand it to the user when they want to connect one. The program is checked first, and the result reports whether the integration is already connected. Connecting happens in the dashboard, not through the API.
Program design and troubleshooting
growsurf_program_design_advisorReturns a short first draft by default. Setdetail: "full"for the complete report, including reward, sharing, and integration figures.benchmarkFactscarries complete statements with each ratio's unit, median, quartiles, sample, and source. Quote these statements together so a referral ratio cannot be mistaken for the percentage of people who refer.Recommend a qualifying action, reward structure, fulfillment path, safeguards, share channels, and integrations. The result includes
markdown, aconfigurationPlanwith exact tool arguments, anddecisionswith the qualifying action and unresolved customer choices. Call it before proposing rewards. Preserve the returned call shapes; the advisor and program-creation tools use differentgoalenums. Replace each<new-program-id>with theidreturned by program creation. Drafts leave reward amounts and commission terms open until the customer chooses them; a budget is a limit, not an incentive. SetsalesMotiontosales_ledfor demos or negotiated contracts, orself_servicefor direct purchases. When the host supplies insights, advice includes aggregate figures; without insights it uses documentation. Non-USD advice and budget comparisons omit dollar reward bands because the data mixes dollar currencies.growsurf_troubleshoot_referral_trackingSymptom-first diagnosis: referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, integrations not syncing, Zapier errors, fraud flags, dashboard numbers that look wrong, and more. Returns the checks to run in order (with the read tool and field for each), the likely causes most common first, fixes, and doc links. Pass asymptomkey, or adescriptionthat names the symptom.
Client & UI Snippets
growsurf_client_snippetsJavaScript SDK, GrowSurf Window, and embeddable examples. Includes a reminder to use a frontend design workflow when placing or styling embeddable UI.growsurf_embeddable_element_snippetHTML snippet for a specific GrowSurf embeddable element.growsurf_grsf_config_snippet<head>snippet for configuringwindow.grsfConfigand participant auto-auth.
Account onboarding
growsurf_create_accountCreate a GrowSurf account and get an API key. This is the only tool that does not requireGROWSURF_API_KEY. The returned key is shown once and locked (403EMAIL_NOT_VERIFIED_ERROR) until the owner verifies their email; verification unlocks that same key, so keep it and retry. It is replaced only on the owner's first dashboard sign-in. Creating an account agrees, on the account holder's behalf, to GrowSurf's Terms of Service and Privacy Policy.
Team
growsurf_get_teamFetch the team bound to the API key or OAuth connection, including its GrowSurf verification state.growsurf_update_teamUpdate the bound team's display name.growsurf_request_team_verificationAsk GrowSurf to verify the bound team, which is required before a program can email participants.growsurf_resend_team_owner_verification_emailResend the verification email to the bound team's owner without revealing their email address.
API & Tracking
growsurf_get_campaignFetch campaign configuration.growsurf_list_campaignsList programs available to the credential. Use this to find acampaignIdbefore calling campaign-scoped tools.growsurf_get_campaign_analyticsFetch program analytics, with optional per-periodseries, comparison, status, rate, email metrics viainclude=email, and participant activity-period engagement viainclude=engagement.growsurf_get_campaign_activation_analyticsFetch eligible-participant activation cohorts with a fixed 7- or 30-day observation window. Referral programs group byenrolledAsAdvocateAt; affiliate programs group byapprovedAsAffiliateAt. ReadcoverageStartAt,state, andreasonbefore interpreting zeroes or nulls.growsurf_create_campaignCreate a new program (campaign) with type-appropriate starter content and optional inline rewards (only needsGROWSURF_API_KEY, notGROWSURF_CAMPAIGN_ID). Review the seeded Design, Emails, Options, Installation, rewards, and GrowSurf Window content before patching.growsurf_agent_program_creation_evalGenerate one-shot program-creation eval prompts and acceptance checks for starter content, conservative rewards, configuration review, frontend install proof, and clean public copy.growsurf_update_campaignUpdate the program's identity and lifecycle: name, company branding, and status (only the fields you send are changed).growsurf_clone_campaignClone the program into a newDRAFTprogram (integrations and credentials are not copied).growsurf_list_campaign_rewardsList the program's configured rewards.growsurf_create_campaign_rewardCreate a campaign reward.growsurf_update_campaign_rewardUpdate a campaign reward by its reward key.growsurf_delete_campaign_rewardDelete a campaign reward by its reward key.growsurf_list_program_resources/growsurf_create_program_resource/growsurf_update_program_resource/growsurf_delete_program_resourceManage ordered participant resources. LINK uses HTTPS and TEXT uses plain text.growsurf_prepare_program_resource_fileRequest a one-time ticket and upload an allowed file up to 10 MB to the exact host-allowlisted destination selected by GrowSurf. Pass the returned ticket and signed result unchanged to create/update. The tool accepts no upload URL or credential and never retries an upload.growsurf_get_campaign_design/growsurf_update_campaign_designRead or patch design configuration, including the Program Editor Design tab and payout-destination confirmation page copy.growsurf_get_campaign_emails/growsurf_update_campaign_emailsRead or patch the Program Editor Emails tab config.growsurf_get_campaign_options/growsurf_update_campaign_optionsRead or patch the Program Editor Options tab config.growsurf_get_campaign_installation/growsurf_update_campaign_installationRead or patch the Program Editor Installation tab config.growsurf_capture_referral_flow_screenshotsCapture temporary GrowSurf preview screenshots for the current program after the user explicitly asks for visual proof. This returns the controlled referrer Window and referred-friend experience; use browser automation instead to prove the user's installed site.growsurf_list_campaign_webhooksList the program's webhooks (secrets are never returned).growsurf_create_campaign_webhookAdd a webhook to the program (with events and a write-only signing secret).growsurf_update_campaign_webhookUpdate a webhook by id (primaryfor the program's primary webhook).growsurf_delete_campaign_webhookRemove a webhook by id.growsurf_test_campaign_webhookSend a live test event to a webhook using its stored URL and secret.growsurf_add_participantAdd a participant (or referred participant) during signup.growsurf_list_participantsList participants in the current program, paginated bynextId. Passmetadata(up to 3 keys) to return only participants whose metadata matches exactly, such as looking someone up by your own customer ID. Use this to find a participant ID before calling participant-scoped tools.growsurf_get_participantFetch one participant by GrowSurf participant ID or email address.growsurf_update_participantUpdate a participant by ID or email (including internalnotes).growsurf_bulk_delete_participants— Check each row outcome.analyticsErasure.status: "pending"means analytics erasure is still pending; do not repeat successful rows. Permanently delete up to 200 participants (by ID and/or email, mixed lists allowed) in one request, with per-rowDELETED/NOT_FOUND/DUPLICATE/ERRORresults. Irreversible — removes the participants' referrals, rewards, commissions, and payout records.growsurf_email_participantEmail a participant using a configured template or a free-form subject/body.growsurf_get_participant_analyticsFetch one participant's engagement, rank, share, affiliate revenue, commission, payout, optional email metrics, and covered first milestones. Useinclude=activationfor milestones such asfirstPortalViewedAtandfirstShareChannel; addseriesfor coveredportalViewsandshareActions. An unavailable null is unknown, not proof that the action never happened.growsurf_get_participant_activity_logsList a participant's activity logs (offset/limit paginated).growsurf_trigger_referralTrigger referral (for referral programs only). Optionally passdelayInDays(1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window).growsurf_cancel_delayed_referralCancel a pending delayed referral trigger before the delay elapses (e.g. on refund/cancellation).growsurf_get_participant_payout_destinationGet a participant's payout-destination status across every provider enabled for the program (PayPal and/or Wise): per-provider status, confirmed payout email, legal recipient type, and repair reason.growsurf_request_participant_payout_destination_confirmationAsk a participant to confirm their payout destination for a provider — sends them a one-time confirmation link (only the participant can confirm).growsurf_record_saleRecord affiliate sales or transactions (for affiliate programs only).growsurf_refund_transactionRecord an amendment (refund, partial refund, or chargeback) against a recorded transaction; reverses or adjusts the referrer's commission (for affiliate programs only). The inverse ofgrowsurf_record_sale.growsurf_create_mobile_participant_tokenCreate or fetch a participant, then create a participant-scoped mobile SDK token for a signed-in mobile user.
Helpers
growsurf_participant_auth_hashGenerate participant auto-auth HMAC hashes (to authenicate participants automatically).growsurf_webhook_normalizeNormalize webhook payloads and generate idempotency keys (to deduplicate webhook deliveries).
Webhooks
GrowSurf webhooks notify your server when important referral or affiliate events occur, such as when new objects like participants, referrals, rewards, or transactions are created. Here are common use-cases:
Fulfill rewards automatically
Maintain internal points or credit systems
Sync participant and referral data into your database
Duplicate Delivery Handling
Webhook handlers should be idempotent because the same event can arrive more than once. Store an idempotency key before changing anything in your system.
Webhook Security & Idempotency
GrowSurf signs webhook deliveries when the webhook has a secret configured: each delivery includes a GrowSurf-Signature HMAC header computed with that secret (the secret is write-only and never returned). To securely use webhooks, we recommend the following:
Set a
secreton the webhook and verify theGrowSurf-Signatureheader on receiptValidate the payload shape and expected event type
Deduplicate webhook events using an idempotency key, because the same event can arrive more than once
The GrowSurf MCP server provides a helper tool (growsurf_webhook_normalize ) that normalizes webhook payloads and generates a best-effort idempotency key to simplify safe webhook processing.
Development and Testing
npm run dev
npm testAdditional Resources
Read developer docs at the following:
JavaScript SDK reference: https://docs.growsurf.com/developer-tools/javascript-sdk/api-reference
REST API reference: https://docs.growsurf.com/developer-tools/rest-api/api-reference
REST API libraries: https://docs.growsurf.com/developer-tools/rest-api/api-libraries
Native mobile guide: https://docs.growsurf.com/getting-started-for-native-mobile
Android SDK: https://docs.growsurf.com/developer-tools/android-sdk
Getting Started with GrowSurf: https://docs.growsurf.com/getting-started
The GrowSurf MCP server helps GrowSurf customers implement referral programs and affiliate programs quickly.
Available Tools
63 toolsgrowsurf_add_participantAdd ParticipantAInspect
Add or fetch a participant by email. Existing participants are returned unchanged. This is trusted direct enrollment; do not use it for a public application when the program requires affiliate review. For affiliate programs, set isAffiliate to true to enroll a new participant as approved or false to create a non-affiliate. If you omit it, a valid referredBy creates a referred non-affiliate; without a valid referrer, the new participant is enrolled as approved. A valid referredBy can be combined with isAffiliate: true. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| ipAddress | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| referredBy | No | ||
| fingerprint | No | ||
| isAffiliate | No | Affiliate programs only. Controls affiliate enrollment for a new participant. `true` enrolls the participant with `affiliateStatus: APPROVED`; `false` creates a non-affiliate without `affiliateStatus`. Existing participants are returned unchanged. | |
| referralStatus | No | ||
| mobileInstanceId | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses substantial behavior beyond the annotations: it is an upsert (existing participants returned unchanged), it is intended for trusted direct enrollment, it explains the approval logic for isAffiliate and referredBy, and it specifies the campaignId fallback to GROWSURF_CAMPAIGN_ID. The annotations are minimal, so the description carries and meets the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core behavior, then gives the warning and affiliate rules. Every sentence contributes useful information, though the affiliate logic is dense and could be tightened slightly without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with an output schema, the description covers the critical enrollment semantics, campaign targeting, and the public-application exclusion. It does not explain referralStatus or the enrichment parameters, but the core decisions needed to invoke the tool correctly are well covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 18%, so the description must compensate. It adds important semantics for email, referredBy, isAffiliate, and campaignId, especially the interaction between isAffiliate and referredBy. However, it leaves several parameters unexplained, including referralStatus, metadata, fingerprint, ipAddress, and mobileInstanceId, so compensation is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb/resource combination: 'Add or fetch a participant by email,' and immediately clarifies the key upsert behavior ('Existing participants are returned unchanged'). This distinguishes it from sibling participant tools like get_participant or update_participant, which are not email-based upserts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear when-to-use context ('trusted direct enrollment') and an explicit when-not-to-use condition ('do not use it for a public application when the program requires affiliate review'). It also gives conditional guidance for affiliate programs. It does not name a specific alternative tool to use instead, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_agent_program_creation_evalProgram Creation EvalsARead-onlyIdempotentInspect
Generate one-shot GrowSurf program-creation eval prompts and acceptance checks for agent steering: starter content review, conservative rewards, configuration review, and frontend install proof.
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| includeOneShotPrompts | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, and non-destructive behavior, so the description only needs to add extra behavioral context. It does so by specifying that the tool produces 'one-shot' evaluation prompts and acceptance checks, and by listing the four focus areas, which goes beyond mere annotation repetition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The entire description is one front-loaded sentence with no filler. It states the verb, resource, purpose, and key scope areas in a compact list, so every part earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema and annotations cover return values and safety behavior, and both parameters are optional with defaults, so an agent can invoke the tool minimally. However, with no schema descriptions for parameters, the description leaves programType semantics and the effect of includeOneShotPrompts unexplained, creating a notable completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden of explaining the two parameters, but it does not mention programType or define what includeOneShotPrompts controls. Only the word 'one-shot' weakly hints at one parameter, and 'program-creation' weakly hints at the other; this is insufficient compensation for a low-coverage schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action, 'Generate one-shot GrowSurf program-creation eval prompts and acceptance checks', naming both the deliverable and its purpose. The colon-delimited list of coverage areas further distinguishes it from the many operational sibling tools, making its unique role clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'for agent steering' implies the intended context, and the content areas suggest evaluation scenarios. However, there is no explicit when-to-use/when-not-to-use guidance or mention of alternatives, leaving the selection logic mostly to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_api_library_snippetsAPI Library SnippetsCRead-onlyIdempotentInspect
Generate official REST API library snippets for TypeScript, Python, PHP, Ruby, and Java, including Create Mobile Participant Token.
| Name | Required | Description | Default |
|---|---|---|---|
| No | |||
| language | No | all | |
| workflow | No | all | |
| campaignId | No | ||
| referredBy | No | ||
| participantIdOrEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds no behavioral detail beyond generating snippets, but it does not contradict the annotations either.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one concise, front-loaded sentence with no filler. It communicates the deliverable and scope quickly, though a short structured format could improve scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With six optional parameters, multiple workflow and language enums, and many sibling snippet tools, more contextual guidance is needed for reliable invocation. The description omits when to use this tool, how to populate workflow-specific identifiers, and how it relates to client/embeddable snippet alternatives; the output schema helps with return values but not invocation context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description needed to explain how to use email, language, workflow, campaignId, referredBy, and participantIdOrEmail. It only echoes the language options and mentions the mobile participant token workflow, leaving most parameters unexplained; the schema itself already provides the enums and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: generating official REST API library snippets for five named languages, and explicitly calls out the Create Mobile Participant Token workflow. It is reasonably distinguishable from sibling snippet tools like client snippets and embeddable snippets, though it does not name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance about when to use this tool versus sibling tools such as growsurf_client_snippets, growsurf_embeddable_element_snippet, or growsurf_grsf_config_snippet. The description also does not explain which workflow or language option fits a given scenario.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_bulk_delete_participantsBulk Delete ParticipantsADestructiveIdempotentInspect
Bulk delete participants from your GrowSurf program in one request. DESTRUCTIVE: deletion is permanent, cannot be undone, and removes the participants' referrals, rewards, commissions, and payout records. Each entry in participants is a GrowSurf participant ID or an email address (mixed lists are allowed), up to 200 entries per request — chunk larger lists across multiple calls. Returns a summary (total, deletedCount, notFoundCount, duplicateCount, errorCount) plus per-row results in request order, each with status DELETED, NOT_FOUND, DUPLICATE (resolves to the same participant as an earlier entry), or ERROR — both 200 and 202 responses can include NOT_FOUND or ERROR rows, so check the summary. A 202 response includes analyticsErasure when analytics erasure is pending. DELETED means participant cleanup completed; reports can retain the participant until analytics erasure completes. Do not repeat successful rows to finish analytics erasure. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participants | Yes | GrowSurf participant IDs and/or email addresses to delete (1-200 entries; mixed lists allowed). |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | No | One entry per submitted identifier, in request order. |
| summary | No | Counts across all submitted entries. |
| analyticsErasure | No | Analytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint, but the description goes far beyond them by explaining what deletion removes (referrals, rewards, commissions, payout records), status semantics, 200 vs 202 differences, analyticsErasure, and the recommendation not to repeat successful rows. This is exemplary behavioral disclosure and adds substantial context not available in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: purpose, destructiveness, input constraints, response format, status meanings, async erasure, and campaign targeting. The destructive warning is front-loaded, and the flow from inputs to outputs is logical. Nothing feels redundant or decorative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity — permanent bulk deletion, mixed identifiers, chunking, partial errors, 200 vs 202 behavior, and pending analytics erasure — the description covers every operational aspect an agent needs. The output schema and this description together give a complete picture, including edge cases like NOT_FOUND and DUPLICATE rows.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds practical value by clarifying that mixed participant IDs and emails are allowed, that lists may need chunking across calls, and that entries resolving to the same participant produce DUPLICATE. This supplements the schema rather than merely restating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Bulk delete'), a precise resource ('participants from your GrowSurf program'), and the scope ('in one request'). It clearly differentiates this from other participant-focused tools and immediately signals permanence, so an agent can identify its purpose at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides strong usage context: when to use bulk deletion, how to chunk lists over 200 entries across multiple calls, and which campaign is targeted by default vs. when campaignId is passed. It lacks an explicit 'do not use this when...' exclusion, but the boundary is clear enough given the identical sibling pool and the permanent nature of the operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_cancel_delayed_referralCancel Delayed ReferralADestructiveIdempotentInspect
Cancel a pending delayed referral trigger for a participant before the delay elapses (e.g. on refund/cancellation). Returns { success, message }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. Present when credit was not awarded immediately. |
| success | No | Whether referral credit was awarded, scheduled, or cancelled. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide destructiveHint=true and idempotentHint=true; the description adds context beyond those: the action applies only to a pending trigger, has a campaign targeting default, and returns { success, message }. It does not mention what happens if the delay has already elapsed, which is minor given the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying distinct value: action window, return shape, campaign targeting. There is no filler or repetition beyond the brief default-campaign note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description gives the core purpose and return shape, and the output schema covers the response. However, it omits the key invoke precondition that one of participantId/participantEmail is required, and does not describe behavior when the delay has already elapsed. For a simple 3-parameter tool this is a noticeable but not crippling gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, so the description must compensate for the otherwise undocumented participantId and participantEmail parameters. It only echoes the schema's campaignId default behavior and names 'participant' generically; it never explains that either participantId or participantEmail is required, nor offers any guidance on selecting between them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Cancel a pending delayed referral trigger'), a target ('a participant'), and a temporal boundary ('before the delay elapses'), with a concrete use case (refund/cancellation). This distinguishes it cleanly from siblings like growsurf_trigger_referral and growsurf_refund_transaction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear guidance on the situation where this tool is appropriate ('before the delay elapses (e.g. on refund/cancellation)') and the default behavior for campaignId. It does not explicitly compare against sibling tools such as growsurf_trigger_referral or explain when not to use it, so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_capture_referral_flow_screenshotsCapture Referral Flow ScreenshotsAInspect
Capture temporary GrowSurf preview screenshots after the user explicitly asks for screenshots or screenshot proof. Returns short-lived URLs for the controlled referrer Window and referred-friend experience for this program. This does not prove the user's installed site; use browser automation for that. This tool does not accept arbitrary URLs, HTML, JavaScript, or external screenshot targets. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| expiresAt | No | When the signed URLs stop working (ISO 8601). |
| generatedAt | No | When the screenshots were captured (ISO 8601). |
| screenshots | No | One entry per captured view. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false and offer no behavioral detail, so the description carries the full burden. It discloses temporary/short-lived URLs, the controlled experiences captured, rejection of arbitrary URLs/HTML/JS/external targets, and the campaignId fallback to GROWSURF_CAMPAIGN_ID. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core purpose, followed by output nature, exclusions/alternative, and parameter targeting. Every sentence earns its place; no fluff or redundant content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter tool with an output schema, the description covers when to call, what it does, what it does not do, and how campaignId targets. The output schema handles return-format details, so no essential context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema's campaignId description already explains the default behavior and the create_campaign relationship. The tool description restates the default-targeting behavior but adds no meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: capture temporary GrowSurf preview screenshots, and narrows scope to the controlled referrer Window and referred-friend experience. It clearly distinguishes itself from the many campaign/config/analysis siblings and explicitly notes this does not prove the user's installed site, preventing confusion with browser automation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly defines when to use: 'after the user explicitly asks for screenshots or screenshot proof.' It also names an alternative for a different need ('use browser automation for that') and lists unsupported input categories, giving both positive and negative usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_client_snippetsClient SnippetsBRead-onlyIdempotentInspect
Generate copy-pasteable client-side snippets for GrowSurf referral tracking, embeddable elements, and the GrowSurf Window (JS + CSS), with placement guidance for app UI work.
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| singlePageApp | No | ||
| referralTrigger | No | signup_plus_qualifying_action | |
| includeUnreadBadge | No | ||
| includeGrowSurfWindow | No | ||
| participantAuthEnabled | No | ||
| includeEmbeddableElements | No | ||
| includeEventSubscriptions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and idempotentHint=true, making it clear this is a safe read-only operation that can be called repeatedly without side effects. The description adds that it generates snippets and provides placement guidance, but does not disclose the format of the output (e.g., exact code blocks, language specifics) beyond JS + CSS. With annotations covering safety, the description adds moderate value, but it could state that no programmatic changes are made and the output is purely for the UI.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that is concise and front-loaded with the core purpose ('Generate copy-pasteable client-side snippets'). It covers key topics (referral tracking, embeddable elements, GrowSurf Window) and adds placement guidance without excessive detail. It could be more structured, but it is efficient and earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 8 parameters with 0% schema description coverage and no parameter documentation in the description, which is a major gap. There is an output schema, which may define the snippet structure, but since it is not shown here, it is unclear. The description is not complete enough for an agent to correctly set all options without further guidance. It needs to either describe parameters or link to resource guides.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning none of the 8 parameters are described in the schema. The description does not explain any parameters, such as programType, singlePageApp, referralTrigger, or includeGrowSurfWindow. This is a significant gap because an agent must guess the meaning of each boolean and enum from names and defaults, which is error-prone. The description should at least summarize key options to compensate for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool generates client-side snippets for GrowSurf referral tracking, embeddable elements, and the GrowSurf Window, specifying JS + CSS and placement guidance. It distinguishes from sibling tools like growsurf_api_library_snippets and growsurf_embeddable_element_snippet by focusing on client-side copy-pasteable snippets for app UI work. The title 'Client Snippets' is more generic, but the description clarifies the specific output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions placement guidance for app UI work, indicating it is intended for front-end integration. It implicitly differentiates from API snippets by naming 'copy-pasteable client-side snippets', but it does not explicitly state when to use this tool versus siblings like growsurf_api_library_snippets or growsurf_mobile_sdk_guide. It lacks explicit when-not-to-use alternatives, but the context is clear enough for an agent to infer the primary use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_clone_campaignClone ProgramAInspect
Clone your GrowSurf program (campaign) into a new DRAFT program. Integrations and credentials are not copied; active rewards are cloned. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating, non-idempotent operation. The description adds valuable behavior: integrations and credentials are not copied, active rewards are cloned, and the result is a draft program. This goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: the main action is front-loaded, the copy caveat is explicit, and the parameter default is clearly stated. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter clone operation with an output schema available, the description covers the essential behavior, the selective copying, and the default target. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents the default behavior and use with growsurf_create_campaign. The description mostly restates this targeting rule, adding little new meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Clone'), the resource ('GrowSurf program/campaign'), and the concrete result ('a new DRAFT program'). This distinguishes it from sibling creation/update tools and makes its purpose immediately clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool does and how the optional campaignId default behaves, but it never says when to choose cloning over creating or updating a program. No alternatives or exclusion criteria are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_accountCreate GrowSurf AccountADestructiveInspect
Create a brand-new GrowSurf account and return an API key. Call this tool only after the authorized owner explicitly approves account creation and accepts GrowSurf's Terms of Service (https://growsurf.com/terms) and Privacy Policy (https://growsurf.com/privacy). This is the only tool that does not require GROWSURF_API_KEY. The account starts a 14-day Business trial without a credit card. The endpoint returns the new key once in apiKey. A lost key cannot be recovered through this API, so do not create an account here unless you can store the key somewhere that outlives the current conversation. If you cannot, ask the account owner to connect GrowSurf's hosted MCP server at https://mcp.growsurf.com instead, which keeps the credential with your tool rather than in chat. The key is locked until the account owner's email address is verified. Until then, program and resource endpoints return a 403 with error code EMAIL_NOT_VERIFIED_ERROR. Create the account, tell the owner to click the link in the verification email, then retry until that error clears. Use growsurf_resend_team_owner_verification_email if the email was lost. The welcome email also contains a set-password link for dashboard access. Accounts whose email is never verified are deleted automatically after 7 days. Verification unlocks the same key you were given, so keep it and retry rather than asking for a replacement. Separately, the API key is replaced the first time the account owner signs in to the GrowSurf dashboard; after that the previous key returns a 403 with error code NOT_AUTHORIZED_ERROR. Some actions, such as emailing participants, also require GrowSurf to verify the team. Personal and disposable email addresses are not accepted.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| company | No | ||
| lastName | No | ||
| firstName | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Email address for the new account. | |
| apiKey | No | An API key for the new account. Shown once, locked (`403` `EMAIL_NOT_VERIFIED_ERROR`) until the account's email is verified, and rotated when the owner first signs in to the dashboard. |
| verificationStatus | No | Team verification state for the new account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations (destructiveHint=true, openWorldHint=true) by detailing the 14-day trial, one-time key delivery, unrecoverable key loss, email-verification lock with 403 EMAIL_NOT_VERIFIED_ERROR, 7-day deletion of unverified accounts, key rotation after dashboard sign-in, and rejection of personal/disposable emails. It also describes post-creation steps and error codes, fully aligning with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is front-loaded with purpose and preconditions, then flows through workflow, error handling, and caveats. Each sentence contributes meaningful operational detail; while it could be tightened, there is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers prerequisites, alternatives, error codes, recovery flows, key lifecycle, and account-deletion behavior, providing everything an agent needs to execute the account-creation workflow end-to-end. Since an output schema exists, the absence of return-value detail is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does for the email parameter, explaining verification requirements and domain restrictions, but it adds no semantic detail for company, lastName, or firstName beyond their self-evident names. This is adequate for the most critical parameter but leaves the others to inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Create a brand-new GrowSurf account and return an API key.' It further distinguishes itself by noting it is the only tool in the set that does not require GROWSURF_API_KEY, making it unmistakable among the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to call: only after owner approval and acceptance of ToS/Privacy Policy. It also provides alternatives—using the hosted MCP server when key storage is impossible, and growsurf_resend_team_owner_verification_email for lost verification emails—so an agent knows when not to use this tool and what to do instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_campaignCreate ProgramAInspect
Create a new GrowSurf program (campaign) pre-populated with type-appropriate starter content, optionally with inline rewards. Starter content includes Design, Emails, Options, Installation, and GrowSurf Window defaults. Only type is required; the program is created in DRAFT status owned by the credential's bound team. currencyISO sets the program's currency (defaults to USD) and is immutable after creation. Pass goal so the share settings suit the audience; it is set here or not at all. Ask the person for the incentive rather than choosing one: leave rewards out unless they named an amount, and tell them the program starts with GrowSurf's starter rewards switched off so it awards nothing yet. Editor-tab config (design, emails, options, installation) is not accepted here. Fetch and review those config sub-resources after creation, then patch only what needs to change. Does NOT require GROWSURF_CAMPAIGN_ID. The response includes the new program id; pass it as campaignId to the other tools (or set GROWSURF_CAMPAIGN_ID) to configure and operate the program.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | What the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it. | |
| name | No | ||
| type | Yes | ||
| rewards | No | Rewards to create with the program. Include this only when the person told you the amount and who funds it. Omit it and the program is seeded with starter rewards that are switched off, awarding nothing until the customer enables one. Send `[]` to start with no rewards at all. | |
| companyName | No | ||
| currencyISO | No | ||
| companyLogoImageUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations carry only a minimal safety profile (readOnlyHint=false, destructiveHint=false). The description adds extensive behavioral context: the program is 'created in DRAFT status owned by the credential's bound team,' `currencyISO` 'is immutable after creation,' `goal` is 'set here or not at all,' and starter rewards are 'switched off so it awards nothing yet.' It also tells the agent how to use the response id as `campaignId` for subsequent tools.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
At roughly 200 words the description is long, but it is heavily front-loaded — the first sentence states the core action and the rest proceeds through constraints in logical order. It is slightly repetitive with the schema's rewards and goal descriptions, though it adds the agent-facing instruction to ask the person for the incentive. Every section earns its place for a tool with this many lifecycle constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema covers return values, and the description covers everything else an agent needs to invoke this correctly: the single required param, the DRAFT state, ownership, currency immutability, set-once goal behavior, the editor-config exclusion, and the id-to-campaignId handoff. The only notable omission is the semantic difference between REFERRAL and AFFILIATE types, which the enum alone does not explain, but this does not block correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 29%, so the description must compensate. It adds critical guidance for the decision-heavy params: 'leave `rewards` out unless they named an amount,' `currencyISO` 'defaults to `USD` and is immutable,' and `goal` is 'set here or not at all.' However, name, companyName, and companyLogoImageUrl receive no description in either the schema or the description, leaving a small gap for those three optional params.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Create a new GrowSurf program (campaign) pre-populated with type-appropriate starter content...' The 'pre-populated with starter content' qualifier and 'optionally with inline rewards' distinguish it from sibling creation tools like growsurf_create_campaign_reward and growsurf_clone_campaign. The title alone is generic, but the description fully disambiguates the tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states what this tool is not for: 'Editor-tab config (design, emails, options, installation) is not accepted here. Fetch and review those config sub-resources after creation, then patch only what needs to change.' It also flags the prerequisite difference from siblings with 'Does NOT require GROWSURF_CAMPAIGN_ID,' and the schema's goal field routes follow-up changes to growsurf_update_campaign_design. This is explicit when/when-not guidance naming the alternative workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_campaign_rewardCreate Campaign RewardAInspect
Create a new campaign reward (reward config) on your GrowSurf program. type must be compatible with the program type (affiliate programs support only AFFILIATE rewards; referral programs support the other types). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| event | No | The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only. | |
| limit | No | ||
| order | No | ||
| title | No | ||
| value | No | Tax valuation for the reward (the referrer's side of a double-sided reward). `fairMarketValueUSD` is the manual fair-market value in USD (major units). `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards always use `NONEMPLOYEE_SERVICES`. | |
| imageUrl | No | ||
| metadata | No | ||
| isVisible | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| couponCode | No | ||
| description | No | ||
| isUnlimited | No | ||
| limitDuration | No | ||
| referredValue | No | Tax valuation for the referred friend's side of a double-sided reward. `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards have no referred-friend side, so GrowSurf clears these settings. Use `PURCHASE_REBATE` only when that is the correct tax character. | |
| numberOfWinners | No | ||
| referralCouponCode | No | ||
| commissionStructure | No | Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED. | |
| conversionsRequired | No | ||
| nextMilestonePrefix | No | ||
| nextMilestoneSuffix | No | ||
| referralDescription | No | ||
| referredRewardUpfront | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating, non-idempotent, non-destructive operation, and the description aligns with that. The description adds useful behavioral context about program-type compatibility and campaignId fallback. It does not disclose validation side effects, auth requirements, or what happens on type mismatch, but given annotation coverage the additional context is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the purpose, the second gives the most important constraint, and the third explains campaign targeting. Every sentence earns its place with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the tool has 23 parameters, nested objects, and many type-conditional fields, yet the description only explains two aspects. An agent would still be uncertain about which fields are required for a given reward type, how `event` relates to reward types, or what `commissionStructure` needs for AFFILIATE rewards. The description is not complete enough for correct invocation of such a complex tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 22%, so the description must compensate. It does add meaning for `type` (compatibility with program type) and `campaignId` (default behavior), but the other 21 parameters—including `event`, `value`, `referredValue`, `commissionStructure`, `isUnlimited`, and many more—receive no description-level guidance. This is a substantial gap for a tool with many conditional fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and object: 'Create a new campaign reward (reward config) on your GrowSurf program.' This distinguishes the tool from sibling update/list/delete reward tools. The added note about type compatibility and campaignId targeting further clarifies exactly what the tool creates and where.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context: type must match the program type, and campaignId defaults to GROWSURF_CAMPAIGN_ID when omitted. However, it does not explicitly say when to use this tool versus update_campaign_reward or list_campaign_rewards, nor does it state exclusions or prerequisites such as needing an existing program.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_campaign_webhookCreate WebhookAInspect
Add a webhook to your GrowSurf program. payloadUrl is required. events is the list of events this webhook is subscribed to (omit to subscribe it to no events). secret is write-only — GrowSurf uses it to sign deliveries (the GrowSurf-Signature HMAC header) and never returns it. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| secret | No | Write-only. Signs deliveries; never returned. | |
| isEnabled | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| payloadUrl | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavior beyond annotations: `secret` is write-only, signs deliveries via the GrowSurf-Signature HMAC header, and is never returned. It also clarifies a non-obvious default: omitting `events` subscribes the webhook to no events. These details materially improve an agent's understanding of side effects and security behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three focused sentences carry a high information density with no filler. The most important call constraint (`payloadUrl` required) is front-loaded, and the write-only secret behavior is explained in a compact, useful way.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the annotations are simple, the description covers the key invocation concerns: required parameter, event subscription semantics, secret handling, and campaign targeting. The only small omission is clarifying the default or effect of `isEnabled`, but this is minor and likely covered by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, so the description must compensate. It explains `payloadUrl` as required, `events` as the subscribed event list with an omit default, `secret` as write-only signing material, and `campaignId` as the targeting override. Only `isEnabled` is left entirely to the schema's bare boolean type, which is a minor gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Add a webhook to your GrowSurf program.' This clearly distinguishes the create action from sibling tools like update, delete, list, and test webhooks. The name and title are not merely restated; the description adds the domain object and action context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use this tool: creating a webhook subscription for a GrowSurf program. It also explains the campaignId targeting rule, including the GROWSURF_CAMPAIGN_ID default. However, it does not explicitly exclude modifying or removing existing webhooks via update/delete siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_mobile_participant_tokenCreate Mobile Participant TokenAInspect
Create or fetch a participant, then create a participant-scoped mobile SDK token via GrowSurf REST. Participant creation is trusted direct enrollment; do not use it for a public application when the program requires affiliate review. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| ipAddress | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| referredBy | No | ||
| fingerprint | No | ||
| isAffiliate | No | Sets whether the participant is an affiliate. Use `true` only for trusted direct enrollment. Public applicants should follow the program's configured application flow. | |
| referralStatus | No | ||
| mobileInstanceId | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| isNew | No | Whether this request created a new participant. |
| expiresIn | No | Token lifetime in seconds. |
| participant | No | The participant record (same shape as the `growsurf_get_participant` result). |
| participantToken | No | Participant-scoped bearer token for GrowSurf mobile SDK participant endpoints. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations confirm mutation (readOnly=false) and no idempotency. The description adds that it may create or fetch a participant, uses direct enrollment, and targets campaignId by default. It does not disclose auth needs, rate limits, or consequences beyond participant creation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with the main action front-loaded and no filler. 'via GrowSurf REST' is arguably redundant, but overall it is compact and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The overall flow, trust caveat, and campaign targeting are covered, and an output schema exists so return values need not be spelled out. However, with 11 parameters and minimal schema descriptions, important inputs like mobileInstanceId are not explained, leaving an agent to guess their role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 18%, so description must compensate, but it only elaborates campaignId (repeating schema) and the isAffiliate trust context. The other 9 parameters (email, mobileInstanceId, referralStatus, etc.) remain effectively undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific compound operation: create/fetch a participant then create a participant-scoped mobile SDK token. It clearly identifies the resource (mobile SDK token) and separates it from sibling participant/campaign tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not: trusted direct enrollment only, avoid public apps requiring affiliate review. It lacks a named alternative, so it doesn't fully route to another tool, but it provides concrete usage context and the campaignId default behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_create_program_resourceCreate Program ResourceAInspect
Create a FILE, LINK, or TEXT resource for participants. LINK requires an HTTPS url. TEXT requires plain text. For a FILE up to 10 MB, call growsurf_prepare_program_resource_file first and pass its uploadTicket and uploadResult unchanged. New resources default to draft unless you set isPublished. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Used only with `LINK`. | |
| text | No | Used only with `TEXT`. | |
| type | Yes | ||
| title | Yes | ||
| category | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| description | No | ||
| isPublished | No | ||
| uploadResult | No | The unmodified result returned by the secure upload flow. Used only with `FILE`. | |
| uploadTicket | No | The one-time upload ticket. Used only with `FILE`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey readOnly=false, idempotent=false, and destructive=false. The description adds meaningful behavior beyond those annotations: new resources default to draft unless isPublished is set, campaignId falls back to GROWSURF_CAMPAIGN_ID, and FILE uploads require an unmodified upload result. This gives an agent actionable expectations without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences carry a dense but well-organized set of facts: what the tool creates, type-specific requirements, the FILE upload prerequisite, and default behavior. It is front-loaded with the core purpose and wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 10 parameters, conditional requirements, and an output schema, the description covers the critical decision points: which fields are required per type, the FILE upload workflow, campaign targeting, and publishing defaults. The presence of an output schema means return values need not be described. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50%, but the description compensates by explaining the role of type, url, text, uploadTicket, uploadResult, campaignId, and isPublished. It clarifies which parameters apply to which resource type, which is not fully evident from the raw schema. It does not mention title, category, or description, but those are relatively self-explanatory and the schema documents some of them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Create') and a clear resource ('program resource'), and further distinguishes among the three resource types (FILE, LINK, TEXT). It is immediately distinct from sibling tools like growsurf_update_program_resource or growsurf_list_program_resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit conditions for each resource type: LINK requires HTTPS url, TEXT requires plain text, and FILE requires calling growsurf_prepare_program_resource_file first and passing uploadTicket/uploadResult unchanged. It also explains the campaignId default and draft default, though it does not explicitly mention alternatives such as updating or deleting an existing resource.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_delete_campaign_rewardDelete Campaign RewardADestructiveIdempotentInspect
Delete a campaign reward (reward config) from your GrowSurf program. The reward is deactivated, removed from the program's reward set, and any connected upfront-discount coupons are cleaned up. campaignRewardId is the reward key. Returns { id, success }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| campaignRewardId | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The deleted campaign reward id. |
| success | No | Whether the campaign reward was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds genuinely new behavioral context: delete means deactivation plus removal from the reward set plus cleanup of connected upfront-discount coupons. It also discloses the { id, success } return shape. No contradiction with annotations — the key-based targeting aligns with idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero waste: the verb-and-resource statement is front-loaded, followed by side effects, then parameter and return behavior. Every sentence carries distinct information that earns its place for a destructive operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool, the description covers what gets destroyed (coupons cleaned up), the targeting fallback, and the return value, while the existing output schema handles return structure. A minor gap is the effect on participants or referrals already holding the reward, and reversibility is not addressed, but nothing essential to invoking the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: campaignId has a detailed schema description but campaignRewardId has none. The description compensates by defining campaignRewardId as 'the reward key' and restating the campaignId targeting/default rule, adding meaning beyond the bare property names. It does not cover every edge but addresses the critical gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific verb 'Delete' plus the resource 'campaign reward (reward config)', where the parenthetical disambiguates a reward config from other reward concepts. Among the many delete siblings (delete_campaign_webhook, delete_program_resource), this unambiguously identifies the target resource. No ambiguity about what is being deleted.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the operational semantics (reward is deactivated, removed from the reward set, coupons cleaned up) so an agent understands what 'delete' actually entails in this system. It also clarifies targeting behavior via campaignId with its GROWSURF_CAMPAIGN_ID default and how to route to a newly created campaign. It does not explicitly contrast with update_campaign_reward for cases where only a deactivation is desired, so no explicit exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_delete_campaign_webhookDelete WebhookADestructiveIdempotentInspect
Remove a webhook from your GrowSurf program by id. Returns { id, success }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| webhookId | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Id of the webhook that was deleted. |
| success | No | Whether the webhook was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey destructiveHint=true, readOnlyHint=false, and idempotentHint=true. The description adds value beyond annotations by disclosing the return shape ({ id, success }) and the campaignId fallback behavior. It aligns with the destructive annotation and adds contextual details without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three brief, purposeful sentences. It front-loads the tool's core purpose, then adds return-value and targeting details. Every sentence earns its place, with no repetition or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive delete operation, the description is complete: it identifies the resource, explains id targeting and campaign selection, notes the default campaign fallback, and mentions the return value. Output schema and annotations cover the remaining structural and safety details, leaving no significant gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%: campaignId is well documented, but webhookId lacks any schema description. The tool description partially compensates by stating 'by id' and explaining campaignId targeting and its default to GROWSURF_CAMPAIGN_ID. This clarifies the role of both parameters, though webhookId meaning remains implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Remove'), resource ('a webhook from your GrowSurf program'), and the identifying key ('by id'). It is clear and actionable, though it does not explicitly distinguish itself from sibling webhook tools like create/update/list/test, leaving some differentiation to the tool name and verb choice.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: when a webhook needs to be removed by id. However, it provides no explicit guidance on when not to use it or which alternative sibling (e.g., update_campaign_webhook) should be chosen instead. The campaignId targeting behavior is useful usage context but does not address tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_delete_program_resourceDelete Program ResourceADestructiveIdempotentInspect
Delete a participant resource from your GrowSurf program. This does not remove its reusable Media Center asset. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| resourceId | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The deleted resource id. |
| success | No | Whether the resource was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=true, and the description's 'Delete' is consistent with these. The description adds genuine value beyond the annotations by clarifying that the reusable Media Center asset is preserved, which is a meaningful behavioral disclosure not captured in the structured fields. No contradiction found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with the primary action front-loaded. The Media Center clarification earns its place and the targeting note is compact. Slightly more structure could be added but there is no wasted prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive 2-parameter tool with an output schema present, the description is reasonably complete, but the resourceId parameter is left undefined in both schema and description, which an agent needs to invoke the tool. The description does not mention what the response looks like or any prerequisites, though the output schema partially mitigates this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% — campaignId is well-described in the schema but resourceId has no description. The tool description reinforces campaignId targeting but does not explain what resourceId refers to or where to obtain it, so it only partially compensates for the undocumented parameter. With half the parameters lacking schema detail, more compensation was needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource ('Delete a participant resource from your GrowSurf program') and adds a distinguishing behavioral note (does not remove the reusable Media Center asset), which separates it from the related create/update/list program resource siblings. It could be stronger by naming sibling tools explicitly, but the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the campaign targeting behavior ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') which is useful context, but it gives no guidance on when to choose this tool over alternatives like growsurf_delete_campaign_reward or when NOT to use it. Usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_email_participantEmail ParticipantADestructiveInspect
Send an email to a participant (by GrowSurf participant ID or email). Provide EITHER emailType to trigger one of the program's configured email templates, OR subject + body for a free-form email (optionally preheader). Free-form emails are sent with the same compliance handling (company name, postal address, and an unsubscribe link are added automatically, and unsubscribed participants are suppressed). Sending requires the team to be verified by GrowSurf and a verified custom email domain on the program (set up in Campaign Editor > 3. Emails > Email Settings). Returns 400 until one is verified. The email is accepted for delivery. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Free-form HTML body. You can personalize it with dynamic text, inserting `{{...}}` tokens like `{{firstName}}` or `{{shareUrl}}`. See [Guide to using dynamic text in GrowSurf emails](https://support.growsurf.com/article/213-guide-to-using-dynamic-text-in-growsurf-emails). | |
| subject | No | Free-form subject. Supports dynamic text (`{{...}}` tokens), the same as the body. | |
| emailType | No | The program email template to trigger. Send the camelCase key; the available types depend on the program type. The template's `isEnabled` setting controls automatic sends only, so this tool can trigger any sendable template. System and transactional types (login link, payout destination confirmation, tax) and the invite email cannot be sent. Referral programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referralLinkUsed`, `referredSignup`, `welcomeReferred`, `goalAchieved`, `campaignEndedWinners`, `campaignEndedNonWinners`, `progressUpdateMonthly`. Affiliate programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referredSignup`, `commissionGenerated`, `commissionAdjusted`, `payoutPending`, `payoutSentSuccess`, `progressUpdateMonthly`. | |
| preheader | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | The email was accepted for delivery. |
| success | No | Whether the email request was accepted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly=false, destructiveHint=true, idempotent=false), the description discloses compliance handling, automatic unsubscribe suppression, the 400 error until verification, and that the email is only accepted for delivery. This gives the agent accurate expectations for side effects and prerequisites without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence adds operational value: mode selection, compliance behavior, prerequisites, error behavior, delivery semantics, and campaign targeting. The most important usage instruction is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, conditional tool with no required fields in the schema, the description explains the key branching constraints, prerequisites, default campaign targeting, and async acceptance. The output schema supplies return details, so no critical context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions already cover body, subject, emailType, and campaignId; the tool description adds the participant-by-ID-or-email contract and the optional preheader role. It doesn't define preheader semantics or email formats in detail, but combined with the oneOf schema constraints an agent has enough to construct valid calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Send an email to a participant (by GrowSurf participant ID or email)' and immediately defines the two modes (template or free-form). This makes it clearly distinct from sibling tools like growsurf_update_campaign_emails (configuration) and growsurf_trigger_referral (side-effect trigger).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to provide emailType versus subject+body, and states that sending depends on team verification and a verified custom email domain. It doesn't name alternatives among siblings or formalize exclusions, but the choice-of-input guidance is concrete and sufficient for selecting this tool and its call form.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_embeddable_element_snippetEmbeddable Element SnippetBRead-onlyIdempotentInspect
Generate the HTML snippet for a GrowSurf embeddable element (with optional auth attributes).
| Name | Required | Description | Default |
|---|---|---|---|
| element | Yes | ||
| participant | No | ||
| withAuthAttributes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds that the output is HTML and may include auth attributes, but it does not clarify what those attributes do, what side effects they imply, or whether participant data becomes embedded in the snippet.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler or redundant wording. It conveys the core action and the main optional capability efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the nested participant object, enum choices, and the withAuthAttributes flag, the description is too thin. It does not explain what participant is for, when auth attributes should be used, or how the returned snippet relates to the embeddable element. The output schema covers return shape but not the decision-making needed for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, but it only hints at 'embeddable element' and 'optional auth attributes.' It does not explain the participant object or provide meaning for the element enum values, leaving a significant semantic gap for the agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Generate') and a specific resource ('HTML snippet for a GrowSurf embeddable element'), making the tool's basic purpose clear. It is distinct from the many campaign/analytics tools, though it does not explicitly differentiate itself from sibling snippet-oriented tools like client_snippets or grsf_config_snippet.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance about when to use this tool versus alternatives, no prerequisites, and no exclusions. An agent is given no context about when an embeddable element snippet is the right choice compared to other snippet or integration tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaignGet ProgramARead-onlyIdempotentInspect
Fetch your GrowSurf campaign (program) details via REST. Embedded reward settings do not establish that an individual reward was earned, approved, or delivered; read the affected participant for earned reward records. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The program's unique id. |
| name | No | The program name (internal only, never shown to participants). |
| type | No | The program type. |
| status | No | The program status. |
| rewards | No | The program's reward configs (`CampaignReward`). Item shape is documented on the `growsurf_list_campaign_rewards` tool. |
| currencyISO | No | The program currency as an ISO 4217 code (e.g. `USD`). |
| inviteCount | No | Total invites sent by participants. |
| winnerCount | No | Participants with at least one approved reward. |
| referralCount | No | Total referrals. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| impressionCount | No | Total referral-link views across participants. |
| participantCount | No | Total participants. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds a meaningful caveat beyond that: embedded reward settings do not prove individual rewards were earned, approved, or delivered, and the affected participant should be read instead. This is valuable behavioral context not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core action is stated first, followed by a critical reward-setting caveat and the campaign targeting rule. No redundant or self-evident content is included.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter, read-only tool with an output schema and strong annotations, the description is complete enough. It covers what the tool fetches, how the target campaign is chosen, and an important interpretation caveat about reward settings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already explains campaignId, its default to GROWSURF_CAMPAIGN_ID, and the use of ids from growsurf_create_campaign. The description restates the default behavior but adds no new parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a clear verb and resource: 'Fetch your GrowSurf campaign (program) details via REST.' It distinguishes the tool as a single-campaign getter, but 'details' is somewhat general and does not explicitly disambiguate it from sibling resources like get_campaign_design, get_campaign_emails, or get_campaign_options.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: call this when you need the core campaign/program details for a specific campaign. It provides the campaignId/fallback selection logic but gives no explicit guidance on when to prefer this over list_campaigns, get_campaign_analytics, or update_campaign.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_activation_analyticsGet Activation AnalyticsARead-onlyIdempotentInspect
Fetch strict activation for eligible participants in one enrollment cohort. Referral programs group by enrolledAsAdvocateAt; affiliate programs group by approvedAsAffiliateAt. The ordered stages are ELIGIBLE, PORTAL_VIEWED, SHARE_ACTION, UNIQUE_REFERRAL_VISIT, LEAD, and CREDITED_REFERRAL. Each participant gets the selected 7- or 30-day observation window. Omit both cohort bounds for the latest fully matured cohort. Read coverageStartAt, state, and reason before interpreting a null or zero; unavailable history does not mean an action never happened. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| cohortTo | No | Exclusive eligibility-cohort end, Unix timestamp in ms. Must be greater than `cohortFrom`. | |
| timezone | No | IANA timezone used to advance cohort boundaries. Defaults to `UTC`. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| cohortFrom | No | Inclusive eligibility-cohort start, Unix timestamp in ms. Use with `cohortTo`. | |
| cohortInterval | No | Bucket size for `cohorts`. Defaults to `day`. | |
| observationWindowDays | No | Days after eligibility in which stages can count. Defaults to `30`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cohorts | No | Selected range split into exact half-open eligibility-cohort buckets. |
| timezone | No | IANA timezone used to advance cohort boundaries. |
| aggregate | No | Strict activation metrics for one exact enrollment cohort. |
| programType | No | Program eligibility model. |
| cohortInterval | No | Bucket size for `cohorts`. |
| coverageStartAt | No | Earliest expected complete activation capture time (Unix ms), or `null` until coverage begins. |
| portalViewedLabel | No | Program-specific display label for the stable `PORTAL_VIEWED` stage. |
| metricContractVersion | No | Shared activation and engagement metric version. |
| observationWindowDays | No | Days after eligibility in which stages count. |
| portalViewedHelperText | No | Display definition for a qualifying signed-in portal view. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint, idempotentHint, and destructiveHint, so the description does not need to repeat those. It adds valuable behavioral details: the distinction between referral and affiliate grouping, the ordered stages, and the observation window. It also warns that unavailable history does not mean an action never happened, which is critical for interpreting data. The only minor gap is not describing pagination or limits, but for a read-only analytics call, this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense with important details but is organized logically: purpose, group-by, stages, observation window, cohort bounds default, coverage caveat, and targeting default. Some redundancy with the schema exists (e.g., cohort bounds), but the added context is not superfluous. It could be slightly more concise but remains focused.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema (mentioned as exists), so return structures are covered there. The description covers all critical aspects: cohort definition, grouping logic, stages, observation window, defaults, and interpretation caveats. For a read-only analytics tool with no required parameters, this is comprehensive and leaves no major ambiguity for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides detailed descriptions for all parameters (100% coverage). The description adds meaning by explaining that cohortFrom/cohortTo define eligibility cohort bounds and that omitting them gets the latest matured cohort, which is not in the schema. It also clarifies the meaning of observationWindowDays by stating it is 'days after eligibility'. Thus it goes beyond the schema for some parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific verb 'Fetch' and the resource 'activation analytics for eligible participants in one enrollment cohort'. It distinguishes itself from sibling tools like growsurf_get_campaign_analytics by focusing on activation funnel stages and cohort grouping. The stages are enumerated, so an agent knows exactly what data to expect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool versus alternatives, such as referring to sibling tools like growsurf_get_campaign_analytics for broader analytics. It also explains critical usage context: cohort bounds omission for the latest matured cohort, the need to read coverageStartAt and state before interpreting nulls, and the default targeting behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_analyticsGet Program AnalyticsARead-onlyIdempotentInspect
Fetch analytics for your GrowSurf program: participants, referrals, impressions, per-channel shares, and affiliate revenue, commission, and payout metrics when applicable. For what impressions, unique impressions, leads, and referrals mean, or why counts differ from another analytics tool, call growsurf_troubleshoot_referral_tracking with symptom numbers_do_not_match rather than guessing. Pass interval (day, week, or month) for a per-period series. Pass comma-separated include values for previousPeriod, statusCounts, rates, email, or engagement. engagement groups unique active, sharing, repeat, and retained participants by when portal views and share actions occurred. Its coverageStartAt, state, and reason distinguish measured zeroes from partial or unavailable history. Scope the timeframe with days (default 365, max 1825) or an explicit startDate/endDate window (Unix ms). timezone and platform apply to engagement only. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| endDate | No | End of the timeframe, Unix timestamp in ms. | |
| include | No | Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view. | |
| interval | No | day/week/month adds a per-period `series`; total (default) returns totals only. | |
| platform | No | Client-platform filter for engagement. Defaults to `ALL`. | |
| timezone | No | IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`. | |
| startDate | No | Start of the timeframe, Unix timestamp in ms. Use with endDate instead of days. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Sent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window. | |
| rates | No | Derived referral rates, each a ratio from 0 to 1. Present only when `include` contains `rates`. |
| series | No | Per-period totals in ascending order. Present only when `interval` is `day`, `week`, or `month`. |
| endDate | No | End of the analytics timeframe, as a Unix timestamp in milliseconds. |
| analytics | No | Analytics totals: `invites`, `impressions`, `uniqueImpressions`, `participants`, `referrals`, `referralCreditPendings`, `referralCreditExpireds`, per-channel share counts (`emailShares`, `twitterShares`, `copyRefLinkShares`, ...), and for affiliate programs `totalRevenue` and `totalCommissions` (in minor currency units (e.g. cents)) plus `totalCommissionCount` and `uniqueCommissionReferrals`. |
| startDate | No | Start of the analytics timeframe, as a Unix timestamp in milliseconds. |
| engagement | No | Opt-in participant engagement grouped by when activity occurred. |
| statusCounts | No | Status-count breakdowns: dashboard-aligned reward counts, and for affiliate programs `affiliateStatus`, `commissionStatus`, and `payoutStatus` (counts and amounts in minor currency units (e.g. cents)). Present only when `include` contains `statusCounts`. |
| previousPeriod | No | Totals for the equal-length window immediately before the requested one (`analytics`, `startDate`, `endDate`). Present only when `include` contains `previousPeriod`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool readOnly, idempotent, and non-destructive; the description adds genuinely useful behavioral context beyond that: engagement counts may be partial or unavailable, coverageStartAt/state/reason distinguish measured zeroes, counts may differ from other analytics tools, timezone/platform apply only to engagement, and campaignId falls back to GROWSURF_CAMPAIGN_ID. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place. It front-loads purpose and troubleshooting routing before parameter details, and it avoids filler or repetition of the schema. The structure flows from what the tool does, to when not to use it, to how to shape the request.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter read-only tool with an output schema and strong annotations, the description covers all call-relevant behaviors: target campaign fallback, optional include values, engagement semantics, timeframe selection, and interval behavior. The output schema can carry return-value details, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 88% schema description coverage, the baseline is 3, but the description adds substantial meaning: it explains comma-separated include values, what engagement groups and its state fields mean, that timezone/platform only affect engagement, days default/max versus startDate/endDate windows, and how to use campaignId from growsurf_create_campaign without restarting. This goes well beyond the input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch analytics for your GrowSurf program' and enumerates the metric categories returned. It also routes definitional and discrepancy questions to growsurf_troubleshoot_referral_tracking, which helps distinguish it from that sibling, though it does not explicitly differentiate from growsurf_get_campaign_activation_analytics or growsurf_get_participant_analytics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit when-not: for metric meanings or count mismatches, call growsurf_troubleshoot_referral_tracking with symptom 'numbers_do_not_match' rather than guessing. It also explains conditions for interval, include, engagement, and campaignId fallback. It stops short of stating when to prefer this over activation analytics or participant analytics, but the guidance is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_designGet Program DesignARead-onlyIdempotentInspect
Fetch the configured design fields for your GrowSurf program, including GrowSurf Window content, colors, sharing sections, participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, participant sign-in copy under login, payout-destination confirmation page copy under payoutDestinationConfirmation, and country-name overrides under countryLabels. participantAvatarStyle is CHARACTERS, INITIALS, ANIMALS, or GRADIENT; missing or unknown values mean INITIALS. The confirmation section is omitted when no confirmation fields are stored. Stored null fields are returned as null; omitted and null fields use localized defaults. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| login | No | The returning-participant sign-in form plus its success, resend, validation, and error text. |
| share | No | Share channels, invite settings, and share-button styling. |
| stats | No | The participant's referral-progress stats panel. Only `title` is editable. |
| theme | No | Visual theme styling (colors, shadows, and similar). |
| header | No | Header content for participants (`postText`) and non-participants (`preText`). |
| signup | No | Signup form fields, GDPR consent, and button and login text. |
| window | No | Layout of the GrowSurf window (`navigationMode`: `TABS` or `LIST`). |
| payouts | No | Affiliate programs only. The Payouts section of the participant portal. |
| rewards | No | Heading, icon, and empty-state text of the rewards panel. |
| resources | No | Participant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools. |
| commissions | No | Affiliate programs only. The Commissions section of the participant portal. |
| leaderboard | No | The leaderboard section: labels, selectors, and name masking. |
| landingPages | No | Portal and landing pages: company info, `content`, `styles`, third-party script ids, and SEO meta tags. |
| countryLabels | No | Participant-facing country-name overrides keyed by ISO 3166-1 alpha-2 code (for example `GB`). Each label replaces the default country name wherever participants pick a country, such as payout and tax forms. Overrides merge per code on `PATCH`; `null` (or the default name) restores a code's default. Only overridden codes are returned. |
| referralStatus | No | The section listing who a participant invited and each invite's progress. |
| referralSummary | No | Referral programs only. The participant's row of summary tiles (clicks, leads, referrals, rewards). |
| affiliateSummary | No | Affiliate programs only. The affiliate's row of summary tiles (clicks, revenue, payouts). |
| referredExperience | No | The banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs. |
| participantSettings | No | The participant's account settings area (logout, PayPal and Wise payout confirmation/status messages, tax details). |
| participantAvatarStyle | No | How participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`. |
| payoutDestinationConfirmation | No | Customizable text for the payout-destination confirmation page opened from payout integration cards. One shared set applies to every enabled payout provider. Provider-aware text may use `{{payoutProvider}}`; omitted and `null` fields use localized defaults. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description goes well beyond this by disclosing enum fallback behavior for `participantAvatarStyle`, omission of the confirmation section when no fields are stored, null versus omitted field handling, and localized defaults. These are behavioral traits an agent cannot infer from the annotations alone, making the description highly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but every sentence conveys essential behavior: field inventory, enum values and fallback, null semantics, section omission, and campaign targeting. It is front-loaded with the core action and resource, and code identifiers are used precisely to avoid ambiguity. It loses one point only because the null/default behavior could have been compressed without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only getter with one optional parameter and an output schema present, the description covers everything needed to invoke it correctly: what fields are returned, enum valid values and default, null behavior, omitted-section behavior, localized defaults, and campaign selection. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for the single `campaignId` parameter, including its default and how to obtain it from growsurf_create_campaign. The description restates the targeting default but does not add new parameter semantics beyond the schema. Per the rubric, baseline 3 is appropriate when the schema carries the load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch the configured design fields for your GrowSurf program.' It enumerates the exact field groups returned (GrowSurf Window content, colors, sharing sections, avatar styles, Claim Offer Popup, login copy, payout confirmation copy, country labels), which unambiguously distinguishes it from sibling tools like growsurf_get_campaign or growsurf_get_campaign_emails. The inclusion of specific code paths such as `participantAvatarStyle` and `countryLabels` removes any ambiguity about scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The primary use case is implied by the purpose: call this when you need the read-only design configuration of a GrowSurf program. The description does clarify the campaign targeting behavior ('Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), which is useful operational guidance. However, it does not explicitly state when to prefer this over alternatives or when not to use it, leaving the agent to infer routing from the tool name and sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_emailsGet Program EmailsARead-onlyIdempotentInspect
Fetch the Emails tab configuration for your GrowSurf program (participant and admin email templates and settings). Returns the full object with every field and its current value — the same shape you send back on update. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| invite | No | The invitation email a participant sends to friends. `useCompanyReplyTo` sets who receives replies. |
| settings | No | Sender (`sender`), physical contact address (`contact`), and shared design (`design`) settings. The design object includes `unsubscribeAffiliateInvite` for direct affiliate invitation emails. |
| loginLink | No | One-time sign-in link for returning participants. Transactional; its toggle cannot be changed. |
| goalAchieved | No | Sent when a participant unlocks a reward. Referral programs only. |
| offerClaimed | No | Sent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed. |
| payoutPending | No | Sent when a payout is on the way. Affiliate programs only. |
| referredSignup | No | Sent to a referrer each time someone signs up using their link. Referral and affiliate programs. |
| taxInfoMissing | No | Asks a participant to submit required tax information. Transactional; its toggle cannot be changed. |
| inviteAffiliate | No | Invites a prospective affiliate to join the program. Its body must keep `{{affiliateInviteLink}}`. Affiliate programs only. Promotional; its toggle can be changed. |
| taxInfoApproved | No | Tells a participant their tax form is complete and approved. Transactional; its toggle cannot be changed. |
| taxInfoReceived | No | Confirms submitted tax information was received. Transactional; its toggle cannot be changed. |
| taxInfoRejected | No | Tells a participant their tax information needs to be resubmitted. Transactional; its toggle cannot be changed. |
| welcomeReferred | No | Welcome email for someone who signs up through a referral link. Referral programs only. |
| referralLinkUsed | No | Sent to a referrer when they earn referral credit. Referral programs only. |
| payoutSentSuccess | No | Sent when a payout completes. Affiliate programs only. |
| commissionAdjusted | No | Sent when a commission is adjusted after a refund or chargeback. Affiliate programs only. |
| welcomeNonReferred | No | Welcome email for a participant who joins without being referred. Referral and affiliate programs. |
| commissionGenerated | No | Sent to an affiliate when they earn a new commission. Affiliate programs only. |
| campaignEndedWinners | No | Sent to reward winners when the program ends. Referral programs only. |
| progressUpdateMonthly | No | Month-end progress recap for participants. Referral and affiliate programs. |
| campaignEndedNonWinners | No | Sent to non-winners when the program ends. Referral programs only. |
| payoutDestinationChanged | No | Tells a participant their payout destination changed. Its body must keep `{{payoutDestinationMaskedEmail}}`. Referral and affiliate programs. Transactional; its toggle cannot be changed. |
| affiliateApplicationDenied | No | Tells an applicant their affiliate application was not approved. Affiliate programs only. Transactional; its toggle cannot be changed. |
| referralLinkViewedFirstTime | No | Sent the first time a participant's referral link is viewed. Referral and affiliate programs. |
| affiliateApplicationApproved | No | Tells an applicant their affiliate application was approved. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateApplicationReceived | No | Confirms an affiliate application was received and is under review. Affiliate programs only. Transactional; its toggle cannot be changed. |
| payoutDestinationConfirmation | No | Asks a participant to confirm the payout destination where they will receive payouts, such as a PayPal or Wise email address. Its body may use `{{payoutProvider}}` and must keep `{{payoutDestinationConfirmationLink}}`. Referral and affiliate programs. Transactional; its toggle cannot be changed. |
| affiliateApplicationStatusLink | No | Sends an applicant a secure link to view their application status. Its body must keep `{{applicationStatusLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateEmailChangeVerification | No | Asks an affiliate to confirm a new account email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateApplicationEmailCorrection | No | Asks an applicant to confirm a corrected email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: it returns the full object with every field and current value, the shape matches the update payload, and the campaignId defaults to GROWSURF_CAMPAIGN_ID when omitted. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly written sentences with no wasted words. The core action and scope are front-loaded, followed by the return shape and defaulting behavior. Every sentence adds necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter, full schema coverage, an output schema, and safety-related annotations, the description is complete. It tells the agent what is returned, how the parameter behaves, and how the result relates to updates. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single campaignId parameter, and the schema already explains the default behavior and the relationship to growsurf_create_campaign. The description repeats the defaulting behavior but does not meaningfully add beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Fetch') and a specific resource ('Emails tab configuration for your GrowSurf program'), and clarifies the scope as participant and admin email templates and settings. It clearly differentiates this read tool from related siblings like growsurf_get_campaign and growsurf_update_campaign_emails by naming the exact configuration area and noting the returned object is the same shape used on update.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes this tool is for reading the current Emails tab configuration, and the phrase 'the same shape you send back on update' implicitly points to growsurf_update_campaign_emails as the companion write tool. It does not explicitly name alternatives or list when not to use it, but the usage context is clear enough for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_installationGet Program InstallationARead-onlyIdempotentInspect
Fetch the Installation tab configuration for your GrowSurf program (embed/installation and tracking setup). Returns the full object with every field and its current value — the same shape you send back on update. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mobile | No | GrowSurf iOS and Android SDK settings. |
| signup | No | Custom signup-form settings (used with `FORM_DETECTION`). |
| shareUrl | No | The landing page referred friends reach from a referral link. Set this before adding other origins to `allowedUrls`. |
| allowedUrls | No | Every additional browser origin where the GrowSurf Window or SDK may run, including development origins such as `http://localhost:3000`. Preserve the full array when patching it. An origin absent from both `shareUrl` and this list can return `403`. |
| signupEvent | No | The signup tracking method: automatic form detection, or participants added via the SDKs and REST API. |
| referralTrigger | No | Referral programs only. `ON_SIGNUP` counts a referral as soon as the friend signs up; `CUSTOM` also requires a qualifying action. |
| useGrowSurfHostedLinks | No | Use GrowSurf-hosted referral links that route clicks by the visitor's device. Mainly for mobile apps. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, and non-destructive behavior. The description adds useful context beyond that: it returns the full object in the exact shape used for update and describes the default campaignId behavior (GROWSURF_CAMPAIGN_ID). No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, purposeful sentences: what it fetches, what it returns and how that relates to updates, and the parameter targeting default. Every sentence earns its place, and the most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, read-only getter with one optional parameter and an output schema, nothing important is missing: the resource, response shape, and default behavior are all covered. An agent can invoke it correctly without guessing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the only parameter. The description repeats the defaulting behavior already stated in the schema and adds little extra semantic meaning. This sits at the baseline for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses the specific verb 'Fetch' with a clearly defined scope: the Installation tab configuration (embed/installation and tracking setup). This sets it apart from sibling getters like growsurf_get_campaign_design or growsurf_get_campaign_emails, though it doesn't explicitly name them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Makes the context clear: call this when you need the Installation tab configuration for a GrowSurf program. The phrase 'same shape you send back on update' naturally links it to update_campaign_installation. It doesn't explicitly list exclusions, but the purpose is clear enough for the agent to choose this over sibling getters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaign_optionsGet Program OptionsARead-onlyIdempotentInspect
Fetch the Options tab configuration for your GrowSurf program (referral triggers, anti-fraud lists and toggles, affiliate enrollment and application review, notifications, and other behavior options). Returns the full object with every field and its current value, the same shape you send back on update. autoFulfillRewards: false permits manual fulfillment and does not prove that any reward went undelivered. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fraud | No | Anti-fraud settings: `blockedEmails`/`blockedIps`/`blockedCountries` and matching allow lists, `blockBurnerEmails`, `blockDataCenterIps`, `blockHighRiskReferrers`, `autoBlockHighRiskIps`, per-IP signup rate limits, and `recaptcha`. |
| autoBlockFraud | No | Automatically block signups flagged as high fraud risk. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| payoutThreshold | No | Affiliate programs only. Minimum payout in minor currency units (e.g. cents). `0` or `null` means no minimum. |
| taxDocumentation | No | Affiliate programs only. Company billing details (name, address, VAT number) used on affiliate payout invoices and for VAT handling. |
| autoFulfillRewards | No | Referral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure. |
| notificationEmails | No | Owner notification settings: `recipients` plus per-event `events` toggles. |
| blockPaidAdsTraffic | No | Do not attribute referrals from visitors who arrived through paid ads. |
| enforceGdprCompliance | No | Store only the minimum participant data (no IP addresses, fingerprints, or mobile instance ids). |
| requireParticipantAuth | No | Require returning participants to authenticate. Affiliate programs require `true`. |
| affiliateApplicationMode | No | Affiliate programs only. How public signups join the program. `OPEN_ENROLLMENT` enrolls them directly; `MANUAL_REVIEW` collects an application you approve or deny; `AUTO_APPROVE` collects the application and approves it immediately. A reviewed mode requires the program's published application page. Enrollment through the API, CSV import, dashboard, or invites is never blocked by this setting. |
| referralCookieWindowDays | No | How long a referral-link click is remembered in the visitor's browser, in days. |
| referralCreditWindowDays | No | How long a referred friend has to complete the qualifying action, in days. `null` means the credit never expires. |
| requireManualFraudApproval | No | Flag suspected fraud for review instead of blocking signups automatically. |
| requireManualRewardApproval | No | Referral programs only. Hold each earned reward for manual approval before it unlocks. |
| affiliateReapplicationPolicy | No | Affiliate programs only. Whether a denied applicant may apply again. `AFTER_COOLDOWN` (the default) allows a new application once `affiliateReapplicationCooldownDays` has passed; `DISABLED` never allows one. |
| affiliateReapplicationCooldownDays | No | Affiliate programs only. How many days a denied applicant waits before they can apply again (1-365, default 30). Only used when `affiliateReapplicationPolicy` is `AFTER_COOLDOWN`. |
| affiliateApplicationReviewEstimateBusinessDays | No | Affiliate programs only. Optional review-time expectation shown to pending applicants, in business days (1-60). `null` clears it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description reveals the full-object return shape, round-trip compatibility with the update operation, the autoFulfillRewards interpretation caveat, and the default target behavior. This adds meaningful operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the purpose and contents, the return shape and update symmetry, and a non-obvious interpretation caveat plus targeting default. The core purpose is front-loaded with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only getter with one optional parameter, an output schema, and safety annotations, the description fully covers target selection, return shape, and a key interpretation pitfall. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the optional campaignId parameter already has a thorough description including default behavior and its use with growsurf_create_campaign. The prose description only restates the default targeting behavior, adding no new semantic information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses specific verb 'Fetch' and resource 'Options tab configuration', enumerating concrete contents such as referral triggers, anti-fraud lists, notifications, and behavior options. This clearly distinguishes it from sibling getters like get_campaign_design and get_campaign_emails.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context: use this to read the Options tab configuration, and it explains how campaignId targeting works. It doesn't explicitly name alternatives or exclusions, but the domain is specific enough that an agent can infer when to select this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_integration_connect_linkGet Integration Connect LinkARead-onlyIdempotentInspect
Return a dashboard link that opens a specific integration's connect panel in the GrowSurf Program Editor (Options > Integrations). Use this whenever a user says they want to connect an integration, for example "connect Stripe", "set up PayPal or Wise payouts", "send Tango Card gift cards", or "sync signups to Mailchimp": call it with the integration key and give the user the returned url to open. Connecting an integration happens in the dashboard, not through the API. GrowSurf cannot link a Stripe, PayPal, Wise, or other account on the user's behalf, so hand them the link. integration must be one of the supported keys (some are camelCase, e.g. constantContact, helpScout). The link points at GROWSURF_CAMPAIGN_ID; pass campaignId to target a different program. The program is checked before the link is returned, and the result also reports whether the integration is already connected, enabled, or autoDisabled, so you can skip handing over a link the user does not need. If that check cannot run, programVerified comes back false and you still get a working production link. Tango Card, Tremendous, and Bask Health apply to referral programs only. Wise applies to affiliate programs only.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program for the link. Defaults to GROWSURF_CAMPAIGN_ID. | |
| integration | Yes | The integration to connect. Must exactly match one of the supported keys (for example `wisecom`; some are camelCase, e.g. `constantContact`, `campaignMonitor`, `helpScout`, `pabblyConnect`, `baskHealth`). |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Dashboard link that opens the integration's connect panel. |
| note | No | Instructions to relay to the user. |
| label | No | Human-readable integration name. |
| enabled | No | Whether the integration is switched on and currently working. Present only when `programVerified` is `true`. |
| category | No | The integration's category. |
| connected | No | Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`. |
| integration | No | The integration key that was requested. |
| autoDisabled | No | Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`. |
| referralOnly | No | `true` when the integration applies to referral programs only. |
| affiliateOnly | No | `true` when the integration applies to affiliate programs only. |
| programVerified | No | `true` when the program's live integration list was read, so the program id is confirmed and the three state fields below are present and current. `false` when that read was unavailable, for example without an API key or `program:read`: the link still works but points at the production dashboard, and the state fields are omitted because the state is unknown. Never treat an absent state field as `false`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnly, idempotent, non-destructive, but the description adds significant behavioral context: it explains the program-check that returns connected/enabled/autoDisabled status, the fallback programVerified=false behavior, and integration-specific applicability (Tango Card only for referral, Wise only for affiliate). It describes exactly what the result reveals and how it should influence agent action, going well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with the essential purpose and usage, then covers edge cases. Each sentence contributes new information (parameter notes, return behavior, program constraints) rather than repeating schema or annotations. It could be slightly trimmed to improve scannability, but all content is relevant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers everything an agent needs to correctly invoke this tool: when to use, how to pass parameters, what the response contains (including status flags), fallback behavior, and program-specific restrictions. With an output schema present, it doesn't need to detail return formatting. The combination of output schema and this description leaves no gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters, so baseline is 3. The description adds value by clarifying camelCase keys (constantContact, helpScout), the default for campaignId (GROWSURF_CAMPAIGN_ID), and program-specific applicability of certain integrations. This goes beyond the schema's basic descriptions and helps avoid mis-selection.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it returns a dashboard link that opens an integration's connect panel, with specific action verbs and resource. It gives concrete example user intents (connect Stripe, set up PayPal, send Tango Card) that distinguish it from other integration-related tools like list_integrations. This is a specific, non-tautological purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'Use this whenever a user says they want to connect an integration' and provides trigger examples. It also explains when NOT to use it (connections happen in dashboard, not via API) and the behavior of the program-check (skip handing over unneeded links). While it doesn't name sibling alternatives, it gives complete contextual guidance for when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_participantGet ParticipantARead-onlyIdempotentInspect
Fetch a single participant by GrowSurf participant ID or email address. referralStatus describes credit to their referrer; referralCount counts referrals this participant generated, so zero is consistent with CREDIT_AWARDED. In rewards, approved records approval; status, isFulfilled, and fulfilledAt record fulfillment marking, not confirmation of delivery. Use growsurf_list_participants first if you need to find a participant ID. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The participant's unique id. |
| rank | No | All-time leaderboard rank. |
| No | The participant's email address. | |
| isNew | No | `true` when the request created the participant. Returned by participant creation calls. |
| notes | No | Internal notes. Never shown to participants. |
| rewards | No | Rewards the participant has earned. |
| isWinner | No | `true` once the participant has earned at least one reward. |
| lastName | No | The participant's last name. |
| metadata | No | Custom key/value metadata (single level). |
| referrer | No | Summary of the participant's referrer (same core fields as a participant). Present only when the participant was referred. |
| shareUrl | No | The participant's unique referral link. Omitted for affiliate program participants who are not approved affiliates. |
| createdAt | No | When the participant joined, as a Unix timestamp in milliseconds. |
| firstName | No | The participant's first name. |
| ipAddress | No | IP address recorded for the participant, or `null`. |
| referrals | No | Ids of participants they successfully referred (100 most recent). |
| referredBy | No | Id of the referrer. Present only when the participant was referred. |
| shareCount | No | Share counts keyed by channel (e.g. `email`, `facebook`, `twitter`, `copyRefLink`, `iosNativeShare`). |
| vanityKeys | No | The participant's vanity keys. |
| fingerprint | No | Browser identifier recorded for the participant, or `null`. |
| inviteCount | No | Invites sent by the participant. |
| isAffiliate | No | Affiliate programs only. Whether this participant is an enrolled affiliate. A referred customer who has not joined the program is `false`. |
| monthlyRank | No | Current-month leaderboard rank (resets monthly). |
| unsubscribed | No | `true` if the participant unsubscribed from program emails. |
| referralCount | No | All-time referrals credited to the participant. |
| fraudRiskLevel | No | The participant's fraud risk level. |
| payoutSettings | No | Actions the participant must complete before a payout can be released. Always present. |
| referralSource | No | How the participant joined the program. |
| referralStatus | No | The referrer's credit status for this participant. Present only when the participant was referred. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| affiliateStatus | No | Affiliate programs only. The enrolled affiliate's status (`APPROVED`, `SUSPENDED`, or `BANNED`). `null` for participants who are not affiliates. |
| fraudReasonCode | No | Reason code behind `fraudRiskLevel` (e.g. `UNIQUE_IDENTITY`, `DUPLICATE_EMAIL`, `MANUAL_UPDATE`). |
| impressionCount | No | Total views of the participant's referral link. |
| prevMonthlyRank | No | Previous-month leaderboard rank. |
| mobileInstanceId | No | App-install scoped identifier supplied by a native app, or `null`. |
| monthlyReferrals | No | Ids of participants they successfully referred this month (100 most recent). |
| paypalEmailAddress | No | PayPal email address on file, used for affiliate or PayPal reward payouts. |
| unreadPayoutsCount | No | Payouts the participant has not yet viewed. Affiliate programs only. |
| monthlyReferralCount | No | Referrals credited this month (resets monthly). |
| allMatchingFraudsters | No | Other participants flagged as matching this participant during anti-fraud checks. |
| uniqueImpressionCount | No | Unique views of the participant's referral link. |
| unreadCommissionsCount | No | Commissions the participant has not yet viewed. Affiliate programs only. |
| prevMonthlyReferralCount | No | Referrals credited the previous month. |
| affiliateEnrollmentSource | No | Affiliate programs only. How the affiliate enrolled (`OPEN_ENROLLMENT`, `APPLICATION`, `PARTICIPANT_AUTH`, `INVITE`, `REST_API`, `CSV`, or `DASHBOARD`). `null` when not recorded. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive behavior; the description adds valuable field-level semantics, including that referralStatus describes credit to the referrer, zero referralCount can coexist with CREDIT_AWARDED, and rewards fulfillment fields are not delivery confirmation. It also discloses how campaignId targets the request.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences with no filler. The primary purpose is front-loaded, the field-semantics caveats are grouped logically, and the sibling routing/default behavior closes the description efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-object read with an output schema and read-only annotations, the description covers every invocation decision: identity lookup, campaign scoping, ID discovery, and tricky return-field semantics. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (33%), so the description compensates by identifying participantId and participantEmail as the two lookup keys and explaining campaignId's default behavior. It doesn't give formats or constraints, but each parameter's role and selection condition are clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise action ('Fetch a single participant') and the two lookup keys (participant ID or email address). The 'single' qualifier cleanly distinguishes it from growsurf_list_participants and other participant-specific siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly directs the agent to growsurf_list_participants when a participant ID is unknown, and explains campaignId's optional targeting versus the GROWSURF_CAMPAIGN_ID default. It doesn't enumerate exclusions against analytics/activity-log siblings, but the context is clear enough for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_participant_activity_logsGet Participant Activity LogsARead-onlyIdempotentInspect
List a participant's activity logs (by GrowSurf participant ID or email), most recent first, offset/limit paginated. limit is 1-100 (default 20); offset skips logs. The response offset is the cursor for the next page (null when there are no more). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Number of activity logs returned per page. |
| offset | No | Offset for the next page, or `null` when there are no more logs. |
| activityLogs | No | Activity log entries for the participant. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description does not need to cover safety. It adds valuable behavioral details beyond annotations, including the offset-as-cursor pagination behavior, the default limit, and the campaignId fallback to GROWSURF_CAMPAIGN_ID. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose, and includes all necessary operational details without redundancy. Every clause adds value, covering lookup methods, ordering, pagination, defaults, and campaign targeting.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with annotations covering safety and an output schema existing, the description is nearly complete. It covers pagination, defaults, and campaign targeting, but does not explicitly state that at least one of participantId or participantEmail is required (though the anyOf schema implies it). This minor gap keeps it from a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 20% (only campaignId has a description), so the description must compensate. It thoroughly explains limit and offset semantics, including default values and cursor usage, clarifies participant lookup methods, and describes campaignId behavior. This goes well beyond the sparse schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and the resource 'participant's activity logs', and specifies lookup by participant ID or email, most recent first, with pagination. It is specific enough to distinguish from siblings like growsurf_get_participant or growsurf_list_participants, though it does not explicitly name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides usage context such as pagination parameters, default limit, and campaignId targeting, but does not mention when to prefer this tool over alternatives like growsurf_get_participant_analytics. The usage is implied rather than explicitly contrasted with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_participant_analyticsGet Participant AnalyticsARead-onlyIdempotentInspect
Fetch analytics for one participant by GrowSurf participant ID or email. The base response includes all-time engagement, rank, share, and applicable affiliate revenue, commission, and payout metrics. Add activation to include for the program-specific eligibility anchor and covered first milestones, including firstPortalViewedAt and firstShareChannel. A null milestone with a partial or unavailable state is unknown, not proof that the action never happened. Request both activation and series for covered portalViews and shareActions buckets. Date-window parameters filter optional series and email data, not the base response or activation milestones. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Number of days for optional `series` and `email` analytics. Does not filter the all-time base response. | |
| endDate | No | End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`. | |
| include | No | Comma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values. | |
| interval | No | Bucket size for `series` and email series. Defaults to `day`. | |
| startDate | No | Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Sent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window. | |
| ranks | No | Leaderboard ranks for this participant. |
| series | No | This participant's per-period activity. Present when `include` contains `series`. |
| endDate | No | Window end (Unix ms). Present with `series` or `email`. |
| analytics | No | All-time participant analytics totals. Date-window parameters do not filter these fields. |
| startDate | No | Window start (Unix ms). Present with `series` or `email`. |
| activation | No | Opt-in covered eligibility and first-milestone analytics for one participant. |
| shareCount | No | Per-channel share counts (e.g. `email`, `facebook`, `twitter`). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description adds valuable behavioral detail: base response is all-time, null milestones mean 'unknown' not 'never happened', date-window parameters only affect optional series/email data, and campaign targeting falls back to GROWSURF_CAMPAIGN_ID. This is precisely the kind of context that prevents misinterpreting returned analytics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence contributes: base scope, include options, null semantics, series behavior, date filtering, and campaign targeting. It is front-loaded with the core purpose and then layers detail logically without fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only analytics tool with an output schema, this description covers the key decision points: how to identify the participant, what optional includes exist, how null values should be interpreted, how date filters behave, and which campaign scope is used. No critical calling context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, and the description compensates by explaining the meaning of 'include' values, how date-window parameters interact with optional data, and the campaignId fallback behavior. It adds meaning beyond the schema descriptions, especially regarding activation milestones and null-state interpretation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch analytics for one participant by GrowSurf participant ID or email.' It clearly distinguishes from campaign-level analytics and general participant tools by scoping to one participant's analytics and listing what the response includes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies when to use this tool: to get analytics for a single participant by ID or email, with optional activation and series data. It does not explicitly name alternatives or exclusion conditions, but the scope is specific enough for an agent to differentiate it from sibling tools like growsurf_get_campaign_analytics or growsurf_get_participant.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_participant_payout_destinationGet Payout DestinationARead-onlyIdempotentInspect
Get a participant's payout-destination status (by GrowSurf participant ID or email) across every payout provider enabled for the program (PayPal and/or Wise). For each provider it reports the current status, the confirmed payout email, the legal recipient type, and — when a delivery bounced or a recipient was invalidated — the repair reason. activeProvider is the provider that currently gets paid, or null until the participant confirms one. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| destinations | No | One entry per enabled payout provider describing the participant's destination for it. |
| activeProvider | No | The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL` and `WISECOM`. |
| enabledProviders | No | Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL` and `WISECOM`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and idempotentHint, and the description adds substantial behavioral detail beyond them: it reports per-provider status, confirmed email, legal recipient type, repair reason, and explains the meaning of activeProvider (null until confirmation). This gives an agent an accurate model of what the call returns and how the data behaves without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense but every sentence earns its place: it defines the resource, the lookup modes, the per-provider result fields, the activeProvider semantics, and the campaignId fallback. It is front-loaded with the main purpose and contains no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description doesn't need to re-enumerate return values, and it still covers the essential input modes, provider scope, and fallback behavior. The safety profile is already covered by annotations, making this contextually complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (only campaignId is described), but the description compensates by clarifying that participantId and participantEmail are alternative lookup keys and that campaignId defaults to GROWSURF_CAMPAIGN_ID. It adds meaning beyond the bare schema property types, though it could have provided more detail on expected formats or precedence between the two identifiers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Get') and resource ('a participant's payout-destination status'), and further specifies lookup by GrowSurf participant ID or email. It is clearly distinct from sibling tools like gets participant profile, analytics, or activity logs, so an agent can select it without confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains how to target a campaign ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') and the two accepted lookup keys. It gives clear operational context but does not explicitly state when to prefer this tool over alternative participant-related tools, so it stops short of a full when/when-not guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_teamGet TeamARead-onlyIdempotentInspect
Fetch the team bound to the API key or OAuth connection. verificationStatus is VERIFIED once GrowSurf has verified the team, which is required before a program can email participants. Personal profiles and internal identifiers are not returned. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint, so safety is covered. The description adds value beyond annotations by specifying what is not returned (personal profiles, internal identifiers) and clarifying the meaning of verificationStatus, which is useful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, all informative, with the main purpose front-loaded in the first sentence. No filler or redundancy; each sentence contributes a distinct piece of information (what it fetches, verification meaning, and non-returned data).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With zero parameters, an output schema, and full annotation coverage, the description rounds out the picture by explaining verification semantics and data exclusions. No essential information is missing for a read-only fetch tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics to explain. The description's note about environment variables (API key vs campaign ID) adds relevant configuration context beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Fetch the team bound to the API key or OAuth connection." This clearly identifies the tool's function and distinguishes it from sibling tools like get_campaign or list_campaigns, even without naming an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context by explaining that verificationStatus must be VERIFIED before a program can email participants, implying when this tool is relevant. It also states the credential requirements (requires API key, not campaign ID), which helps route usage, though it does not explicitly name alternative tools or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_grsf_config_snippetParticipant Auto-Auth SnippetARead-onlyIdempotentInspect
Generate the snippet for participant auto-auth using window.grsfConfig (place before the GrowSurf Universal Code).
| Name | Required | Description | Default |
|---|---|---|---|
| hash | No | ||
| No | |||
| campaignId | No | ||
| affiliateJoin | No | ||
| useCampaignIdPlaceholder | No | ||
| enableParticipantAutoAuth | No | ||
| includeAutoAuthCommentHeader | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, idempotentHint=true, destructiveHint=false), so the bar is lower. The description adds meaningful behavioral context by specifying placement in the <head> and the ordering requirement before the GrowSurf Universal Code — a non-obvious constraint that could break the integration if ignored.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with zero filler: the verb and resource are front-loaded, and the parenthetical placement instruction earns its place. There is no redundancy with the title or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters, 0% schema coverage, and no parameter documentation, the description is too thin. Even though an output schema exists to cover return values, an agent cannot reasonably decide how to set enableParticipantAutoAuth, affiliateJoin, useCampaignIdPlaceholder, or how the hash should be computed, making the tool under-specified for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage and 7 parameters, the description carries the full burden of explaining parameters, but it mentions none of them — hash, email, campaignId, affiliateJoin, useCampaignIdPlaceholder, enableParticipantAutoAuth, and includeAutoAuthCommentHeader are all undocumented. The description does nothing to compensate for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Generate') with a concrete resource (the <head> snippet for participant auto-auth) and states the exact mechanism (window.grsfConfig). It also gives installation context ('place before the GrowSurf Universal Code'), making it clearly distinguishable from siblings like growsurf_client_snippets or growsurf_embeddable_element_snippet.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the use case by naming participant auto-auth and the placement constraint relative to the Universal Code, which gives the agent situational context. However, it never explicitly contrasts this tool with alternatives (e.g., when to use this vs. growsurf_client_snippets or growsurf_participant_auth_hash) and provides no exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_integration_guideIntegration GuideCRead-onlyIdempotentInspect
Generate a guided, happy-path GrowSurf integration plan (referral + affiliate).
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| singlePageApp | No | ||
| referralTrigger | No | signup_plus_qualifying_action | |
| webhookSecurity | No | token_in_url | |
| participantAuthEnabled | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, which fully cover the safety/mutation profile; the description does not contradict these. The added 'happy-path' qualifier is a useful behavioral signal that this produces a straightforward plan rather than troubleshooting edge cases (unlike growsurf_troubleshoot_referral_tracking). However, the description does not disclose what the plan contains or its limitations, beyond the happy-path scope.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The single sentence has no wasted words and is well front-loaded. But it is so terse that the tool is under-specified rather than efficiently concise. There is room to add meaningful guidance without sacrificing brevity, so the conciseness is adequate but not exemplary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 5 optional parameters, 3 enums, and an output schema, the description is incomplete. It does not explain how the parameters shape the generated plan, what 'happy-path' means operationally, or how this guide differs from the many sibling guide/snippet/advisor tools. The output schema mitigates some return-value uncertainty, but the description leaves too much about behavior and parameter influence unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% with 5 parameters, so the description bears the full burden of explaining parameter semantics, but it mentions none of them. While parameter names like programType and singlePageApp are fairly self-explanatory, enum values such as 'signup_plus_qualifying_action' and 'token_in_url' are opaque and unaddressed. The description adds zero value to the input schema at a coverage level where it absolutely must compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Generate') with a specific resource ('GrowSurf integration plan') and scopes it as 'guided, happy-path' covering referral and affiliate. This is clear about what the tool produces. However, it does not differentiate from the very similar sibling growsurf_program_design_advisor, which likely also delivers advisory/plan guidance, so an agent could confuse the two.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as growsurf_program_design_advisor, growsurf_api_library_snippets, or growsurf_client_snippets. No exclusions, prerequisites, or context are given. The description merely states what it does, leaving the agent to infer when 'happy-path integration planning' is the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_campaign_rewardsList Campaign RewardsARead-onlyIdempotentInspect
List your GrowSurf program's configured rewards. These settings do not establish that a participant earned or received a reward; inspect their rewards with growsurf_get_participant. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rewards | No | The program's active, visible, and enabled reward configs. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering the safety profile. The description adds meaningful behavioral context beyond the annotations by explaining that this returns configured reward settings, not earned/received rewards, and by noting the campaign targeting fallback. This is useful semantic behavior not present in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no redundant phrasing. The core purpose is front-loaded, the critical exclusion is stated clearly, and the targeting behavior is explained in the final sentence. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with one well-documented parameter, an output schema, and safety-relevant annotations, the description is fully sufficient. It covers what the tool returns, what it does not return, the relevant alternative, and the campaign targeting behavior, leaving no important gap for an agent to guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents campaignId thoroughly, including its default value and how to use an id from growsurf_create_campaign. The description mostly restates this targeting behavior ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), adding no new parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource — 'List your GrowSurf program's configured rewards' — making the operation unambiguous. It also draws an explicit distinction from participant rewards ('does not establish that a participant earned or received a reward'), which separates it from growsurf_get_participant without needing to inspect that tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when this tool is not the right choice: to see whether a participant earned a reward, you should use growsurf_get_participant instead. It also clarifies the targeting behavior with campaignId and the fallback to GROWSURF_CAMPAIGN_ID, giving an agent clear conditions for invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_campaignsList ProgramsARead-onlyIdempotentInspect
List the GrowSurf programs available to the bound team. Use this first when you need to choose a campaignId before calling campaign-scoped tools. Deleted programs are not returned. Does NOT require GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| campaigns | No | Programs available to the API key's bound team. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already state readOnlyHint true, idempotentHint true, and destructiveHint false, so the safety profile is covered. The description adds valuable behavioral context beyond those annotations: 'Deleted programs are not returned' clarifies output filtering, and 'Does NOT require GROWSURF_CAMPAIGN_ID' clarifies an operational constraint. This is meaningful extra transparency for a zero-parameter tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences and every sentence earns its place: the first states the core function, the second gives when-to-use guidance, and the third adds behavioral filter and environment-variable context. It is front-loaded with the purpose and contains zero filler. This is an appropriately sized description for a simple list tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a zero-parameter read-only list operation, and the output schema exists, so the description needn't enumerate the return fields. The description covers scope ('available to the bound team'), usage order (first before campaign-scoped tools), output filter (deleted programs omitted), and an important environment variable exception. Combined with annotations, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, and the input schema is an empty object with 100% schema description coverage, so the baseline is 4. The description adds relevant context about the missing GROWSURF_CAMPAIGN_ID requirement, which helps an agent understand that no campaign ID is needed here unlike its siblings. This is a useful addition even though there are no explicit parameters to document.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens by clearly stating what the tool does: 'List the GrowSurf programs available to the bound team.' This is a specific verb plus resource and scope. It also distinguishes itself from the many campaign-scoped sibling tools by positioning this as the entry point for choosing a campaign ID, so an agent can tell it apart from tools like growsurf_get_campaign or growsurf_list_campaign_rewards.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: 'Use this first when you need to choose a campaignId before calling campaign-scoped tools.' It also notes that GROWSURF_CAMPAIGN_ID is not required. It doesn't name a specific alternative tool or provide an explicit when-not, but the 'use first' instruction and the distinction from campaign-scoped tools clearly places it as the initial discovery step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_campaign_webhooksList WebhooksARead-onlyIdempotentInspect
List your GrowSurf program's webhooks (secrets are never returned). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| webhooks | No | Webhooks configured for the program. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and idempotent. The description adds meaningful behavioral disclosure by stating that webhook secrets are never returned, which is important security context an agent needs. The fallback targeting behavior is also clearly explained beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The core action is stated first, the important security caveat follows, and the parameter targeting rule is clearly front-loaded. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with zero required parameters and an output schema, this description is complete. It covers the resource, the security caveat, and the parameter targeting behavior. The annotations carry the safety profile, and the output schema covers return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the campaignId parameter is already well documented in the input schema. The description mostly restates the parameter's default behavior, so it adds little semantic value beyond what the schema provides. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the exact resource and action: 'List your GrowSurf program's webhooks'. This clearly differentiates it from sibling tools like growsurf_list_campaigns and growsurf_list_integrations. The qualifier about secrets not being returned further sharpens what this tool specifically provides.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when the campaignId parameter is targeted and when the default GROWSURF_CAMPAIGN_ID is used. It gives enough context for the agent to know how the tool selects its scope, though it does not explicitly discuss alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_integrationsList IntegrationsARead-onlyIdempotentInspect
List every integration your GrowSurf program can connect (Stripe, PayPal, Wise, Mailchimp, Slack, Zapier, Webhooks, and more) with its current state, so you can check whether an integration is connected before you act on it. Each entry has connected (credentials are stored), enabled (switched on and working), autoDisabled (GrowSurf switched it off after repeated delivery failures — the credentials are still stored, but nothing is delivered until the user reconnects it), and connectUrl (the dashboard link to hand the user). Integrations that do not apply to the program type are omitted (for example, Wise on a referral program). Read-only: connecting an integration happens in the GrowSurf dashboard, not through the API — call growsurf_get_integration_connect_link for the link to hand the user. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| integrations | No | Every integration this program can connect, in the order the GrowSurf dashboard lists them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, but the description adds meaningful behavioral context: it explicitly says the call is read-only, explains the autoDisabled state (credentials stored but nothing delivered until reconnect), and notes that inapplicable integrations are omitted. This exceeds what the annotations alone convey and contains no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: it names example integrations, defines each state field, explains omission behavior, clarifies read-only semantics with a sibling pointer, and specifies the parameter default. The core action is front-loaded, and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is already covered. The description adds everything else an agent needs: field semantics, omitted integration behavior, the dashboard-only connect path, the connect-link sibling, and the campaignId targeting rule. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents campaignId fully, including its default to GROWSURF_CAMPAIGN_ID and the use case of passing a newly created campaign id. The description restates 'Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID,' adding no new meaning beyond the schema. With 100% schema coverage, the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource — 'List every integration your GrowSurf program can connect' — and defines the tool's scope and output fields (connected, enabled, autoDisabled, connectUrl). It also differentiates itself from the sibling growsurf_get_integration_connect_link by stating that connecting happens in the dashboard and routing users to that sibling for the connect link.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete use case ('so you can check whether an integration is connected before you act on it'), states when not to use the tool ('connecting an integration happens in the GrowSurf dashboard, not through the API'), and explicitly names the alternative growsurf_get_integration_connect_link. It also clarifies the campaignId default behavior, giving an agent full routing context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_participantsList ParticipantsARead-onlyIdempotentInspect
List participants in your GrowSurf program, newest page first. limit is 1-100 (default 10). Pass response nextId into the next call to continue paging. Pass metadata to return only participants whose stored metadata matches every given key and value exactly, for example { "customerId": "12345" } to look someone up by your own customer ID; filtered results are ordered by participant ID. Use this when you need a participant ID before calling participant-scoped tools. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| nextId | No | Participant ID returned as `nextId` from the previous page. | |
| metadata | No | Exact-match filter on participant metadata, up to 3 keys, for example `{ "customerId": "12345" }`. Values compare as strings. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Maximum number of participants requested for this page. |
| nextId | No | Participant id to pass as `nextId` for the next page, or `null` when there are no more results. |
| participants | No | Participants returned for this page. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context beyond that: pagination semantics ('Pass response nextId into the next call'), the ordering of results ('newest page first' and 'filtered results are ordered by participant ID'), and the metadata exact-match behavior. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph but is information-dense. The main purpose is front-loaded, followed by pagination, filtering, and targeting details. Each clause serves a purpose, and there is no filler. It could be slightly more structured (e.g., bullet points), but it is efficient and readable. Slightly above average due to the density without waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema (not shown but indicated), so return value details are covered elsewhere. The description fully addresses the key operational aspects: pagination, filtering, default campaign behavior, and the use case for obtaining participant IDs. For a list endpoint with multiple optional parameters, this is complete. An agent can call it correctly without additional guesswork.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all four parameters with descriptions and constraints (75% coverage). The description adds meaningful semantics: it explains the default campaignId behavior, the limit range (1-100, default 10), how nextId works, and the metadata filter semantics (exact match, every key and value, ordering). The example with customerId is particularly helpful. This goes beyond the schema and compensates for the remaining 25% coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists participants in a GrowSurf program, with a specific resource (participants) and a useful scope ('newest page first'). It also explicitly frames the use case ('Use this when you need a participant ID before calling participant-scoped tools'), distinguishing it from sibling tools like growsurf_get_participant and participant mutation tools. The action and resource are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'Use this when you need a participant ID before calling participant-scoped tools.' It also explains the campaign targeting default (GROWSURF_CAMPAIGN_ID) and how to override with a passed campaignId. Paging via nextId and metadata filtering are described with concrete examples, giving the agent clear when-to-use and how-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_program_resourcesList Program ResourcesARead-onlyIdempotentInspect
List the participant resources configured for your GrowSurf program, including drafts. Results stay in display order. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| resources | No | The program's resources in participant display order, including drafts. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint, idempotentHint, and destructiveHint, so the description only needed to add behavioral context. It does that by revealing drafts are included, results maintain display order, and the default campaign fallback, none of which appear in annotations. No contradiction found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying distinct information: result set, ordering, and campaign targeting. Front-loaded with the action and resource, no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list operation with one optional parameter and an output schema, the description covers result contents (including drafts), ordering, and target-selection logic. Nothing an agent needs to invoke it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%; the campaignId schema already documents the default behavior in nearly the same words as the description. The description's 'Targets ... otherwise GROWSURF_CAMPAIGN_ID' adds no semantic detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a concrete verb and object: 'List the participant resources configured for your GrowSurf program, including drafts.' This clearly identifies the resource type and scope, which distinguishes it from list_campaigns, list_participants, and list_campaign_rewards without naming them. It falls just short of a 5 because it never explicitly contrasts itself with a sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not name alternatives or specify when to prefer this tool over list_campaigns/list_campaign_rewards; usage is implied by its resource name and 'configured for your GrowSurf program.' It does give clear parameter targeting guidance ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), but that is invocation detail, not tool-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_mobile_sdk_guideMobile SDK GuideBRead-onlyIdempotentInspect
Generate native iOS/Android SDK 0.4.0 guidance, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.
| Name | Required | Description | Default |
|---|---|---|---|
| platform | No | both | |
| campaignId | No | ||
| mobilePublicKey | No | ||
| participantState | No | both | |
| attributionProvider | No | all | |
| includeInstallSnippets | No | ||
| serverVerifiedQualifyingAction | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is clear. The description adds that this tool generates guidance covering specific SDK features, but it does not disclose output format, limits, or any nuances about what 'guidance' includes beyond topic names. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, focused, and front-loaded with the action and resource. It includes the SDK version and relevant topics without padding. It is concise, though it could invest some of that brevity in parameter clarification.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter tool with no required arguments and no schema descriptions, the description leaves key decisions unspecified, such as how to choose participantState or attributionProvider, and whether generated guidance will include install snippets by default. The output schema removes some burden, but the lack of parameter context makes the description incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the responsibility to explain parameters. It only mentions high-level topics like attribution and platform features; it does not provide meaning for campaignId, mobilePublicKey, participantState, attributionProvider, includeInstallSnippets, or serverVerifiedQualifyingAction. This is better than having no contextual hints, but far from sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Generate'), a clear resource ('native iOS/Android SDK 0.4.0 guidance'), and lists concrete topics (attribution, shareUrl, trackShare, native GrowSurf Window). It is distinguishable from a generic integration guide, though it does not explicitly contrast itself with siblings like growsurf_integration_guide or growsurf_api_library_snippets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'native' and 'SDK 0.4.0' imply when this tool is appropriate, but there are no explicit when-to-use or when-not-to-use statements, and no mention of alternative tools for web/client integration. An agent would have to infer the boundary against sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_participant_auth_hashCompute Participant Auth HashBRead-onlyIdempotentInspect
Compute the server-side SHA-256 HMAC for GrowSurf Participant Auto Authentication. Set affiliateJoin only when this signed-in user may join the affiliate program directly.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| affiliateJoin | No | ||
| participantAuthSecret | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| hash | No | The computed hash. Pass it to the GrowSurf client as the participant's `hash` value. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds that it is a server-side computation, but does not disclose additional behavioral details (e.g., output format or how secrets are handled). Since annotations carry most of the burden, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero fluff. The purpose is front-loaded and the second sentence adds a specific, necessary usage note. Perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having annotations, the description lacks explanation of participantAuthSecret, how the output is used (e.g., for auto-authentication URLs), and any context about the HMAC construction. For a tool with 3 params and no schema descriptions, this is incomplete and could leave an agent uncertain about required inputs and expected outputs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains affiliateJoin but does not clarify email (implicit as user identifier) or participantAuthSecret (how to obtain or its role). The missing explanation of participantAuthSecret is a significant gap for a tool that apparently requires it to compute the HMAC.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific action ('Compute the server-side SHA-256 HMAC') and identifies the resource ('GrowSurf Participant Auto Authentication'), which is clear. However, it does not explicitly distinguish this from sibling tools (e.g., growsurf_create_mobile_participant_token), so it loses a point for missing differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides conditional guidance for one parameter ('Set affiliateJoin only when this signed-in user may join the affiliate program directly'), which implies a usage context. But there is no explicit mention of when to prefer this tool over alternatives or any exclusions, so guidance is partial.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_prepare_program_resource_filePrepare Program Resource FileAInspect
Prepare a local file for a FILE Program Resource. Pass the safe file name, matching supported MIME type, and padded base64 bytes (10 MB maximum). GrowSurf requests a one-time ticket and uploads only to the secure HTTPS destination selected by GrowSurf. The result contains only uploadTicket and uploadResult; pass both unchanged to growsurf_create_program_resource or growsurf_update_program_resource. The tool does not accept upload URLs or credentials and never retries an ambiguous upload. This tool is the only source of uploadTicket and uploadResult, and it needs GROWSURF_UPLOAD_ALLOWED_ORIGINS set on the server; without it, FILE resources are unavailable and only LINK and TEXT resources can be created. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | A safe base name with an allowed extension: jpg/jpeg/png/gif/webp/pdf/csv/zip/doc/docx/xls/xlsx/ppt/pptx. | |
| mimeType | Yes | The supported MIME type matching fileName's extension. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| fileBase64 | Yes | Canonical padded base64 file bytes only. Do not include a data-URL prefix or whitespace. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uploadResult | No | The minimal signed upload confirmation. Pass it unchanged to create/update. |
| uploadTicket | No | The one-time GrowSurf ticket. Pass it unchanged to create/update. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses meaningful behavior beyond the annotations: a one-time ticket is requested, upload goes only to a GrowSurf-selected HTTPS destination, ambiguous uploads are never retried, and no credentials are accepted. It also surfaces the server prerequisite GROWSURF_UPLOAD_ALLOWED_ORIGINS and the campaign targeting fallback, all of which are essential for correct invocation. No contradiction with readOnlyHint=false, idempotentHint=false, destructiveHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized: purpose first, then input requirements, upload mechanics, result routing, exclusions, and environmental prerequisite. Each sentence adds operational value, and nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with output schema and complex file-upload behavior, the description covers prerequisites, constraints, output usage, and campaign targeting. It is complete enough that an agent can correctly select and invoke the tool without needing to infer undocumented behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema describes all four parameters (100% coverage), the description adds high-value semantics: the 10 MB maximum, padded base64 encoding requirement, safe file name and matching MIME type expectation, and campaignId defaulting to GROWSURF_CAMPAIGN_ID. This goes beyond the schema's field-level descriptions and clarifies how to construct valid inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Prepare a local file for a `FILE` Program Resource.' It also clarifies the tool's unique role as 'the only source of uploadTicket and uploadResult', which distinguishes it from create/update/delete program resource siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs the agent to pass the result unchanged to growsurf_create_program_resource or growsurf_update_program_resource, and it names when the tool is unavailable ('without it, FILE resources unavailable and only LINK and TEXT resources can be created'). It also states what the tool will not do, such as accepting upload URLs or credentials, providing clear when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_program_design_advisorProgram Design AdvisorARead-onlyIdempotentInspect
Use for program designs, benchmarks, typical rewards, and metric definitions, including participant-to-referral and lead-to-referral ratios. Read-only; call with known context before asking questions. Returns a short draft, complete benchmarkFacts to quote, exact configurationPlan tool calls, and unresolved decisions. Preserve the calls and leave unresolved incentives open. Use the default summary for first designs and configuration drafts; use detail: full when the user requests detailed benchmark tables or a specific figure absent from the summary. Hosted figures describe GrowSurf's high-performing programs; without a bundle, guidance is documentation-based. Use programType: AFFILIATE for affiliates and industry: other for local services, pets, hospitality, or agencies. All inputs are optional.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | What a successful referral means for the business. `paid_conversions` and `leads` imply a qualifying action; `signups`, `subscribers`, and `waitlist` count the signup unless a separate `qualifyingAction` needs clarification. This is the advisor's goal enum; use the separate creation goal returned in `configurationPlan` for `growsurf_create_campaign`. | other |
| detail | No | Use summary for a first design or configuration draft, including a reward structure recommendation. Use full only for requested detailed benchmark tables or specific figures absent from the summary, such as reward amounts, share channels, or integration proportions. | summary |
| audience | No | Who refers whom. | |
| industry | No | Closest industry segment: `financial_services_fintech` (banking, lending, investing, insurance, payments, crypto), `saas_ai` (software sold to businesses, developer tools, AI products), `media_newsletters` (newsletters, podcasts, publishers, content brands), `healthcare_wellness` (clinics, telehealth, fitness, nutrition, mental health, supplements), `education_workforce` (courses, bootcamps, tutoring, hiring and job platforms), `consumer_subscriptions_commerce` (consumer apps, e-commerce, marketplaces, subscription boxes). Use `other` when no segment clearly fits (local services, pets, hospitality, agencies) rather than stretching one; `other` returns the platform-wide figures. | other |
| companyName | No | Used in the heading and proposed program name; omit it when unknown. | |
| currencyISO | No | ISO 4217 code. Non-USD advice omits the dollar reward bands. No exchange rate or equivalent-currency benchmark is available. | |
| programType | No | REFERRAL | |
| salesMotion | No | Use `sales_led` for demos, sales calls, negotiated pricing, or signed contracts; use `self_service` when customers buy directly. This selects the reward structure. Omit when unknown. | |
| includeRules | No | Append guidance on applying the recommendations. Off by default. | |
| businessModel | No | One line on what the business sells and how. Also set `salesMotion` when the buying process is known. | |
| qualifyingAction | No | The action a referred friend must complete, in the customer's words. | |
| rewardBudgetPerReferral | No | The customer's spending limit per successful referral, in major currency units. A budget does not select an incentive amount or commission rate. Budget comparisons omit the mixed-currency reward amount bands. |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The requested summary or full advice, including the same configuration calls and their conditions. |
| decisions | No | Use one qualifying action throughout the draft. Unresolved choices require a customer decision before configuration. |
| benchmarkFacts | No | Complete benchmark statements with metric units, median, Q1, Q3, sample, and source. Quote each statement intact. Empty when no suitable figures are available. |
| configurationPlan | No | Proposed calls using the listed tools' argument shapes. Preserve each tool and arguments object when presenting the plan; replace <new-program-id> with the creation response's id before execution. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though readOnlyHint and destructiveHint are already annotated, the description adds valuable behavior: it will return draft text, `benchmarkFacts`, exact `configurationPlan` calls, and unresolved `decisions`; tells the agent to preserve those calls and leave incentives open; and explains the hosted-figures versus documentation-only data source. These details go well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well organized: purpose first, then output shape, operational instructions, mode selection, data-source caveat, and key parameter guidance. Each sentence adds distinct information and no filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter, zero-required advisor tool with rich annotations and an output schema, the description covers the essential operational context: read-only behavior, output contents, summary/full selection, external data caveats, and parameter hints. Nothing critical is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema description coverage is 92%, so the schema already documents nearly all parameters. The description adds useful emphasis for `detail`, `programType`, and `industry`, but those points largely restate what the schema already provides, so the tool description does not materially exceed the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific responsibility ('program designs, benchmarks, typical rewards, and metric definitions'), specific outputs ('benchmarkFacts', 'configurationPlan', 'decisions'), and is clearly distinct from campaign creation or analytics siblings. 'Read-only' and 'returns exact configurationPlan tool calls' further separate it from execute-style tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit conditions: use the summary for first designs and configuration drafts, use `detail: full` for requested benchmark tables or absent figures, and set `programType`/`industry` appropriately. It does not explicitly name alternate sibling tools or state when not to use this tool, so it misses the 'when-not' portion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_record_saleRecord SaleAIdempotentInspect
Record a sale/transaction for an affiliate program. Use webhooks to know when commissions are added. Requires at least one transaction identifier (externalId, transactionId, orderId, paymentId, invoiceId, paymentIntentId, or chargeId) so repeated calls are de-duplicated instead of double-paying the referrer; reuse the same one when refunding. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| paidAt | No | ||
| orderId | No | ||
| chargeId | No | ||
| currency | Yes | ||
| testMode | No | Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit. | |
| invoiceId | No | ||
| netAmount | No | ||
| paymentId | No | ||
| taxAmount | No | ||
| amountPaid | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| customerId | No | ||
| externalId | No | ||
| totalTaxes | No | ||
| description | No | ||
| grossAmount | Yes | ||
| invoiceTotal | No | ||
| amountCashNet | No | ||
| participantId | No | ||
| transactionId | No | ||
| subscriptionId | No | ||
| totalTaxAmount | No | ||
| paymentIntentId | No | ||
| paymentProvider | No | Connected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions. | |
| totalTaxAmounts | No | ||
| participantEmail | No | ||
| invoiceTotalExcludingTax | No | ||
| invoiceSubtotalExcludingTax | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. |
| success | No | `true` when the sale was recorded; `false` when it matched an existing transaction. |
| duplicate | No | `true` when the sale matched an existing transaction. |
| firstSale | No | Whether this was the referred customer's first recorded sale. |
| duplicateFields | No | Identifier fields that matched an existing transaction. |
| commissionsCreated | No | Commissions created by this duplicate request. |
| matchingCommissionIds | No | Commission ids that matched the submitted identifiers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate idempotentHint=true but not readOnlyHint, which aligns with the description's emphasis on de-duplication and avoiding double payments. The description goes beyond annotations by explaining the de-duplication mechanism and the requirement for a transaction identifier, and mentions the targeting of campaignId or defaulting to GROWSURF_CAMPAIGN_ID. No contradiction with annotations found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with three sentences that are front-loaded with the core purpose and de-duplication warning. It avoids unnecessary details and effectively communicates the essential requirements and behavior without being verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the tool with 28 parameters, the description provides critical context on de-duplication, targeting campaignId, and the webhook recommendation. However, it could be more complete by elaborating on the interplay between parameters (e.g., when to use netAmount vs grossAmount) or the expected output, but the output schema and annotations help fill some gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 11%, so the description does not repeat parameter details. It mentions the requirement for at least one transaction identifier and explains the purpose of campaignId, but does not elaborate on other parameters like amounts, dates, or participant identifiers. The description adds some value but does not fully compensate for the low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool records a sale/transaction for an affiliate program, with specific verbs and resource. It distinguishes itself by mentioning webhooks and de-duplication for commission tracking, which is a distinct purpose from the sibling tools like growsurf_refund_transaction or growsurf_trigger_referral.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use this tool: to record a sale, and provides context on using webhooks to know when commissions are added. It also mentions the alternative of relying on webhooks and notes the necessity of transaction identifiers for de-duplication, giving clear usage context without naming siblings directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_refund_transactionRefund TransactionADestructiveIdempotentInspect
Record an amendment (refund, partial refund, or chargeback) against a previously recorded affiliate transaction; reverses or adjusts the referrer's commission. The inverse of growsurf_record_sale. Identify the original transaction with the same identifier you sent when recording it (omit amountRefunded for a full refund). Already-paid commissions are not clawed back (recorded for tax only). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | No | ||
| orderId | No | ||
| chargeId | No | ||
| currency | No | ||
| refundId | No | Stable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation. | |
| testMode | No | Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`. | |
| invoiceId | No | ||
| paymentId | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| externalId | No | ||
| description | No | ||
| refundAmount | No | Positive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation. | |
| refundStatus | No | ||
| amendmentType | No | ||
| participantId | No | ||
| transactionId | No | ||
| amountRefunded | No | ||
| paymentIntentId | No | ||
| paymentProvider | No | Connected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider. | |
| participantEmail | No | ||
| refundHistoryComplete | No | Set true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list. |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | No | Pending commissions deleted by the amendment. |
| matched | No | Commissions found for the provided identifiers. |
| message | No | Human-readable result message. |
| success | No | `true` when the amendment was processed; `false` when no matching transaction was found. |
| adjusted | No | Commissions partially adjusted. |
| notFound | No | Present and `true` when no commission matched the provided identifiers. |
| reversed | No | Commissions reversed (set to zero amount). |
| amendmentType | No | Amendment type that was processed. |
| matchingCommissionIds | No | Commission ids that matched the submitted identifiers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive and idempotent behavior. The description adds meaningful context beyond that: already-paid commissions are not clawed back and are recorded for tax only, and campaign targeting defaults to GROWSURF_CAMPAIGN_ID. No contradiction with annotations is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and contains no filler. The phrase 'The inverse of growsurf_record_sale' is slightly redundant with the opening sentence, but it earns its place by explicitly differentiating the tool from a sibling. It could be tightened, but it is well organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core workflow, full-refund signaling, commission clawback behavior, and campaign default. Combined with the output schema and detailed parameter descriptions for the complex refund fields, an agent has enough to invoke the tool correctly. It does not explicitly state provider-side effects, but those are covered in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 29%, so the description must compensate. It adds useful guidance on reusing the original identifier and omitting amountRefunded for a full refund, but most of the 21 parameters are left to the schema. The schema does contain rich descriptions for the most complex parameters, making the added value adequate but not comprehensive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Record an amendment'), the resource it acts on (a previously recorded affiliate transaction), and the effect (reverses or adjusts the referrer's commission). It explicitly names growsurf_record_sale as its inverse, making the distinction from the sibling sales tool clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this for refunds, partial refunds, and chargebacks against existing transactions, and it tells the agent to reuse the original transaction identifier. It names the inverse tool but does not explicitly provide a when-not-to-use rule or conditional alternative selection, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_request_participant_payout_destination_confirmationRequest Payout Destination ConfirmationADestructiveInspect
Ask a participant to confirm their payout destination for a provider (by GrowSurf participant ID or email). Sends them a one-time confirmation link for the chosen provider; only the participant can open the link and confirm — this just triggers the message, and the provider must be enabled for the program. Returns { status, provider, providerDisplayName, expiresAt }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | Yes | The payout provider the participant should confirm a destination for. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | Confirms the message was requested (`CONFIRMATION_REQUESTED`). |
| provider | No | The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL` and `WISECOM`. |
| expiresAt | No | When the confirmation link expires, as a Unix timestamp in milliseconds. |
| providerDisplayName | No | The customer-facing provider name (e.g. "PayPal", "Wise"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructive and non-idempotent behavior, and the description adds valuable context: the link is one-time, only the participant can open it, it merely triggers the message (not a direct update), and the provider must be enabled. It also discloses the return fields. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the core action, and includes all necessary details without redundancy. Each sentence adds value: what it does, how it works, and what it returns.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description covers the main behavioral aspects, provider requirement, return value, and campaign targeting. It does not mention error handling or prerequisites like participant existence, but these are minor gaps given the output schema and annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%, with provider and campaignId having descriptions. The description clarifies that participantId and participantEmail are alternatives (via the anyOf schema) and explains that campaignId defaults to GROWSURF_CAMPAIGN_ID. It also specifies that the participant is identified by ID or email, compensating for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Ask a participant to confirm their payout destination'), the resource (payout destination for a provider), and the identification methods (participant ID or email). It also distinguishes itself from sibling tools like growsurf_get_participant_payout_destination by focusing on triggering confirmation rather than retrieving it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use the tool: to trigger a one-time confirmation link for a participant's payout destination. It explains the effect (sends a message, only participant can confirm) and notes that the provider must be enabled. However, it does not explicitly mention alternative tools for checking existing destinations, leaving some ambiguity about when to prefer this over gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_request_team_verificationRequest Team VerificationAIdempotentInspect
Ask GrowSurf to verify the team bound to the API key or OAuth connection. Verification is required before a program can email participants. Calling this again while a request is pending does not create a duplicate. Returns the team with its updated verificationStatus. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotency, non-read-only, and non-destructive hints. The description adds valuable specifics beyond those: idempotency is refined to 'while a request is pending,' the return value is the team with updated `verificationStatus`, and the credential requirements are stated. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well organized: it leads with the core action, then the business necessity, then idempotency, return value, and credentials. Every sentence contributes necessary information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema and useful annotations, the description covers all essential aspects: what the tool does, when it is needed, idempotency behavior, the response shape, and authentication prerequisites. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is 100%, so there is little to document. The description still adds meaningful operational context by stating it requires `GROWSURF_API_KEY` and explicitly does not require `GROWSURF_CAMPAIGN_ID`, which helps an agent understand invocation prerequisites.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Ask GrowSurf to verify the team bound to the API key or OAuth connection.' It also clarifies the outcome via the updated `verificationStatus`, distinguishing it from related team operations like growsurf_get_team and growsurf_update_team.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates when to use the tool: 'Verification is required before a program can email participants.' It also advises that calling again while a request is pending is safe. However, it does not explicitly name alternatives or exclusion cases, such as when to use growsurf_resend_team_owner_verification_email instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_resend_team_owner_verification_emailResend Team Owner Verification EmailADestructiveInspect
Resend the email-verification message to the bound team's owner. The response never reveals the owner's email address. A 200 with status: SENT is returned only when an email was sent. Returns 400 if the email is already verified and 429 if one was sent too recently. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | Status of the verification email request. |
| success | No | Whether the verification email request was accepted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral details beyond the annotations: requires GROWSURF_API_KEY, does not require GROWSURF_CAMPAIGN_ID, response never reveals owner email, and maps status codes to specific outcomes (sent, already verified, rate-limited). These complement the destructiveHint annotation without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the primary action. Each sentence contributes distinct value: the action, privacy guarantee, response code semantics, and authentication requirements. There is no redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters and an output schema exists, the description covers all essential call context: response behavior, authentication needs, and a key privacy constraint. An agent can confidently invoke the tool without additional information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description does not need to elaborate on parameters, and no additional meaning is required beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action (resend verification email) and target (team's owner), making the purpose clear. However, it does not mention the sibling tool request_team_verification or how this differs, so it misses the 'distinguishes from siblings' criterion for a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives. It does not mention the sibling request_team_verification or any conditions that would select this tool over others. The response codes (400, 429) give some context but do not help with tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_test_campaign_webhookSend Test WebhookADestructiveInspect
Send a live test event to a webhook on your GrowSurf program using its stored URL and secret. Optionally pass event to choose which event type to simulate; when omitted, the webhook's first enabled event is used (returns 400 if the webhook has no enabled events). Returns the mock payload and the receiving endpoint's response. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| event | No | ||
| webhookId | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
| payload | No | The mock event payload that was sent. |
| success | No | Whether the test webhook request completed. |
| response | No | Response returned by the webhook endpoint during the test. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnly=false, destructiveHint=true), the description discloses that this sends a live request using the stored URL/secret, returns the mock payload plus the endpoint's response, and returns 400 when no enabled events exist. It also explains the campaignId fallback to GROWSURF_CAMPAIGN_ID. This is rich behavioral context consistent with the destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences front-load the core action, then add event behavior, return value, and fallback targeting without waste. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter destructive test tool with an output schema and helpful annotations, the description covers live behavior, error cases, return values, and default targeting. No important calling information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 33% schema coverage, the description adds crucial meaning: what happens when `event` is omitted (first enabled event, 400 if none), and how `campaignId` defaults to the environment variable. `webhookId` is only implicitly identified as the webhook receiver, but the required parameter name plus schema makes the mapping clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb and object: 'Send a live test event to a webhook on your GrowSurf program using its stored URL and secret.' This clearly identifies the operation and differentiates it from webhook CRUD siblings like growsurf_create_campaign_webhook and growsurf_list_campaign_webhooks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is clear from 'live test event' and the webhook context, and the description explains event selection and fallback behavior. It does not explicitly name sibling alternatives or when-not-to-use conditions, but the context is sufficiently unambiguous for selecting this tool over configuration/read tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_trigger_referralTrigger ReferralADestructiveInspect
Trigger referral credit for a referred participant (use when your trigger is Sign up + Qualifying Action). Optionally pass delayInDays (1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| delayInDays | No | ||
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. Present when credit was not awarded immediately. |
| success | No | Whether referral credit was awarded, scheduled, or cancelled. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already signal mutating and destructive behavior, and the description adds useful behavioral detail beyond them: optional delayInDays holds the credit before awarding, and campaignId falls back to GROWSURF_CAMPAIGN_ID. It explains the withholding window purpose with the refund-window example, giving agents practical context for side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly written in three sentences with no filler. The core action and usage condition are front-loaded, followed by the delay behavior and campaign targeting behavior, so each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema, the annotations, and the 4-parameter input schema, the description covers the important selection and invocation details: when to use it, how delay works, and how campaign targeting resolves. It does not describe edge cases or explicit consequences beyond credit awarding, but nothing critical is missing for a competent agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description must compensate. It adds real semantics for delayInDays (hold 1-90 days before awarding) and campaignId (targets provided campaign or defaults to GROWSURF_CAMPAIGN_ID). participantId and participantEmail remain schema-only, but they are self-descriptive and the anyOf constraint clarifies that one is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and object: 'Trigger referral credit for a referred participant', clearly identifying the action and its target. It also names the exact integration condition ('Sign up + Qualifying Action'), which distinguishes this tool from generic participant or campaign operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use the tool: 'use when your trigger is Sign up + Qualifying Action'. It provides clear contextual guidance, though it does not explicitly name alternatives or exclusion cases, so it stops short of a perfect 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_troubleshoot_referral_trackingTroubleshoot Referral TrackingARead-onlyIdempotentInspect
Call first for a program problem, even without a program or participant ID. It returns initial checks; ask for IDs before reading records. Covers referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, an integration or CRM (HubSpot, Mailchimp, and others) not syncing, Zapier errors, fraud flags, analytics numbers that look wrong, and more. Returns the checks to run in order (with the read tool and field for each), the likely causes most common first, fixes, and doc links. Pass a symptom key; unknown keys return the available symptoms; a description is matched only when it contains a symptom's label or alias verbatim, otherwise the symptom list is returned.
| Name | Required | Description | Default |
|---|---|---|---|
| symptom | No | The symptom to diagnose. Known keys: `participant_emails_not_sending`, `reward_not_issued`, `referral_not_credited`, `participants_not_added`, `universal_code_not_detected`, `platform_specific_install`, `numbers_do_not_match`. Unknown keys return the symptom list. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| description | No | The problem in the customer's words, when `symptom` is unknown. | |
| participantId | No | Affected participant id, echoed into participant-level checks. | |
| participantEmail | No | Affected participant email, when the id is unknown. |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description discloses the triage return structure (checks in order with the read tool and field for each, likely causes most common first, fixes, doc links) and the fallback behavior of both free-text inputs: unknown symptom keys return the symptom list, and description only matches on a verbatim label or alias. These behaviors are not derivable from the annotations and materially affect call outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but information-dense, with every clause earning its place: positioning, symptom coverage, output structure, and input matching rules. The key directive 'Call first' is front-loaded, followed by a logically ordered expansion of what the tool covers and returns.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a triage tool with 5 parameters, strong annotations, and an output schema, the description covers when to call, what inputs are accepted and how they are matched, and what the response contains. Nothing an agent needs to invoke it correctly is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents all five parameters, setting a baseline of 3. The description adds genuine value by specifying the description parameter's verbatim label/alias matching rule and by clarifying the symptom-list fallback behavior — details not present in the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific directive, 'Call first for a program problem,' and defines a concrete scope by enumerating the covered symptoms: referrals not credited, participant emails not sending, rewards not issued, Universal Code not detected, integration/CRM sync issues, Zapier errors, fraud flags, and analytics discrepancies. This verb+resource+scope combination clearly distinguishes it from sibling read/CRUD tools like growsurf_get_campaign_analytics or growsurf_list_participants.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit positioning guidance: 'Call first for a program problem, even without a program or participant ID' and 'ask for IDs before reading records,' which tells the agent when to invoke this tool versus the read tools. However, it names no explicit alternative tools or when-not-to-use conditions, so the boundary against the 65 siblings is left somewhat to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaignUpdate ProgramADestructiveIdempotentInspect
Update your GrowSurf program's (campaign's) identity and lifecycle: name, companyName, companyLogoImageUrl, and status (set IN_PROGRESS to publish/resume the program, COMPLETE to end it). Only the fields you send are changed. type, urlId, and currencyISO are immutable (currency is chosen once at program creation), so this tool does not accept them. Editor-tab config (design, emails, options, installation) is edited with the dedicated config sub-resource tools, not here. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| status | No | Lifecycle transition. IN_PROGRESS publishes/resumes the program; COMPLETE ends it. These are the only accepted targets — DRAFT/PENDING/CANCELLED are rejected by the API. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| companyName | No | ||
| companyLogoImageUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavioral context beyond annotations: partial updates ('Only the fields you send are changed'), lifecycle meanings of status values, immutable fields (`type`, `urlId`, `currencyISO`), and default campaign targeting. While annotations already indicate mutating/destructive/idempotent behavior, the description provides the specific constraints and effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with the core purpose, then enumerating scope, exclusions, and targeting default. No repetition or filler; every sentence contributes actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a focused update tool with five parameters, annotations, and an output schema, the description covers what is updatable, what is not, how status works, where config editing belongs, and how campaign selection defaults. Nothing essential to correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 40% of parameters, and the description compensates by naming the remaining mutable fields and explaining the semantics of status transitions. It also clarifies that immutable fields are intentionally not accepted, adding meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Update your GrowSurf program's (campaign's) identity and lifecycle,' then enumerates the exact mutable fields (name, companyName, companyLogoImageUrl, status). It clearly differentiates itself from config sub-resource tools and create/list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says editor-tab config is handled by dedicated config sub-resource tools, 'not here,' and defines the default targeting behavior for campaignId. It also explains when to use a specific campaignId (e.g., after growsurf_create_campaign), giving agent clear selection logic.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_designUpdate Program DesignADestructiveIdempotentInspect
Update the design configuration for your GrowSurf program, including participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, participant sign-in copy under login, and payout-destination confirmation page copy under payoutDestinationConfirmation. participantAvatarStyle accepts CHARACTERS, INITIALS, ANIMALS, or GRADIENT. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Fetch the configuration first, preserve starter content unless the user asked to change it, then pass just the fields you want to change under fields. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by detailing partial-update semantics ('Only the fields you send are changed; anything you leave out is untouched') and explicitly warning that arrays replace wholesale. This is valuable context given destructiveHint=true, and it also clarifies the campaign targeting fallback behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but efficient, front-loading the core purpose followed by key behavioral rules and parameter guidance. No sentence is wasted; the most important operational constraints are stated clearly and compactly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool does, which fields matter, how partial updates and array replacement behave, which campaign is targeted, and the safe invocation pattern (fetch first, preserve starter content). Given the output schema and annotations, this is sufficient for an agent to correctly select and invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%, and the required `fields` parameter is undocumented in the schema. The description compensates by explaining what fields can live inside it, including participantAvatarStyle options and content areas, and by explaining campaignId's fallback and usage for newly created campaigns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it updates the design configuration for a GrowSurf program, naming specific subfields (participantAvatarStyle, login, payoutDestinationConfirmation) and the enum values for participantAvatarStyle. This distinguishes it from sibling update tools like growsurf_update_campaign, growsurf_update_campaign_options, or growsurf_update_program_resource by scoping it to design configuration.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit operational guidance: fetch the configuration first, preserve starter content unless the user asked to change it, and pass only the fields to change. It also explains campaignId fallback behavior. It does not explicitly contrast with alternative update tools, but the design-specific scope makes the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_emailsUpdate Program EmailsADestructiveIdempotentInspect
Update the Emails tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Pass just the fields you want to change under fields. To see the full object with every field and its current value, fetch the tab first, then send back only what you want to change. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral detail beyond annotations: partial-update semantics ('fields you leave out is untouched'), the destructive array behavior ('arrays replace wholesale'), and the target-selection fallback to GROWSURF_CAMPAIGN_ID. This aligns with destructiveHint=true and idempotentHint=true without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the main action, followed by update semantics and targeting. 'Pass just the fields you want to change' is slightly redundant with the preceding sentence, so it could be tightened, but overall every sentence contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a partial-update tool with an output schema and two parameters, the description covers the action, id resolution, idempotent/partial behavior, destructive array caveat, and a safe fetch-modify-send pattern. An agent has enough to invoke it correctly without guessing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: campaignId is documented, but fields is an opaque additionalProperties object. The description compensates by explaining how fields behaves (only included properties are updated, arrays replace wholesale) and by telling the agent to fetch before updating to learn valid keys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb and resource ('Update the Emails tab configuration for your GrowSurf program'), which clearly sets it apart from sibling tools like growsurf_get_campaign_emails and the more general growsurf_update_campaign. The mention of 'Emails tab' disambiguates from other update tools in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage context: fetch the tab first to get the full object, then send back only changed fields. It does not explicitly name alternative tools or state when not to use this tool, but the fetch-first instruction implicitly routes to growsurf_get_campaign_emails and gives a concrete workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_installationUpdate Program InstallationADestructiveIdempotentInspect
Update the Installation tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). To let GrowSurf run on another origin, such as http://localhost:3000, add that origin to allowedUrls and preserve the rest of the array; a browser origin missing from both shareUrl and allowedUrls can return 403. Leave shareUrl out of the patch unless the customer asked for a different landing page: every referral link already shared points at the current one. A patch that would replace a Share URL that is already set is refused until you confirm it with the customer and resend with replaceExistingShareUrl: true. Fetch the tab first, then pass just the fields you want to change under fields. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, and `signup`. Arrays replace wholesale. | |
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| replaceExistingShareUrl | No | Set this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, destructiveHint=true, and idempotentHint=trueUTE. The description adds important behavioral context beyond annotations: partial patch semantics, array replacement, 403 risk for missing origins, and refusal of shareUrl replacement unless confirmed. It does not mention the output schema details, but annotations cover idempotency and mutability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is thorough yet concise, front-loading the core behavior and then providing crucial edge cases without redundancy. Each sentence adds value, and the structure flows logically from general behavior to specific warnings.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (nested fields, array replacement, safety guards) and the presence of an output schema, the description covers all essential operational context: how patching works, how to handle arrays, when to use confirmation flag, and target resolution. No missing information that would cause incorrect usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema covers parameters well, the description adds critical nuances: the signup.url distinction from shareUrl, the need to preserve array entries, and the condition for replaceExistingShareUrl. The schema descriptions already cover basics, but the description enriches parameter understanding beyond simple definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as updating the Installation tab configuration and distinguishes it from sibling tools like growsurf_get_campaign_installation (read) and growsurf_update_campaign (campaign-level update). It specifies the resource (Installation tab) and the action (update/patch).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: fetch the tab first, pass only fields to change, handle arrays wholesale, and avoid changing shareUrl unless requested. It also clarifies when to use replaceExistingShareUrl and mentions the default target campaignId, aligning with sibling tools like growsurf_get_campaign_installation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_optionsUpdate Program OptionsADestructiveIdempotentInspect
Update the Options tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Pass just the fields you want to change under fields. To see the full object with every field and its current value, fetch the tab first, then send back only what you want to change. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavior beyond the annotations: fields omitted are untouched, arrays replace wholesale, and only provided fields under 'fields' are changed. This is critical for a tool marked destructiveHint=true because it tells the agent exactly where the destructive risk lies and how to avoid unintended data loss.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded, with the core action in the first sentence and the most important semantic caveats (partial update, array replacement) immediately after. Every sentence adds information needed for correct invocation, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter update tool with an output schema and annotations, the description covers all essential operational context: what the tool updates, how partial updates behave, the danger of array replacement, how to discover the full object, and the target campaign resolution. Nothing an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description substantially enriches the schema. It clarifies that the 'fields' object is a partial patch, not a full replacement, and explains the campaignId default behavior with GROWSURF_CAMPAIGN_ID. This goes well beyond the bare schema where 'fields' is just an object with additionalProperties and campaignId lacks operational context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Update') with a specific resource ('the Options tab configuration for your GrowSurf program'), which clearly distinguishes it from fetch operations like growsurf_get_campaign_options and from other update tools like growsurf_update_campaign. It also immediately explains the partial-update model, making the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: it should be used when updating the Options tab, and it recommends fetching the current tab first to see the full object before sending changes. It does not explicitly name 'growsurf_get_campaign_options' as the fetch alternative, but 'fetch the tab first' conveys the intended workflow without needing a formal exclusion list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_rewardUpdate Campaign RewardADestructiveIdempotentInspect
Update an existing campaign reward (reward config) on your GrowSurf program. campaignRewardId is the reward key (e.g. crew_...). The reward type is immutable. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| event | No | The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only. | |
| limit | No | ||
| order | No | ||
| title | No | ||
| value | No | Tax valuation for the reward (the referrer's side of a double-sided reward). `fairMarketValueUSD` is the manual fair-market value in USD (major units). `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards always use `NONEMPLOYEE_SERVICES`. | |
| imageUrl | No | ||
| metadata | No | ||
| isVisible | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| couponCode | No | ||
| description | No | ||
| isUnlimited | No | ||
| limitDuration | No | ||
| referredValue | No | Tax valuation for the referred friend's side of a double-sided reward. `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards have no referred-friend side, so GrowSurf clears these settings. Use `PURCHASE_REBATE` only when that is the correct tax character. | |
| numberOfWinners | No | ||
| campaignRewardId | Yes | ||
| referralCouponCode | No | ||
| commissionStructure | No | Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED. | |
| conversionsRequired | No | ||
| nextMilestonePrefix | No | ||
| nextMilestoneSuffix | No | ||
| referralDescription | No | ||
| referredRewardUpfront | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey read-only=false, destructive=true, and idempotent=true, so the description's additional behavioral notes are what matter. It adds non-obvious details: the reward type is immutable and the call targets either an explicit campaignId or the default GROWSURF_CAMPAIGN_ID. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The main verb and resource come first, followed by the required ID semantics, then the immutability constraint, then the targeting fallback. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 23-parameter update operation with nested tax and commission structures, the description is too thin. It does not state whether omitted fields are preserved or reset, which fields can safely be combined, or what configuration constraints apply beyond type immutability. The low schema coverage leaves a significant gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 22%, so the description should compensate for the many undocumented parameters. It adds meaning for only campaignRewardId and campaignId; the other 21 parameters, including nested objects like value, referredValue, and commissionStructure, receive no meaningful guidance from the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Update an existing campaign reward (reward config) on your GrowSurf program.' It also clarifies the reward key format and notes that the reward type is immutable, which distinguishes this update tool from create/delete/list siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for existing rewards because it requires a campaignRewardId, and it warns that type cannot be changed. However, it never explicitly contrasts this with growsurf_create_campaign_reward or growsurf_delete_campaign_reward, and it provides no when-not-to-use guidance or alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_campaign_webhookUpdate WebhookADestructiveIdempotentInspect
Update a webhook on your GrowSurf program by id (webhookId is primary for the program's primary webhook). Only the fields you send are changed. secret is write-only and never returned. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| secret | No | Write-only. | |
| isEnabled | No | ||
| webhookId | Yes | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| payloadUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=true, and idempotentHint=true. The description adds valuable behavioral context beyond those: partial update semantics ('Only the fields you send are changed'), the write-only nature of `secret` ('never returned'), and the campaign targeting fallback. It does not contradict the annotations. It could add more about side effects or reversibility, but the provided context is meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct information: what the tool does, the partial-update behavior, and the targeting fallback. The most important scoping information (webhookId primary) is front-loaded. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema, so return values need not be described. The description covers the key operational details: id-based targeting, partial updates, write-only secret, and campaign fallback. It lacks explicit mention of the `events` enum values or `isEnabled` semantics, but those are self-evident from the schema. Given the complexity of the anyOf requirement structure, a bit more guidance on which fields are commonly updated together would push this to a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, so the description must compensate. It does: it explains `webhookId` special value 'primary', clarifies that `secret` is write-only and never returned, and explains the `campaignId` fallback behavior. However, it does not elaborate on `events`, `payloadUrl`, or `isEnabled` semantics beyond what the schema's names imply, so it doesn't fully cover the gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Update'), a resource ('webhook on your GrowSurf program'), and the identifier mechanism ('by id', with `webhookId` is `primary` for the program's primary webhook). It also clarifies the partial-update semantics ('Only the fields you send are changed'), which distinguishes it from a full replacement. This clearly differentiates it from sibling tools like growsurf_create_campaign_webhook and growsurf_delete_campaign_webhook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use this tool: updating an existing webhook by id, with a special note for the primary webhook. It also explains the campaign targeting behavior ('Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID'). However, it does not explicitly state when NOT to use it or name alternatives like growsurf_create_campaign_webhook or growsurf_test_campaign_webhook, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_participantUpdate ParticipantADestructiveIdempotentInspect
Update a participant by GrowSurf participant ID or email. Only the fields you send are changed; read-only fields such as counters, isAffiliate, origin, and fraud state are rejected with a 400. In affiliate programs, affiliateStatus accepts APPROVED, SUSPENDED, or BANNED; APPROVED enrolls the participant, while SUSPENDED and BANNED require an existing affiliate. Affiliate enrollment cannot be removed through REST. notes is freeform internal notes (never shown to participants). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| No | Change the participant's email address. | ||
| notes | No | Freeform internal notes (internal only, never exposed to participants). | |
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| referredBy | No | ||
| vanityKeys | No | ||
| unsubscribed | No | ||
| participantId | No | ||
| referralStatus | No | ||
| affiliateStatus | No | Affiliate programs only. Sets the affiliate status. `APPROVED` also enrolls a participant who is not yet an affiliate. `SUSPENDED` and `BANNED` are rejected for non-affiliates. | |
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations carry only readOnlyHint=false and destructiveHint=true, and the description adds substantial behavioral context: partial-update behavior, 400 rejection of read-only fields (counters, isAffiliate, origin, fraud state), the affiliateStatus enrollment rules (APPROVED enrolls; SUSPENDED/BANNED require an existing affiliate), the REST limitation on removing affiliate enrollment, and notes never being shown to participants. No contradiction with the annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but logically front-loaded: core update behavior first, then rejection rules, affiliate caveats, notes privacy, and campaign targeting. Every sentence contributes information; the only mild redundancy is affiliateStatus detail that also appears in the schema, which is acceptable for a high-risk field.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter write operation with an output schema and nested objects, the description covers the critical behavioral context: identification keys, partial-update semantics, rejection behavior, affiliate constraints, and campaign targeting. Since an output schema exists, return values need not be described; the main remaining gap is parameter-level meaning for the undocumented fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 31% (4 of 13 params documented), and the description meaningfully compensates for the riskiest semantics: it clarifies that only sent fields change, which fields get rejected, and how affiliateStatus behaves. But it adds little for the nine undocumented parameters (referredBy, vanityKeys, unsubscribed, metadata, firstName, lastName, participantId, participantEmail, referralStatus), so the compensation is incomplete for a tool with this many parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause 'Update a participant by GrowSurf participant ID or email' states a specific verb, resource, and the two identification methods. This cleanly separates it from siblings like growsurf_add_participant, growsurf_get_participant, and growsurf_bulk_delete_participants without needing to inspect the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong contextual cues for correct invocation, namely partial-update semantics ('Only the fields you send are changed') and the campaign targeting rule ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'). However, it never explicitly states when to prefer this tool over alternatives such as growsurf_add_participant or when updating is inappropriate, leaving the selection to inference from the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_program_resourceUpdate Program ResourceADestructiveIdempotentInspect
Update at least one participant resource field, or move it to a zero-based position. Only sent fields change. To replace a FILE, call growsurf_prepare_program_resource_file first and pass its uploadTicket and uploadResult unchanged. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Used with `LINK`. | |
| text | No | Used with `TEXT`. | |
| type | No | ||
| title | No | ||
| category | No | ||
| position | No | ||
| campaignId | No | Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server. | |
| resourceId | Yes | ||
| description | No | ||
| isPublished | No | ||
| uploadResult | No | The unmodified result returned by the secure upload flow for a replacement `FILE`. | |
| uploadTicket | No | The one-time upload ticket for a replacement `FILE`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=true, and destructiveHint=true. The description confirms the mutating nature ('Update', 'Only sent fields change') but doesn't elaborate on destructive implications or idempotency. It adds a key behavioral detail: targeting logic ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), which is useful beyond annotations. However, it doesn't disclose potential side effects like overwriting fields or irreversible changes, which is expected for a destructive update. The description covers the basics but could add more depth on what actually gets overwritten or the impact on FILE replacement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences long, which is concise for a complex tool with many conditional requirements. It front-loads the key purpose ('Update at least one participant resource field') and immediately explains the FILE replacement workflow. The targeting logic is placed at the end, which is less prominent but still clear. No wasted words, though the FILE replacement instruction could be more clearly separated from the general update purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists, para, so return values are covered by that. The description addresses the most complex aspect (FILE replacement) by referencing the prepare function and specifying pass-through of uploadTicket/uploadResult. However, it does not mention the conditional schema constraints like 'only one of type/url/text' or the anyOf requirements, which the agent might need to avoid validation errors. Given the complexity of the schema, the description provides sufficient but not exhaustive context to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 42%, so the schema leaves many parameters undocumented. The description clarifies the 'position' parameter as zero-based and the 'uploadTicket'/'uploadResult' requirement for FILE replacement, which adds meaning beyond the schema. However, it doesn't explain the semantics of fields like 'title', 'category', 'isPublished', or the difference between 'text' and 'url'. Given moderate coverage, the description adds some but not enough to fully compensate. It explicitly mentions the conditional requirement for uploadTicket/uploadResult, aiding the agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Update'), the resource ('program resource'), and the scope ('at least one participant resource field, or move it to a zero-based position'). It distinguishes this from the create and delete siblings by focusing on updating existing resourcesately, and mentions a specific alternative for replacing a FILE.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: to update fields or move position. It also provides a clear when-not: 'To replace a FILE, call growsurf_prepare_program_resource_file first' and instructs to pass the uploadTicket and uploadResult unchanged. This distinguishes from the create tool and gives operational context for the complex FILE replacement case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_teamUpdate TeamADestructiveIdempotentInspect
Update the display name of the team bound to the API key or OAuth connection. Personal profiles, billing, and team ownership are not editable here. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The team's display name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate destructiveHint=true and readOnlyHint=false, implying mutation. The description states it updates the display name, which aligns, but doesn't escalate the destructive nature—e.g., no warning that changing name may affect existing references. It adds value by clarifying scope but doesn't go beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences: first states the action and scope, second lists exclusions and requirements. No fluff, front-loads the core action, and packs useful constraints efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (1 param, no nested objects) and presence of output schema, the description covers essential usage. It clarifies auth requirements, exclusions, and the single editable field. Slight gap: doesn't mention potential side effects or irreversible changes, but given simple scope, it's sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for the single parameter 'name' with a description. The description adds no extra syntax or format details beyond schema, so baseline 3 is appropriate. It does not complement the schema, but doesn't need to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it updates the team's display name, specifying the scope (team bound to API key or OAuth connection). It distinguishes from other team-related tools like growsurf_get_team and growsurf_request_team_verification, though it doesn't explicitly name them. The verb 'update' and resource 'team' are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly notes what is NOT editable (personal profiles, billing, ownership), giving clear boundaries. It also states the required environment variable and that campaign ID is not needed, which helps agent decide when to use this tool. These details provide strong usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_webhook_normalizeNormalize Webhook PayloadARead-onlyIdempotentInspect
Validate/normalize a GrowSurf webhook payload and generate a best-effort idempotency key for dedupe.
| Name | Required | Description | Default |
|---|---|---|---|
| payload | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No | Whether the payload is a valid GrowSurf webhook envelope. |
| error | No | Why the payload failed validation. Present only when `ok` is `false`. |
| envelope | No | The normalized webhook envelope. Present only when `ok` is `true`. |
| idempotencyKey | No | A deterministic key for ignoring duplicate deliveries. Present only when `ok` is `true`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral nuance beyond annotations by noting the idempotency key is 'best-effort' and intended for dedupe, which helps the agent set expectations about reliability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that front-loads the core action and then adds the key generation behavior. There is no filler or repetition of the title, and every phrase earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single parameter, an output schema present, and annotations covering side-effect and idempotency traits, the description covers the essential context for invoking the tool. It does not explain what 'normalize' entails in detail, but for a simple utility this is not a critical gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the payload parameter has an empty schema, so the description must compensate. It does identify the payload as a 'GrowSurf webhook payload,' adding essential meaning, but it does not describe the expected structure, event types, or validation behavior. This is a minimal but non-trivial compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb pair ('Validate/normalize'), a precise resource ('a GrowSurf webhook payload'), and an additional distinct behavior ('generate a best-effort idempotency key'). This clearly distinguishes it from the many webhook CRUD siblings like growsurf_create_campaign_webhook and growsurf_test_campaign_webhook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context that this tool is for preprocessing incoming GrowSurf webhook payloads, which is enough to infer when an agent should reach for it versus CRUD webhook tools. It does not explicitly state when not to use it or name alternatives, but the context is not misleading and the purpose is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.16.0- Changed
growsurf_list_participants1 field changed- added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "description": "Exact-match filter on participant metadata, up to 3 keys, for example `{ \"customerId\": \"12345\" }`. Values compare as strings.", + "maxProperties": 3, + "minProperties": 1, + "type": "object" +}
1 tool update
v0.15.1- Changed
growsurf_bulk_delete_participants2 fields changed- changed
Output schema / descriptionPrevious value: -"Bulk delete outcome. A `200` response can still include `NOT_FOUND` or `ERROR` rows, so check the summary."New value: +"Bulk delete outcome. A `202` response includes `analyticsErasure` when analytics erasure is pending. Both `200` and `202` responses can include `NOT_FOUND` or `ERROR` rows, so check the summary." - added
Output schema / properties / analyticsErasureAdded value: +{ + "description": "Analytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions.", + "properties": { + "operationId": { + "description": "Opaque reference for support inquiries about this analytics erasure.", + "type": "string" + }, + "status": { + "description": "Erasure has been accepted but is not confirmed complete.", + "enum": [ + "pending" + ], + "type": "string" + } + }, + "type": "object" +}
27 tool updates
v0.14.0- Changed
growsurf_create_campaign2 fields changed- added
Input schema / properties / goalAdded value: +{ + "description": "What the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it.", + "enum": [ + "CUSTOMERS", + "USERS", + "SUBSCRIBERS", + "WAITLIST", + "B2B_SAAS_SELF_SERVICE", + "B2B_SAAS_ENTERPRISE", + "B2C_SUBSCRIPTIONS", + "FINANCIAL_SERVICES", + "ONLINE_EDUCATION", + "ONLINE_INSURANCE" + ], + "type": "string" +} - added
Input schema / properties / rewards / descriptionAdded value: +"Rewards to create with the program. Include this only when the person told you the amount and who funds it. Omit it and the program is seeded with starter rewards that are switched off, awarding nothing until the customer enables one. Send `[]` to start with no rewards at all."
- Changed
growsurf_create_campaign_reward5 fields changed- added
Input schema / properties / commissionStructure / allOfAdded value: +[ + { + "if": { + "properties": { + "event": { + "enum": [ + "CLICK", + "LEAD" + ] + } + }, + "required": [ + "event" + ] + }, + "then": { + "properties": { + "amount": { + "minimum": 1, + "type": "integer" + }, + "type": { + "enum": [ + "FIXED" + ] + } + }, + "required": [ + "amount" + ] + } + } +] - changed
Input schema / properties / commissionStructure / descriptionPrevious value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED." - added
Input schema / properties / commissionStructure / properties / amount / minimumAdded value: +1 - added
Input schema / properties / commissionStructure / properties / event / descriptionAdded value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`." - added
Input schema / properties / eventAdded value: +{ + "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.", + "enum": [ + "LEAD", + "CONVERSION" + ], + "type": "string" +}
- Added
growsurf_create_program_resource - Added
growsurf_delete_program_resource - Changed
growsurf_get_campaign1 field changed- added
Output schema / properties / rewardEvidenceAdded value: +{ + "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.", + "properties": { + "approvalPolicy": { + "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.", + "enum": [ + "manual", + "automatic", + "unknown" + ], + "type": "string" + }, + "automaticFulfillmentMarking": { + "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.", + "type": [ + "boolean", + "null" + ] + }, + "basis": { + "enum": [ + "this_response_only" + ], + "type": "string" + }, + "conclusion": { + "type": "string" + }, + "deliveryStatus": { + "enum": [ + "unknown" + ], + "type": "string" + }, + "integrationConnection": { + "enum": [ + "not_established" + ], + "type": "string" + }, + "nextStep": { + "type": "string" + }, + "programReferralTrigger": { + "enum": [ + "not_established" + ], + "type": "string" + } + }, + "type": "object" +}
- Added
growsurf_get_campaign_activation_analytics - Changed
growsurf_get_campaign_analytics4 fields changed- changed
Input schema / properties / include / descriptionPrevious value: -"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, and `email`. Combine `email` with `previousPeriod` or a non-total `interval` to receive matching email metrics for those windows."New value: +"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view." - added
Input schema / properties / platformAdded value: +{ + "description": "Client-platform filter for engagement. Defaults to `ALL`.", + "enum": [ + "ALL", + "WEB", + "IOS", + "ANDROID" + ], + "type": "string" +} - added
Input schema / properties / timezoneAdded value: +{ + "description": "IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.", + "type": "string" +} - added
Output schema / properties / engagementAdded value: +{ + "description": "Opt-in participant engagement grouped by when activity occurred.", + "properties": { + "breakdowns": { + "description": "Engagement grouped by platform, portal source, and share channel.", + "properties": { + "firstShareChannels": { + "items": { + "properties": { + "key": { + "description": "Stable first-share channel key.", + "type": "string" + }, + "sharingParticipants": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "platforms": { + "items": { + "properties": { + "activeParticipants": { + "type": "integer" + }, + "key": { + "enum": [ + "WEB", + "IOS", + "ANDROID" + ], + "type": "string" + }, + "portalViews": { + "type": "integer" + }, + "shareActions": { + "type": "integer" + }, + "sharingParticipants": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "portalViewSources": { + "items": { + "properties": { + "activeParticipants": { + "type": "integer" + }, + "key": { + "enum": [ + "DEFAULT_LAUNCHER", + "SDK_OPEN", + "CSS_CLASS", + "EMBEDDABLE_ELEMENT", + "HOSTED_PORTAL", + "NATIVE_WINDOW", + "UNKNOWN" + ], + "type": "string" + }, + "portalViews": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "shareChannels": { + "items": { + "properties": { + "key": { + "description": "Stable share-channel key.", + "type": "string" + }, + "shareActions": { + "type": "integer" + }, + "sharingParticipants": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "comparison": { + "description": "Current-versus-previous engagement changes.", + "properties": { + "metrics": { + "properties": { + "activeParticipants": { + "description": "Change in unique active participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "portalViews": { + "description": "Change in total signed-in portal views.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatActiveParticipants": { + "description": "Change in repeat active participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatSharingParticipants": { + "description": "Change in repeat sharing participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "shareActions": { + "description": "Change in total accepted share actions.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "sharingParticipants": { + "description": "Change in unique sharing participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": [ + "object", + "null" + ] + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + } + }, + "type": "object" + }, + "coverageStartAt": { + "description": "Earliest expected complete capture time (Unix ms), or `null` until coverage begins.", + "type": [ + "integer", + "null" + ] + }, + "interval": { + "description": "Bucket size used for `series`.", + "enum": [ + "day", + "week", + "month" + ], + "type": "string" + }, + "metricContractVersion": { + "description": "Shared activation and engagement metric version.", + "type": "integer" + }, + "period": { + "description": "Exact half-open current and previous activity bounds.", + "properties": { + "effectiveFrom": { + "description": "Measured start after coverage, or `null`.", + "type": [ + "integer", + "null" + ] + }, + "from": { + "description": "Inclusive requested activity start (Unix ms).", + "type": "integer" + }, + "previousFrom": { + "description": "Inclusive previous-period start (Unix ms).", + "type": "integer" + }, + "previousTo": { + "description": "Exclusive previous-period end (Unix ms).", + "type": "integer" + }, + "to": { + "description": "Exclusive requested activity end (Unix ms).", + "type": "integer" + } + }, + "type": "object" + }, + "platform": { + "description": "Requested and applied client-platform filter.", + "properties": { + "applied": { + "enum": [ + "ALL", + "WEB", + "IOS", + "ANDROID" + ], + "type": "string" + }, + "requested": { + "enum": [ + "ALL", + "WEB", + "IOS", + "ANDROID" + ], + "type": "string" + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + } + }, + "type": "object" + }, + "previousPeriod": { + "description": "Engagement totals for the immediately previous equal activity period.", + "properties": { + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "totals": { + "description": "Unique participant metrics and action totals for one activity period.", + "properties": { + "activeParticipants": { + "description": "Eligible participants with a signed-in portal view.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "portalViews": { + "description": "Total accepted signed-in portal-view actions.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatActiveParticipants": { + "description": "Eligible participants active on at least two distinct program-local days.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatSharingParticipants": { + "description": "Eligible participants who shared on at least two distinct program-local days.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "retainedActiveParticipants": { + "description": "Eligible participants active in both the current and previous equal periods.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "shareActions": { + "description": "Total accepted referral-link share actions.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "sharingParticipants": { + "description": "Eligible participants with an accepted share action.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "sharingRate": { + "description": "Sharing participants divided by active participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + "programType": { + "description": "Program eligibility model.", + "enum": [ + "REFERRAL", + "AFFILIATE" + ], + "type": "string" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "series": { + "description": "Continuous half-open activity intervals in ascending order.", + "items": { + "properties": { + "activeParticipants": { + "description": "Unique active participants.", + "type": "integer" + }, + "from": { + "description": "Inclusive interval start (Unix ms).", + "type": "integer" + }, + "portalViews": { + "description": "Total signed-in portal views.", + "type": "integer" + }, + "shareActions": { + "description": "Total accepted share actions.", + "type": "integer" + }, + "sharingParticipants": { + "description": "Unique sharing participants.", + "type": "integer" + }, + "to": { + "description": "Exclusive interval end (Unix ms).", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "timezone": { + "description": "IANA timezone used for interval and distinct-day calculations.", + "type": "string" + }, + "totals": { + "description": "Unique participant metrics and action totals for one activity period.", + "properties": { + "activeParticipants": { + "description": "Eligible participants with a signed-in portal view.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "portalViews": { + "description": "Total accepted signed-in portal-view actions.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatActiveParticipants": { + "description": "Eligible participants active on at least two distinct program-local days.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "repeatSharingParticipants": { + "description": "Eligible participants who shared on at least two distinct program-local days.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "retainedActiveParticipants": { + "description": "Eligible participants active in both the current and previous equal periods.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "shareActions": { + "description": "Total accepted referral-link share actions.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "sharingParticipants": { + "description": "Eligible participants with an accepted share action.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "sharingRate": { + "description": "Sharing participants divided by active participants.", + "properties": { + "delta": { + "description": "Optional current-minus-previous difference on comparison metrics.", + "type": "number" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + }, + "value": { + "description": "Measured value, or `null` when unavailable.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Changed
growsurf_get_campaign_design5 fields changed- added
Output schema / properties / participantAvatarStyleAdded value: +{ + "description": "How participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`.", + "enum": [ + "CHARACTERS", + "INITIALS", + "ANIMALS", + "GRADIENT" + ], + "type": "string" +} - changed
Output schema / properties / referredExperience / descriptionPrevious value: -"The banner and headline shown to a visitor who arrives through a referral link."New value: +"The banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs." - added
Output schema / properties / referredExperience / propertiesAdded value: +{ + "isOfferPopupConfettiEnabled": { + "description": "Whether to show confetti after a claim.", + "type": "boolean" + }, + "isOfferPopupEnabled": { + "description": "Whether referred visitors see the Claim Offer Popup.", + "type": "boolean" + }, + "isOfferPopupOverlayDimmed": { + "description": "Whether a centered popup dims the page behind it.", + "type": "boolean" + }, + "isOfferPopupReferrerImageShown": { + "description": "Whether to show the referrer's profile image.", + "type": "boolean" + }, + "isOfferPopupShownOnAllPages": { + "description": "Whether the popup can appear on every installed page.", + "type": "boolean" + }, + "offerPopupButtonText": { + "description": "Offer-save button text.", + "maxLength": 100, + "type": [ + "string", + "null" + ] + }, + "offerPopupDelaySeconds": { + "description": "Delay before the popup appears.", + "enum": [ + 0, + 3, + 5, + 10 + ], + "type": "integer" + }, + "offerPopupDescription": { + "description": "Text below the popup heading.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + }, + "offerPopupImageUrl": { + "description": "Optional popup image.", + "maxLength": 500, + "type": [ + "string", + "null" + ] + }, + "offerPopupPlacement": { + "description": "Where the popup appears.", + "enum": [ + "CENTER", + "BOTTOM", + "BOTTOM_RIGHT", + "BOTTOM_LEFT", + "TOP" + ], + "type": "string" + }, + "offerPopupSecondaryLinkText": { + "description": "Optional post-claim link text.", + "maxLength": 100, + "type": [ + "string", + "null" + ] + }, + "offerPopupSecondaryLinkUrl": { + "description": "Optional post-claim link destination. When saving, use `http://` or `https://`. Send `null` or an empty string to clear it.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + }, + "offerPopupThankYouButtonText": { + "description": "Post-claim signup button text.", + "maxLength": 100, + "type": [ + "string", + "null" + ] + }, + "offerPopupThankYouText": { + "description": "Message shown after the offer is saved.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + }, + "offerPopupTitle": { + "description": "Popup heading.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + } +} - added
Output schema / properties / resourcesAdded value: +{ + "description": "Participant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools.", + "type": "object" +} - added
Output schema / properties / theme / propertiesAdded value: +{ + "referredExperienceOfferPopup": { + "description": "Paid-plan color settings for the Claim Offer Popup.", + "properties": { + "backgroundColor": { + "description": "Popup background color.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + }, + "color": { + "description": "Popup text color.", + "maxLength": 255, + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + } +}
- Changed
growsurf_get_campaign_emails1 field changed- added
Output schema / properties / offerClaimedAdded value: +{ + "description": "Sent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed.", + "type": "object" +}
- Changed
growsurf_get_campaign_options2 fields changed- changed
Output schema / properties / autoFulfillRewards / descriptionPrevious value: -"Referral programs only. Automatically mark earned rewards as fulfilled."New value: +"Referral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure." - added
Output schema / properties / rewardEvidenceAdded value: +{ + "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.", + "properties": { + "approvalPolicy": { + "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.", + "enum": [ + "manual", + "automatic", + "unknown" + ], + "type": "string" + }, + "automaticFulfillmentMarking": { + "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.", + "type": [ + "boolean", + "null" + ] + }, + "basis": { + "enum": [ + "this_response_only" + ], + "type": "string" + }, + "conclusion": { + "type": "string" + }, + "deliveryStatus": { + "enum": [ + "unknown" + ], + "type": "string" + }, + "integrationConnection": { + "enum": [ + "not_established" + ], + "type": "string" + }, + "nextStep": { + "type": "string" + }, + "programReferralTrigger": { + "enum": [ + "not_established" + ], + "type": "string" + } + }, + "type": "object" +}
- Changed
growsurf_get_integration_connect_link5 fields changed- changed
Input schema / properties / integration / enumPrevious value: -[ - "stripe", - "chargebee", - "recurly", - "paypal", - "wisecom", - "tangocard", - "hubspot", - "salesforce", - "marketo", - "mailchimp", - "activecampaign", - "bentonow", - "mailerlite", - "resenddotcom", - "loopsdotso", - "convertkit", - "constantContact", - "campaignMonitor", - "aweber", - "klaviyo", - "mailjet", - "sendgrid", - "sendinblue", - "emailoctopus", - "customerio", - "getresponse", - "drip", - "googleanalytics", - "segmentanalytics", - "posthoganalytics", - "mixpanelanalytics", - "pendo", - "fullstory", - "heapanalytics", - "amplitude", - "googleads", - "metaads", - "linkedinads", - "twitterads", - "slack", - "intercom", - "helpScout", - "zapier", - "integromat", - "pabblyConnect", - "webhook", - "baskHealth" -]New value: +[ + "stripe", + "chargebee", + "recurly", + "paypal", + "wisecom", + "tangoCard", + "tremendous", + "hubspot", + "salesforce", + "marketo", + "mailchimp", + "activecampaign", + "braze", + "bentonow", + "mailerlite", + "resenddotcom", + "loopsdotso", + "convertkit", + "constantContact", + "campaignMonitor", + "aweber", + "klaviyo", + "mailjet", + "sendgrid", + "sendinblue", + "emailoctopus", + "customerio", + "getresponse", + "drip", + "googleanalytics", + "segmentanalytics", + "posthoganalytics", + "mixpanelanalytics", + "pendo", + "fullstory", + "heapanalytics", + "amplitude", + "googleads", + "metaads", + "linkedinads", + "twitterads", + "slack", + "intercom", + "helpScout", + "zapier", + "integromat", + "pabblyConnect", + "webhook", + "baskHealth", + "tangocard" +] - added
Output schema / properties / autoDisabledAdded value: +{ + "description": "Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / connectedAdded value: +{ + "description": "Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / enabledAdded value: +{ + "description": "Whether the integration is switched on and currently working. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / programVerifiedAdded value: +{ + "description": "`true` when the program's live integration list was read, so the program id is confirmed and the three state fields below are present and current. `false` when that read was unavailable, for example without an API key or `program:read`: the link still works but points at the production dashboard, and the state fields are omitted because the state is unknown. Never treat an absent state field as `false`.", + "type": "boolean" +}
- Changed
growsurf_get_participant5 fields changed- added
Output schema / properties / rewardEvidenceAdded value: +{ + "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.", + "properties": { + "approvalPolicy": { + "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.", + "enum": [ + "manual", + "automatic", + "unknown" + ], + "type": "string" + }, + "automaticFulfillmentMarking": { + "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.", + "type": [ + "boolean", + "null" + ] + }, + "basis": { + "enum": [ + "this_response_only" + ], + "type": "string" + }, + "conclusion": { + "type": "string" + }, + "deliveryStatus": { + "enum": [ + "unknown" + ], + "type": "string" + }, + "integrationConnection": { + "enum": [ + "not_established" + ], + "type": "string" + }, + "nextStep": { + "type": "string" + }, + "programReferralTrigger": { + "enum": [ + "not_established" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Output schema / properties / rewards / items / properties / fulfilledAt / descriptionPrevious value: -"When the reward was fulfilled, as a Unix timestamp in milliseconds. `null` until fulfilled."New value: +"When the reward was marked fulfilled, as a Unix timestamp in milliseconds. `null` until marked fulfilled; this is not a delivery receipt." - changed
Output schema / properties / rewards / items / properties / isFulfilled / descriptionPrevious value: -"`true` once the reward has been fulfilled."New value: +"`true` once the reward is marked fulfilled. Confirm actual delivery through fulfillment records." - changed
Output schema / properties / rewards / items / properties / status / descriptionPrevious value: -"Fulfillment status of the earned reward."New value: +"Fulfillment marking of the earned reward. `FULFILLED` records that it was marked fulfilled, not proof of delivery. `CANCELLED` means an unpaid Lead reward was reversed before fulfillment." - changed
Output schema / properties / rewards / items / properties / status / enumPrevious value: -[ - "PENDING", - "FULFILLED" -]New value: +[ + "PENDING", + "FULFILLED", + "CANCELLED" +]
- Changed
growsurf_get_participant_analytics9 fields changed- added
Input schema / properties / days / descriptionAdded value: +"Number of days for optional `series` and `email` analytics. Does not filter the all-time base response." - changed
Input schema / properties / endDate / descriptionPrevious value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`." - changed
Input schema / properties / include / descriptionPrevious value: -"Comma-separated optional data. Current values are `series` and `email`; the API returns `400` for unknown values."New value: +"Comma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values." - changed
Input schema / properties / startDate / descriptionPrevious value: -"Start of the timeframe, Unix timestamp in ms. Use with endDate instead of days."New value: +"Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`." - added
Output schema / properties / activationAdded value: +{ + "description": "Opt-in covered eligibility and first-milestone analytics for one participant.", + "properties": { + "cohort": { + "description": "Program-specific eligibility anchor and covered value.", + "properties": { + "anchorAt": { + "description": "Covered anchor time (Unix ms). `null` is unknown and does not mean enrollment never occurred.", + "type": [ + "integer", + "null" + ] + }, + "anchorField": { + "enum": [ + "enrolledAsAdvocateAt", + "approvedAsAffiliateAt" + ], + "type": "string" + } + }, + "type": "object" + }, + "coverageStartAt": { + "description": "Earliest expected complete participant activation capture time (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "enrolledAsAdvocateAt": { + "description": "Referral only. Covered advocate enrollment (Unix ms); `null` does not mean enrollment never occurred.", + "type": [ + "integer", + "null" + ] + }, + "metricContractVersion": { + "description": "Shared activation and engagement metric version.", + "type": "integer" + }, + "milestones": { + "description": "Covered first milestones. A `null` value is unknown and does not mean the action never happened.", + "properties": { + "firstCommissionAt": { + "description": "Affiliate only. First covered commission (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstLeadAt": { + "description": "First covered referred lead (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstPortalViewedAt": { + "description": "First covered signed-in portal view (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstReferralAt": { + "description": "First covered credited referral (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstReferralLinkCopiedAt": { + "description": "First covered referral-link copy (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstRewardAt": { + "description": "Referral only. First covered participant reward (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstShareAt": { + "description": "First covered accepted share action (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "firstShareChannel": { + "description": "Channel for `firstShareAt`, or `null` when the first covered share is unavailable.", + "enum": [ + "email", + "facebook", + "twitter", + "linkedin", + "pinterest", + "threads", + "bluesky", + "sms", + "messenger", + "whatsapp", + "wechat", + "telegram", + "reddit", + "tumblr", + "qrcode", + "copyRefLink", + "iosNativeShare", + "androidNativeShare", + null + ], + "type": [ + "string", + "null" + ] + }, + "firstUniqueClickAt": { + "description": "First covered unique referral visit (Unix ms).", + "type": [ + "integer", + "null" + ] + }, + "payoutSetupCompletedAt": { + "description": "First covered payout-setup completion (Unix ms).", + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "programType": { + "description": "Program eligibility model.", + "enum": [ + "REFERRAL", + "AFFILIATE" + ], + "type": "string" + }, + "reason": { + "description": "Why a value is partial or unavailable, or `null` when it is available.", + "enum": [ + "COVERAGE_UNAVAILABLE", + "PRE_COVERAGE", + "PARTIAL_COVERAGE", + "INSUFFICIENT_COVERAGE", + "EMPTY_DENOMINATOR", + "QUERY_LIMIT_EXCEEDED", + "PARTICIPANT_NOT_ELIGIBLE", + null + ], + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Whether the value is complete, partial, or unavailable for the requested bounds.", + "enum": [ + "AVAILABLE", + "PARTIAL", + "UNAVAILABLE" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Output schema / properties / analytics / descriptionPrevious value: -"Participant analytics totals."New value: +"All-time participant analytics totals. Date-window parameters do not filter these fields." - changed
Output schema / properties / analytics / properties / leads / descriptionPrevious value: -"Pending referral credits."New value: +"Current pending referral credits." - added
Output schema / properties / series / items / properties / portalViewsAdded value: +{ + "description": "Covered signed-in portal views, or `null` outside known coverage.", + "type": [ + "integer", + "null" + ] +} - added
Output schema / properties / series / items / properties / shareActionsAdded value: +{ + "description": "Covered accepted share actions, or `null` outside known coverage.", + "type": [ + "integer", + "null" + ] +}
- Changed
growsurf_list_campaign_rewards2 fields changed- added
Output schema / properties / rewardEvidenceAdded value: +{ + "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.", + "properties": { + "approvalPolicy": { + "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.", + "enum": [ + "manual", + "automatic", + "unknown" + ], + "type": "string" + }, + "automaticFulfillmentMarking": { + "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.", + "type": [ + "boolean", + "null" + ] + }, + "basis": { + "enum": [ + "this_response_only" + ], + "type": "string" + }, + "conclusion": { + "type": "string" + }, + "deliveryStatus": { + "enum": [ + "unknown" + ], + "type": "string" + }, + "integrationConnection": { + "enum": [ + "not_established" + ], + "type": "string" + }, + "nextStep": { + "type": "string" + }, + "programReferralTrigger": { + "enum": [ + "not_established" + ], + "type": "string" + } + }, + "type": "object" +} - added
Output schema / properties / rewards / items / properties / eventAdded value: +{ + "description": "The referral event that earns this Campaign Reward. `LEAD` means a referred signup; `CONVERSION` means a qualifying action.", + "enum": [ + "LEAD", + "CONVERSION", + null + ], + "type": [ + "string", + "null" + ] +}
- Added
growsurf_list_integrations - Changed
growsurf_list_participants1 field changed- added
Output schema / properties / rewardEvidenceAdded value: +{ + "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.", + "properties": { + "approvalPolicy": { + "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.", + "enum": [ + "manual", + "automatic", + "unknown" + ], + "type": "string" + }, + "automaticFulfillmentMarking": { + "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.", + "type": [ + "boolean", + "null" + ] + }, + "basis": { + "enum": [ + "this_response_only" + ], + "type": "string" + }, + "conclusion": { + "type": "string" + }, + "deliveryStatus": { + "enum": [ + "unknown" + ], + "type": "string" + }, + "integrationConnection": { + "enum": [ + "not_established" + ], + "type": "string" + }, + "nextStep": { + "type": "string" + }, + "programReferralTrigger": { + "enum": [ + "not_established" + ], + "type": "string" + } + }, + "type": "object" +}
- Added
growsurf_list_program_resources - Added
growsurf_prepare_program_resource_file - Added
growsurf_program_design_advisor - Changed
growsurf_record_sale3 fields changed- changed
Input schema / allOfPrevious value: -[ - { - "anyOf": [ - { - "required": [ - "participantId" - ] - }, - { - "required": [ - "participantEmail" - ] - } - ] - }, - { - "anyOf": [ - { - "required": [ - "externalId" - ] - }, - { - "required": [ - "transactionId" - ] - }, - { - "required": [ - "orderId" - ] - }, - { - "required": [ - "paymentId" - ] - }, - { - "required": [ - "invoiceId" - ] - }, - { - "required": [ - "paymentIntentId" - ] - }, - { - "required": [ - "chargeId" - ] - } - ] - } -]New value: +[ + { + "anyOf": [ + { + "required": [ + "participantId" + ] + }, + { + "required": [ + "participantEmail" + ] + } + ] + }, + { + "anyOf": [ + { + "required": [ + "externalId" + ] + }, + { + "required": [ + "transactionId" + ] + }, + { + "required": [ + "orderId" + ] + }, + { + "required": [ + "paymentId" + ] + }, + { + "required": [ + "invoiceId" + ] + }, + { + "required": [ + "paymentIntentId" + ] + }, + { + "required": [ + "chargeId" + ] + } + ] + }, + { + "if": { + "required": [ + "paymentProvider" + ] + }, + "then": { + "required": [ + "testMode", + "transactionId" + ] + } + }, + { + "if": { + "not": { + "required": [ + "paymentProvider" + ] + } + }, + "then": { + "not": { + "required": [ + "testMode" + ] + } + } + } +] - added
Input schema / properties / paymentProviderAdded value: +{ + "description": "Connected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions.", + "enum": [ + "stripe", + "chargebee", + "recurly" + ], + "type": "string" +} - added
Input schema / properties / testModeAdded value: +{ + "description": "Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.", + "type": "boolean" +}
- Changed
growsurf_refund_transaction6 fields changed- changed
Input schema / allOfPrevious value: -[ - { - "anyOf": [ - { - "required": [ - "participantId" - ] - }, - { - "required": [ - "participantEmail" - ] - } - ] - }, - { - "anyOf": [ - { - "required": [ - "externalId" - ] - }, - { - "required": [ - "transactionId" - ] - }, - { - "required": [ - "orderId" - ] - }, - { - "required": [ - "paymentId" - ] - }, - { - "required": [ - "invoiceId" - ] - }, - { - "required": [ - "paymentIntentId" - ] - }, - { - "required": [ - "chargeId" - ] - } - ] - } -]New value: +[ + { + "anyOf": [ + { + "required": [ + "participantId" + ] + }, + { + "required": [ + "participantEmail" + ] + } + ] + }, + { + "anyOf": [ + { + "required": [ + "externalId" + ] + }, + { + "required": [ + "transactionId" + ] + }, + { + "required": [ + "orderId" + ] + }, + { + "required": [ + "paymentId" + ] + }, + { + "required": [ + "invoiceId" + ] + }, + { + "required": [ + "paymentIntentId" + ] + }, + { + "required": [ + "chargeId" + ] + } + ] + }, + { + "if": { + "required": [ + "paymentProvider" + ] + }, + "then": { + "required": [ + "testMode", + "transactionId" + ] + } + }, + { + "if": { + "not": { + "required": [ + "paymentProvider" + ] + } + }, + "then": { + "not": { + "required": [ + "testMode" + ] + } + } + } +] - added
Input schema / properties / paymentProviderAdded value: +{ + "description": "Connected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider.", + "enum": [ + "stripe", + "chargebee", + "recurly" + ], + "type": "string" +} - added
Input schema / properties / refundAmount / descriptionAdded value: +"Positive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation." - added
Input schema / properties / refundHistoryCompleteAdded value: +{ + "description": "Set true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list.", + "type": "boolean" +} - added
Input schema / properties / refundId / descriptionAdded value: +"Stable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation." - added
Input schema / properties / testModeAdded value: +{ + "description": "Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`.", + "type": "boolean" +}
- Added
growsurf_troubleshoot_referral_tracking - Changed
growsurf_update_campaign1 field changed- added
Input schema / anyOfAdded value: +[ + { + "required": [ + "name" + ] + }, + { + "required": [ + "companyName" + ] + }, + { + "required": [ + "companyLogoImageUrl" + ] + }, + { + "required": [ + "status" + ] + } +]
- Changed
growsurf_update_campaign_installation1 field changed- added
Input schema / properties / replaceExistingShareUrlAdded value: +{ + "description": "Set this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused.", + "type": "boolean" +}
- Changed
growsurf_update_campaign_reward5 fields changed- added
Input schema / properties / commissionStructure / allOfAdded value: +[ + { + "if": { + "properties": { + "event": { + "enum": [ + "CLICK", + "LEAD" + ] + } + }, + "required": [ + "event" + ] + }, + "then": { + "properties": { + "amount": { + "minimum": 1, + "type": "integer" + }, + "type": { + "enum": [ + "FIXED" + ] + } + }, + "required": [ + "amount" + ] + } + } +] - changed
Input schema / properties / commissionStructure / descriptionPrevious value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED." - added
Input schema / properties / commissionStructure / properties / amount / minimumAdded value: +1 - added
Input schema / properties / commissionStructure / properties / event / descriptionAdded value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`." - added
Input schema / properties / eventAdded value: +{ + "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.", + "enum": [ + "LEAD", + "CONVERSION" + ], + "type": "string" +}
- Changed
growsurf_update_campaign_webhook1 field changed- added
Input schema / anyOfAdded value: +[ + { + "required": [ + "payloadUrl" + ] + }, + { + "required": [ + "events" + ] + }, + { + "required": [ + "secret" + ] + }, + { + "required": [ + "isEnabled" + ] + } +]
- Added
growsurf_update_program_resource
54 tool updates
v0.12.2- First observed
growsurf_add_participant - First observed
growsurf_agent_program_creation_eval - First observed
growsurf_api_library_snippets - First observed
growsurf_bulk_delete_participants - First observed
growsurf_cancel_delayed_referral - First observed
growsurf_capture_referral_flow_screenshots - First observed
growsurf_client_snippets - First observed
growsurf_clone_campaign - First observed
growsurf_create_account - First observed
growsurf_create_campaign - First observed
growsurf_create_campaign_reward - First observed
growsurf_create_campaign_webhook - First observed
growsurf_create_mobile_participant_token - First observed
growsurf_delete_campaign_reward - First observed
growsurf_delete_campaign_webhook - First observed
growsurf_email_participant - First observed
growsurf_embeddable_element_snippet - First observed
growsurf_get_campaign - First observed
growsurf_get_campaign_analytics - First observed
growsurf_get_campaign_design - First observed
growsurf_get_campaign_emails - First observed
growsurf_get_campaign_installation - First observed
growsurf_get_campaign_options - First observed
growsurf_get_integration_connect_link - First observed
growsurf_get_participant - First observed
growsurf_get_participant_activity_logs - First observed
growsurf_get_participant_analytics - First observed
growsurf_get_participant_payout_destination - First observed
growsurf_get_team - First observed
growsurf_grsf_config_snippet - First observed
growsurf_integration_guide - First observed
growsurf_list_campaign_rewards - First observed
growsurf_list_campaign_webhooks - First observed
growsurf_list_campaigns - First observed
growsurf_list_participants - First observed
growsurf_mobile_sdk_guide - First observed
growsurf_participant_auth_hash - First observed
growsurf_record_sale - First observed
growsurf_refund_transaction - First observed
growsurf_request_participant_payout_destination_confirmation - First observed
growsurf_request_team_verification - First observed
growsurf_resend_team_owner_verification_email - First observed
growsurf_test_campaign_webhook - First observed
growsurf_trigger_referral - First observed
growsurf_update_campaign - First observed
growsurf_update_campaign_design - First observed
growsurf_update_campaign_emails - First observed
growsurf_update_campaign_installation - First observed
growsurf_update_campaign_options - First observed
growsurf_update_campaign_reward - First observed
growsurf_update_campaign_webhook - First observed
growsurf_update_participant - First observed
growsurf_update_team - First observed
growsurf_webhook_normalize
TDQS
Scored across 63 tools
Most CRUD tools are clearly separated by resource (campaign, reward, participant, webhook, resource), but the many guidance/snippet tools (integration_guide, client_snippets, api_library_snippets, mobile_sdk_guide, embeddable_element_snippet, grsf_config_snippet) have overlapping boundaries. Campaign analytics vs. activation analytics also require careful reading to tell apart.
The growsurf_ prefix and snake_case are consistent, and most tools follow verb_noun. However, several tools are noun phrases (growsurf_client_snippets, growsurf_grsf_config_snippet, growsurf_program_design_advisor, growsurf_api_library_snippets), and names like growsurf_agent_program_creation_eval break the predominant pattern.
63 tools is far beyond the 50+ threshold and makes the surface very hard to navigate. The broad domain justifies some size, but the dozens of doc/snippet generators and overlapping analytics tools could be consolidated significantly.
The surface covers account/team management, campaign lifecycle, editor tabs, rewards, resources, webhooks, participants, analytics, payouts, integrations, and affiliate transactions. Minor gaps remain (no campaign deletion, no single-participant delete, affiliate enrollment cannot be removed), but core workflows have no dead ends.
Maintenance
Related MCP Connectors
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Run B2B outreach from your AI agent: 250+ tools for campaigns, leads, LinkedIn and email workflows.
Manage 230M+ influencers, track campaigns, and access real-time CIMS analytics via AI agents
Manage BioFlow link-in-bio pages, blocks, leads, and analytics from AI agents.
Related MCP Servers
- FlicenseAqualityCmaintenanceEnables users to manage affiliate marketing directly within Claude by connecting to the Affilync platform. Affiliates can search campaigns and track earnings, while brands can create campaigns, monitor performance, and manage affiliate applications through natural language.201-
- AlicenseAqualityDmaintenanceEnables AI agents to access affiliate marketing capabilities through AgentFuse's API, allowing them to browse affiliate programs, generate tracked links, and record conversions without writing HTTP code.723 npmMIT
- FlicenseAqualityDmaintenanceEnables AI agents to automate sales outreach, research leads, and manage campaigns directly in OutreachPilot via natural language commands.31-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to manage GoHighLevel workspaces through natural language, with 508 tools across 18 domains for complete CRM, marketing, and workflow automation.Apache 2.0