// concepts

Grouped tools

How superagnt_ MCP servers and agents list one tool per resource and risk class with an action argument, how a grouped call is routed and checked, and how connection tools are grouped.

superagnt_ lists the same operations two ways over MCP: one tool per operation, or one tool per resource and risk class with an action argument that picks the operation. Both run the same operations with the same permissions, billing and audit trail. Grouping changes how tools are listed and named: a grouped server lists far fewer tools, so a client spends less of its context window on tool definitions. Tool families, the name prefixes and what a server serves by default are on Tools and tool families.

01

Two ways to list the same tools

  • Per-operation: one tool per operation, such as agnt_db_select, data_x_user_details_get_user_details or connection_hubspot_search_deals.
  • Grouped: one tool per resource and risk class, such as agnt_db_read, called with action: "select" to run agnt_db_select.

Which surface you get

Server or agentSurface
Every workspace MCP server: the default server at https://mcp.superagnt.com/mcp, custom servers and scoped installs such as /mcp/tiktok, including servers created before grouped tools shippedGrouped
Agents created in the superagnt app, by the Agnt Wizard or with agnt_agents_createGrouped
Agents created before grouped tools shippedPer-operation
Agents the platform sets up from its own templates: hires, your workspace's first agent and the inbox managerPer-operation

A server's or agent's surface is set when it is created, and no setting changes it later. The tool count the superagnt app shows for a server is what a client sees in tools/list, so a grouped tool counts once. What a deployed agent can call is on Agent tools and the MCP gateway.

02

Per-operation names keep working

Every per-operation name a server or agent serves stays callable, whatever its surface. A prompt, skill or script that calls agnt_db_select keeps working on a grouped server, even though tools/list shows agnt_db_read. Operations a grouped listing leaves out, such as an older version of an operation that a newer one replaces, are callable by name too.

Grouping never widens what a caller can do. A grouped tool only routes to operations the server or agent already has: it appears when at least one of its operations is present, and its action list holds only those. A custom server whose tool list holds only agnt_db_select and agnt_db_execute_sql lists agnt_db_read with one action, agnt_db_sql with one action, and no agnt_db_write at all. When a tool is served only some of its actions, its description has a line naming the rest, so a model does not try them:

agnt_db_read with only selecttext
Check database status, list tables, extensions and migrations, and select rows.
Actions:
- select (agnt_db_select): Read rows from a public.* table. Needs: table.
Not available here: status, list_tables, list_extensions, list_migrations.

Per-operation names are also the key everything else is stored under:

  • Permissions, approvals and usage always name the operation that ran, whichever name was called. A call to data_x_users with action: "tweets" is gated, approved and recorded in usage as data_x_user_s_tweets_get_user_tweets.
  • Stored tool lists are per operation. A custom server's tool list, agnt_tools_enable, and an agent's tools.add, tools.remove and permissions.tools all store per-operation names: a grouped name given to any of them is saved as the operations it covers. In permissions.tools, a level you set on a single operation wins over the level its grouped name passes down.
  • Prompts and skills are written with per-operation names. A grouped agent reads them in grouped form: agnt_db_select in its system prompt or native skills reaches the model as agnt_db_read(action: "select"). A per-operation agent's model only sees per-operation names, so a change that newly writes a grouped name into its system prompt or native skills is refused with grouped_tool_names_on_per_operation_agent, naming the per-operation tool for each action. Nothing is saved.
  • TypeScript skill code always calls per-operation names, on both surfaces. The Agnt Wizard refuses skill code that calls a grouped name and points to the per-operation names to use.

03

Calling a grouped tool

Pass action plus that operation's own arguments:

grouped calljson
{
  "name": "agnt_db_read",
  "arguments": {
    "action": "select",
    "table": "leads",
    "filters": ["status.eq.new"],
    "limit": 20
  }
}

Each grouped tool's description starts with a summary, then lists its actions. Each action line names the per-operation tool it runs and the arguments it requires, so a name cited anywhere else still maps to a listed tool:

agnt_files_lookup descriptiontext
List workspace files, read a file's metadata, or read its contents.
Actions:
- list (agnt_files_list): List workspace files (chat uploads, skill outputs, API uploads) visible to this agent.
- get (agnt_files_get): Fetch metadata for a single workspace file by id. Needs: file_id.
- read (agnt_files_read): Read the contents of a workspace file. Needs: file_id.

The input schema lists action (required, with every action it routes) and the union of every action's arguments. When actions describe the same argument differently, its description gives each action's wording in brackets, such as [search] ... [enrich] .... On a grouped server, agnt_tools_search returns each tool with the grouped_name, action and, where it applies, object to call it with.

The server checks the chosen operation's required arguments after routing. A call that is missing one runs nothing and gets an error naming the missing arguments, with that operation's input schema. Arguments the chosen operation does not take are dropped, never forwarded, and data calls report them in ignored_args. A data action that pages through a separate next-page operation takes the page token itself: see Response views and paging.

When a call cannot be routed

A grouped call that cannot be routed runs nothing. Over MCP it is a tool error with isError: true: structuredContent.code is VALIDATION_ERROR, structuredContent.tool is the grouped tool, and structuredContent.error says why. An agent on superagnt_'s own runtime gets the same fields as JSON text, with the message in error and the fields in detail.

errorWhenAlso carries
INVALID_ARGUMENTSarguments is a string, array, number or boolean instead of an object.valid_actions
MISSING_ACTIONThe call has no usable action: absent, empty, or not a string.valid_actions, and action when one was sent
UNKNOWN_ACTIONaction names an operation this tool does not route for this server or agent.action, valid_actions
MISSING_OBJECTThe action works across record types and the call has no object.action, valid_objects
UNKNOWN_OBJECTobject names a record type the action does not take.action, object, valid_objects
MISSING_REQUIREDThe chosen operation's required arguments are not all present.action, member (the per-operation tool), missing, input_schema
MISSING_LOOKUP_FIELDA lookup call has no lookup_field.action, valid_fields
UNKNOWN_LOOKUP_FIELDlookup_field names a field the tool does not serve.action, valid_fields
UNKNOWN_OBJECTjson
{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "Unknown object \"invoices\" for connection_hubspot_records_read action \"search\". Valid objects: contacts, companies, deals, tickets, products, line_items.\n\nError details:\n{ ...the structuredContent below... }"
    }
  ],
  "structuredContent": {
    "code": "VALIDATION_ERROR",
    "error": "UNKNOWN_OBJECT",
    "tool": "connection_hubspot_records_read",
    "action": "search",
    "object": "invoices",
    "valid_objects": ["contacts", "companies", "deals", "tickets", "products", "line_items"],
    "message": "Unknown object \"invoices\" for connection_hubspot_records_read action \"search\". Valid objects: contacts, companies, deals, tickets, products, line_items."
  }
}

Re-call with one of the listed values. The other error shapes are on Reading errors.

04

Risk classes and annotations

Every grouped tool holds one risk class. A read, write or destructive tool routes only operations of that class:

  • read: looks and changes nothing.
  • write: creates or changes something.
  • destructive: removes or undoes something, such as a delete, an archive, a cancellation or a revoked share.
  • paid: on data tools, the people, company and SEO tools, billed per result or by what the request did. On connection tools, operations that move your money or spend your credits with the vendor.

A tool's MCP annotations follow its class, so a client that decides approval from them can trust them for every action the tool routes:

ClassAnnotations on the grouped tool
readreadOnlyHint: true, destructiveHint: false
write, platform toolsreadOnlyHint: false, destructiveHint: false
write, connection toolsreadOnlyHint: false, with no claim to be non-destructive, because a vendor update can overwrite or remove what it names
destructivereadOnlyHint: false, destructiveHint: true
paid, data toolsreadOnlyHint: true, openWorldHint: true
paid, connection toolsreadOnlyHint: false, openWorldHint: true

Destructive platform operations sit in tools of their own, such as agnt_webhooks_admin, agnt_dashboards_remove, agnt_bindings_remove and agnt_sync_delete, or stay single tools, such as agnt_db_delete.

05

What is grouped

Platform tools

