Skip to content

Pin + research: is our MCP tool shape (one tool per resource, action enum) still best practice? #359

Description

@leggetter

Why

We are about to ship v3.0.0 (#348), which is the first release in a while that can change MCP tool names without a compatibility cost — the hookdeck_gateway_ rename is already in it, and clients must re-grant tool permissions either way.

That makes it the right and possibly only cheap moment to ask whether the shape of our tools is right, not just their names. This issue pins exactly what we have today so any redesign is measured against a fixed reference rather than a memory of one.

This issue is a pin and a research tracker. It proposes no change yet.

Tagged in git as v3.0.0-pin-pre-tool-shape-review (a965637).

The design under review

We use one tool per resource, with an action enum parameter, rather than one tool per operation. gateway_connections with action: "list" | "get" | "pause" | … instead of gateway_list_connections, gateway_get_connection, gateway_pause_connection.

The original reasoning was context economy: fewer tool definitions in the model's context. Every tool a server registers costs tokens in every request for the whole session, whether used or not.

The question is whether that trade still holds, and whether we have taken it too far.

Where we are — Event Gateway

Tool Actions
gateway_connections list, get, pause, unpause, create, upsert, update, delete, enable, disable
gateway_sources list, get, create, upsert, update, delete, enable, disable
gateway_destinations list, get, create, upsert, update, delete, enable, disable
gateway_transformations list, get, create, upsert, update, delete, run
gateway_events list, get, raw_body, retry, cancel, mute
gateway_requests list, get, raw_body, events, ignored_events, retry
gateway_issues list, get, update, dismiss
gateway_attempts list, get
gateway_metrics events, requests, attempts, transformations

Plus platform tools hookdeck_login, hookdeck_projects, and gateway_help.

9 product tools, 55 actions.

Where we are — Outpost

Tool Actions
outpost_tenants list, get, upsert, delete, token, portal
outpost_destinations list, get, create, update, delete, enable, disable
outpost_events list, get, retry
outpost_attempts list, get
outpost_config get, set, custom_domain_get, custom_domain_set, custom_domain_delete
outpost_metrics events, attempts
outpost_publish publish
outpost_topics, outpost_destination_types, outpost_status list / get

The cost this shape carries

Collapsing operations into one tool means the schema is the union of every action's parameters, and the model has to infer which apply to the action it picked. Parameter count per Gateway tool:

Tool Params
gateway_events 25
gateway_requests 19
gateway_connections 10
gateway_issues 10
gateway_metrics 10
gateway_transformations 9
gateway_sources 8
gateway_destinations 8
gateway_attempts 7

gateway_events carries 25 parameters across 6 actions. Only a handful are meaningful for any one action — raw_body needs an id and nothing else, while list uses most of the filters. Nothing in the schema expresses that, so correctness rests on the description text and the model's inference.

There is also a second-order effect: some parameters are renamed between the MCP surface and the API (connection_idwebhook_id, filter_statusstatus), which exists partly to keep one flat namespace workable across several actions.

What the research needs to answer

  1. Consensus position. What do Anthropic, OpenAI and the MCP spec authors actually recommend on tool granularity? Is one-tool-per-operation the default advice, and how strong is it?
  2. Is context economy still the binding constraint? It motivated this design. With larger context windows, prompt caching, and client-side tool filtering, does it still dominate — or has the cost moved to model accuracy in action selection and parameter validity?
  3. Evidence, not opinion. Are there benchmarks or evals measuring tool-count and schema-complexity effects on tool-selection accuracy? (Berkeley Function Calling Leaderboard, τ-bench, MCP-specific evals, published internal evals.)
  4. What comparable servers do. GitHub, Stripe, Linear, Sentry, Supabase, Cloudflare, Notion — one tool per operation or consolidated? Do they use toolsets / dynamic discovery / filtering instead of consolidation to manage context?
  5. The fat-schema question specifically. Is a 25-parameter union schema a known anti-pattern, and what is recommended instead — narrower tools, per-action schemas, nested objects, oneOf/anyOf variants?
  6. Migration cost if we change. We would be renaming and re-shaping tools inside the same major that already renames them. Doing both at once is cheaper than doing them in separate majors.

Constraint on any outcome

Whatever we conclude, hookdeck_login and hookdeck_projects stay platform-prefixed and shared across product servers. That is settled and not part of this review.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions