MCP catalog tool design: from dozens of endpoints to a large operation set

MCP catalog tool design: from dozens of endpoints to a large operation set
Unif Engineering team
Unif Engineering team

Updated

How UnifAPI grew from dozens of endpoints to a large public-data operation set behind three MCP catalog tools — and why Skills hide the complexity.

In short: This engineering note explains why UnifAPI exposes a large operation catalog through three MCP tools and why Skills are the user-facing layer above that catalog.

UnifAPI's first MCP catalog exposed 73 endpoints. The current catalog exposes a large operation set across live public-data APIs through three MCP tools: list_operations, get_operation, and call_api. Doing that well is harder than it looks: the model still needs to discover the right operation, inspect the schema, and make a clean call. This is what we learned about naming, descriptions, parameter schemas, and the failure modes that don't show up until you have dozens of operations live.

Why a large operation set changes the product

At 5-10 operations, MCP "just works" — the model searches the catalog, picks one, and calls it. At 20-30, operation naming starts to matter; you see the model occasionally pick the close-but-wrong path. At 50+, the catalog itself becomes load-bearing.

The count will keep growing, but the product lesson is already clear: as operation count rises, Skills become more important because they hide catalog navigation behind a task result.

Operation naming: agent-readable, not human-readable

Our operation labels follow one pattern: platform, verb, noun. TikTok search videos, Reddit get post, LinkedIn search people. Verbose, but unambiguous. The model picks the right operation because the name reads like a sentence fragment, not a code identifier.

We tried shorter conventions early — tiktok.search, reddit.post — and saw the model pick wrong on close pairs ("search" on TikTok vs. "search" on Reddit when the user said "search"). The platform prefix in the operation title disambiguates without the model having to reason about it.

Descriptions are the prompt

Each operation description is one or two sentences. The model sees them during discovery and inspection. Two patterns that earn their tokens: lead with the verb-object summary in the first 12 words, and end with a use-when hint.

Good: "Search TikTok for videos matching a keyword or hashtag. Use when the user wants short-video discovery on a topic." Bad: "This endpoint allows you to query the TikTok platform and retrieve a paginated list of videos that match a search term, optionally filtered by various parameters including ..." The second one is technically more complete and is the wrong tradeoff in a large catalog.

Parameter schemas: keep them flat

call_api takes a flat object: path, method, query, and body. Required fields first, optionals after. The reason is simple: nested JSON schemas confuse the model's tool-call generator. We've watched Claude correctly understand a parameter and then output it at the wrong nesting level because the schema looked branchy.

When an operation genuinely needs polymorphic input (search by keyword OR by hashtag), get_operation needs to show a concrete call example. A concrete example beats a branchy schema every time.

What we got wrong

Three mistakes worth naming. First, we let Twitter and Reddit have nearly-identical descriptions for their respective search operations, and the model started picking one when the user explicitly asked for the other. Fixed by making each description name its platform explicitly in the first sentence.

Second, we returned source error messages straight through for a while. Some of those reference platform-specific concepts the model doesn't understand, and the agent would loop trying to fix an issue our envelope was hiding. Fixed by normalizing errors into a closed vocabulary such as unauthorized, validation_error, invalid_id, not_found, rate_limited, and upstream_unavailable.

Third, we under-documented pagination on a few operations, and the model would re-call from cursor 0 every loop instead of advancing. Fixed by spelling out the pagination contract in the inspected operation data itself, not just in the spec.

Open questions

At what point do we partition the catalog? A large operation set fits behind one MCP server today, but the catalog may eventually need category filters or category-specific servers so the model only loads what it needs.

We don't know the right answer yet. If you're shipping agents that consume a lot of UnifAPI operations today, we want to hear how the operation-pick latency looks on your end — drop us a note at hello@unifapi.com.

Unified response envelope - pairs tool discovery with the response contract.

Connect UnifAPI MCP - shows the operator-facing setup path.

Developer resources - collects the machine-readable specs and docs.