AreaGrouped tools
Workspace databaseagnt_db_read, agnt_db_write, agnt_db_sql
Filesagnt_files_lookup
Agentsagnt_agents_read, agnt_agents_write, agnt_agents_run
Schedules, queues, data pipelinesagnt_schedules_write, agnt_queues_read, agnt_queues_write, agnt_data_job_lookup, agnt_data_job_write
Webhooksagnt_webhooks_read, agnt_webhooks_write, agnt_webhooks_admin
Vendor syncagnt_sync_read, agnt_sync_write, agnt_sync_delete
Dashboardsagnt_dashboards_read, agnt_dashboards_write, agnt_dashboards_remove
Memory, knowledge, guidanceagnt_memory_read, agnt_memory_write, agnt_knowledge_read, agnt_knowledge_write, agnt_guidance_read
Observability, usageagnt_observability_read, agnt_usage_read
Supportagnt_support_read, agnt_support_write
Inbox automationagnt_inbox_automation_read, agnt_inbox_automation_write, agnt_inbox_automation_delete
Connections and chat bindingsagnt_bindings_read, agnt_bindings_write, agnt_bindings_remove
Tool management, subscriptionagnt_tools_write, agnt_subscription_read

The inbox automation tools are named agnt_email_* per operation and agnt_inbox_automation_* grouped, because they manage triage rules, reminders and labels and never read or send mail.

Data tools

Data sources are grouped per resource, such as data_x_users, data_x_posts, data_linkedin_profiles, data_linkedin_companies, data_reddit_subreddits, data_youtube_videos and data_tiktok_read. The people, company and SEO tools (data_agnt_people, data_agnt_companies, data_agnt_contacts and every data_seo_* tool) are paid. A next-page operation is not an action of its own: the action it continues takes the page token. POST duplicates of GET operations are not listed on grouped servers. Grouped data tools answer in compact markdown unless asked otherwise, as Response views and paging explains.

Listed under their own names

Everything else is listed under its per-operation name on both surfaces:

  • Platform operations that stand alone, such as agnt_db_delete, agnt_files_upload, agnt_schedules_delete, agnt_tools_search, agnt_tools_list_enabled, agnt_subscription_change and escalate_to_human.
  • The three web data tools, data_web_scrape, data_web_search and data_web_map, and data_agnt_people_find_mobile.
  • Connector tools, such as the Slack and iMessage tools, and every tool a remote MCP server serves (mcp_*).
  • The few connection operations that stay ungrouped, listed in the next section.

06

Connection tools

A connected vendor's connection_* tools are grouped the same way: one tool per resource (the thing an agent works on, such as contacts or pull requests) and risk class, each with an action. Every vendor follows the rules below, and the structural ones (one risk class per tool, every operation placed, typed arguments, descriptions that fit) are checked automatically on every change to the platform. HubSpot's 133 operations list as 30 tools, GitHub's 76 as 29, and HeyReach's 84 as 41 grouped tools plus connection_heyreach_auth_check_api_key. Each vendor's page lists its grouped tools with their risk class and actions, and every operation with its per-operation name, for example HubSpot, GitHub and HeyReach.

One resource and one risk class per tool

A tool holds one resource and one risk class: read, write, destructive or paid. Reading, changing and archiving HubSpot records are three tools, connection_hubspot_records_read, connection_hubspot_records_write and connection_hubspot_records_delete, never one. An operation's class comes from what it does, not its HTTP method: HubSpot's searches are POST requests and sit in the read tool, and a POST that removes something is destructive. Resources an agent works on separately get tools of their own, such as HubSpot's activities beside its records, HubSpot's batch operations (connection_hubspot_records_batch_write) beside the single-record ones, or HeyReach's campaign senders beside its campaigns. Operations that share almost none of their inputs sit in separate tools too.

Sending is its own tool

Sending something that reaches people, such as an email, an inbox reply, a direct message or a LinkedIn message, is a _send tool of its own, apart from the same resource's labels and drafts. connection_gmail_mail_send sends, replies to all and forwards, while connection_gmail_mail_write labels messages and saves drafts. Others include connection_instantly_emails_send, connection_heyreach_inbox_send and connection_x_official_dms_send.

An operation whose job is to move money or spend vendor credits is paid, and a paid tool holds nothing else. That covers Stripe payment intents, refunds and subscription changes (connection_stripe_refunds_write), Dub commission adjustments and bounty approvals, enrichments and email finding (connection_apollo_io_people_enrich, connection_heyreach_emails_find), every Exa call (connection_exa_web_search, connection_exa_contents, connection_exa_answers), AI Ark's searches and exports (connection_ai_ark_people, connection_ai_ark_people_export) and Memelord's memes. Switching on future spend counts too: Instantly's enrichment settings sit in the paid connection_instantly_enrichments_write. The one exception is the update of a charge that is still pending, a Stripe payment intent's, which stays with its create. An operation that spends only through an option or the vendor's own rules, such as a lead import that can verify emails, keeps its read or write class, and its description says it can spend.

The object dimension

Where several record types take the same input, one action covers them all and an object argument picks the record type. HubSpot's records and activities, and QuickBooks' reads and deletes, work this way:

object calljson
{
  "name": "connection_hubspot_records_read",
  "arguments": { "action": "search", "object": "deals", "query": "acme", "limit": 10 }
}

The description names such an action once, with the record types it takes and the per-operation tool for each: - search (object: contacts, companies, deals, tickets, products, line_items): ... Ops: contacts → connection_hubspot_search_contacts; .... A missing object is MISSING_OBJECT and one the action does not take is UNKNOWN_OBJECT. Both list valid_objects, and nothing runs.

Record types whose inputs differ never share an action. Each QuickBooks record type is saved with its own body, so connection_quickbooks_save_invoice and its siblings are listed under their own names. Some vendors' operations take an argument named object of their own, such as Attio's records, which take the Attio object's slug or id. There object is that operation's own argument, passed through unchanged.

Typed inputs and whole descriptions

When actions take the same field in different shapes, like a create body and its partial update, the tool lists one typed shape that accepts both, and the field's description names what only some actions require. connection_attio_objects_write describes its data argument with [create] needs api_slug, singular_noun, plural_noun. Operations whose inputs no single typed shape can hold belong to different tools, so a connection tool never lists an argument untyped when its operations give it a type.

A connection tool's description is never shortened. Every action line and every argument description is shown whole, as written for the operation, and a resource whose description would pass 2,048 characters, the length some MCP clients cut tool descriptions at, is split into more tools instead. Platform and data tools shorten their action sentences when they must, but never drop an action, its per-operation name or its required arguments.

The lookup action

Some filters take one of more than a hundred values, like AI Ark's industries and departments, Instantly's SuperSearch sub-industries, or the activity types lemlist's activity log filters on. When a field's allowed values run past 2,048 characters and no operation of the tool requires that field, the tool lists it as plain text, says how many values it takes, and adds a lookup action. lookup answers from the integration's own definition: it makes no call to the vendor, needs no approval and costs nothing.

lookup calljson
{
  "name": "connection_ai_ark_people",
  "arguments": {
    "action": "lookup",
    "lookup_field": "account.industries.any.include.content[]",
    "lookup_query": "software"
  }
}
lookup resultjson
{ "field": "account.industries.any.include.content[]", "total": 1, "values": ["software development"] }

lookup_field takes a field named in the description's lookup line. lookup_query keeps the values that contain the text, ignoring case, and lookup_limit caps how many come back (default 100, at most 500). A result cut by the limit carries truncated: true and a note to narrow it with lookup_query.

Hidden and listed on their own

Every operation of a connected vendor is exactly one of three things: an action of a grouped tool, hidden, or listed under its own name.

Hidden operations are not listed on grouped servers and stay callable by name. They are older versions that a newer operation replaces, such as HeyReach's first add-leads operations (connection_heyreach_campaign_add_leads), hidden only while the grouped tool routes the newer one, and operations that are no work for an agent, such as Attio's SCIM provisioning endpoints.

These are listed under their own names on every surface:

  • A vendor's only operation, where a group would only add a step: connection_rb2b_list_profiles, connection_linear_lineargraphql.
  • The Postgres and Supabase database tools, a write and a read that cannot share a tool: connection_postgres_query, connection_postgres_schema, connection_supabase_query, connection_supabase_schema.
  • QuickBooks' per-record-type saves, such as connection_quickbooks_save_customer and connection_quickbooks_save_invoice.
  • Operations that take an argument named action themselves, which a grouped tool reserves: connection_calendly_list_activity_log_entries, connection_lemlist_remove_campaign_lead, connection_lemlist_update_contact_list_members, connection_smartlead_push_leads_to_campaign.
  • connection_heyreach_auth_check_api_key, which a skill calls by name.

Per-operation names stay the key

Every per-operation connection name still works, as a callable tool on both surfaces and as the key for permissions, approvals and usage. A call to connection_hubspot_records_write with action: "create" and object: "contacts" is gated, approved and recorded as connection_hubspot_create_contact. Which operations run on their own and which wait for a person is on Permissions and approvals.