Agent tools: four tools instead of fifty-five

Decided 8 November 2026 (John, in session). This document records why the MCP surface changed and how the four tools work. The REST API, CLI and generated clients are unchanged by this decision; it concerns what an agent sees over MCP.

Why

On 8 November 2026 the hosted MCP (https://api.threefold.eco/mcp) was exercised as a coding agent would use it: about 70 calls across every tool. Findings:

ProblemMeasured
Too many tools55 tools (52 keyless). Their definitions cost about 24,000 tokens of the agent's context before any call; the 10-market and 56-genre enums were repeated in most of them. Mobbin's MCP, the reference for this product shape, has 8, of which 3 search.
The model barely saw resultsThe text block of every result was a one-line summary ("50 items returned."); the data was only in structuredContent, which not every host passes to the model.
Results too large where they did arrivechart_history 1.19 MB, get_app 179 KB, compare_markets 166 KB, paid_ads 70 KB with 180 ads in the whole library.
Broken tools4 failed output validation on every realistic call (fixed in #60); 6 analysis tools failed without ANTHROPIC_API_KEY and blamed the caller; 4 label tools returned 404 while labels are off; 7 operator tools were listed to customers.
No guidanceNo server instructions.

The tools mirrored the REST API one to one. An agent had to choose among 55 and stitch six calls together to answer one question, which costs more context than one good answer, not less.

Principles

  1. Tools follow the person's questions, not the API. Someone taking an app into another market asks three things: how does this app show up there, what does this market reward, and is my thing ready for it. A team adds a fourth: keep track of what we follow.
  2. One call answers the question across Brand, Paid and Organic. Splitting pillars into separate tools repeats the 55-tool mistake. The value is the joined-up answer.
  3. Size is controlled per answer, not by tool count. Every result leads with a digest under a hard budget, then offers filters and a cursor to drill down, and a link to see everything in the web app. Raw rows are never dumped into the agent's context, however much data sits behind the answer. This matters most for Paid, which will carry every platform, format, sponsorship and UGC.
  4. We supply evidence and criteria; the user's agent judges. Threefold labels the market once, at collection time (shared, cheap per item), and runs rule checks (limits, language, counts). Judgement on the user's own material (screenshots, ad drafts, copy, repository) is done by the user's agent against our criteria and reference examples. Their unreleased material never has to leave their machine, nothing needs uploading to the hosted server, no model runs per request on our side, and the answer stays fast. Server-side grading, for consistent scores and audit trails, is an optional enterprise extra, not the default.
  5. Every answer serves the person behind the agent too. Results carry threefold.eco links to the same view in the web app, so the agent does the research and the person can check the evidence visually.
  6. Nothing that cannot work is listed. Tools whose dependencies are not configured are not offered; operator tools live in the CLI.

The four tools

ToolQuestionReplaces
appHow does this app show up across stores, pillars and markets?get_app, search_apps, search_app_store, screenshot_gallery, listing_history, chart_history, export_history, app_reviews, review_summary, compare_paid, explain_listing_differences, paid_ads/organic_posts by app
marketWhat wins in this market and genre, optionally next to an app like mine or my home market?top_apps, compare_markets, paid_ads, paid_summary, organic_posts, price_points, market_glossary, market_launch_checklist, b2b_market_checklist, market_take, label_profile, label_compare, language_fit
checkGrade my listing, screenshots, ad, name, website, repository or live app for this market.market_brief, market_entry_report, market_entry_narrative, listing_check, variant_lint, i18n_check, i18n_check_rules, i18n_report, brand_name_check, translate, visual_brief
workspaceWhat do we track, who are our competitors, what changed, what have we saved?track_app, backfill_app, create/list/delete_watch, watch_events, save_item, list_collections, get_collection, add_note, account_usage

Removed from MCP: operator and ingest tools (run_ingest, plan_ingest, ingest_cost, ingest_status, media_archive_status, plan_media_archive: use the CLI), discover_endpoints and describe_endpoint (the docs, OpenAPI and llms.txt cover them), and request_coverage (a result that meets a coverage gap says so and how to ask). Server-side narrative tools (explain_*, *_narrative, translate, visual_brief, brand_name_check) follow principle 4: the agent writes the narrative from the evidence. Their REST routes remain.

Result shape (all four)

  • Text block (what the model reads): a markdown digest, at most about 4,000 tokens. Key facts with numbers, the top few examples, a citation link for every claim (store URL, ad library URL, post URL), the threefold.eco link for the person, and how to go deeper (which focus, filter or cursor to pass next). Coverage gaps are stated in the digest, not hidden.
  • Images: at most 6 low-resolution previews per result, in the order the digest refers to them.
  • structuredContent: the same answer as typed data, for hosts and programs that read it.
  • _meta: cost, balance and data freshness, as before.

app

Inputs: app (name or id; an ambiguous name returns the candidates), markets (optional; default the app's charting markets, capped), store (ios, play; default both when linked), focus (overview default, brand, paid, organic, reviews, changes), platform, format, since, cursor.

Overview: per market, the localised title and subtitle, copy language, rating, chart positions and first screenshot; Paid and Organic totals by platform with the longest-running examples; how the app differs between markets. Each focus expands one part with paging.

market

Inputs: market, genre (plain words, fuzzy matched; a miss returns suggestions), like (optional reference app), vs (optional home market), store, focus (overview default, brand, paid, organic, pricing, language, launch), platform, format, cursor.

Overview: the top apps and how localised they are, which ads run longest, top posts, price points and local vocabulary. With vs, what differs from the home market and who crossed over. With like, where an app like that fits and what it would need to change. Label findings (formats, styles, offers) appear here once labels are live; until then the digest says they are not available.

check

Inputs: market, what (listing, screenshots, ad, name, website, repo, app), url (for what: website), plus the material: listing fields (title, subtitle, keywords, description, promotional text), app (id, for a live app), name, genre, from (home market).

Returns: the rule checks threefold ran (field limits, language and variant problems, keyword overlap with the market's vocabulary, screenshot counts), the criteria for this market with the numbers behind them, reference examples from the top apps (images and links), and a closing instruction telling the agent what to grade itself. what: app is the market-entry brief for a live app. what: repo returns the market's readiness rules for the agent to apply to the repository it already has open; the local stdio server also runs the scanner over the path given.

what: website (added 8 Nov 2026) fetches the given page and the market's language version it links (hreflang; redirects followed, every hop checked as a public address) and checks: hreflang annotations, a version for the market's language or variant, <html lang>, the text's language, Spanish variant terms, and the legal pages the market's law requires (Impressum and privacy notice in Germany, mentions légales in France, aviso legal in Spain, the 特定商取引法 notice in Japan), each with its source. It reports currencies and payment methods named on the page without grading them. A page that builds its content in the browser is reported as not checkable rather than failing. Competitors' websites come later (docs/plan-data-everywhere.md, workstream C).

workspace

Actions: get (default: the workspace's apps, competitors per market, target markets, watches, latest digest, saved items, usage), set_apps, set_competitors, set_markets, watch, unwatch, changes (what changed since the last digest), save (a brief or check result, shared with the team), saved.

For an individual this is "this is my app". For a team it is shared memory: the competitor sets, digests and saved briefs everyone opens. Once set, the workspace becomes the default context: market answers "you against your competitors", check knows which app is yours.

Enterprise, outside the tools

The four tools serve individuals and teams alike; the enterprise layer is the account and admin side, most of it built: SSO, audit log, scoped keys, admin-provisioned connectors for Claude, ChatGPT and Grok (docs/launch/enterprise-connectors.md), the EU region guard, data export. Still to add: digests by email, Slack or webhook; a feed into the customer's BI; optional server-side grading with consistent scores.

Context budget

BeforeAfter
Tool definitions~24,000 tokens (55 tools)target under 4,000 tokens (4 tools)
Typical result in the model's viewone line (data out of view) or 50 KB to 1.2 MBdigest of at most ~4,000 tokens plus up to 6 previews
Calls to answer "how does Duolingo advertise in Germany"about 61

Measured after the build (8 November 2026, local server on a copy of production)

Value
Tool definitions (tools/list)8,985 bytes, about 2,250 tokens (was 95,296 bytes)
Server instructions1,266 characters
app Duolingo, 3 markets5,493-character digest, 3 previews
market Mexico, language learning, like Duolingo, vs US5,486 characters, 2 previews
check listing for Mexico3,404 characters; flags Spain-only terms (móvil, vosotros) with sources
check repo (hosted)4,687 characters: the market's readiness rules for the agent to apply
workspace get1,020 characters

Every read path of the four tools is covered by test/mcp-output-schemas-postgres.test.mjs: no error, digest within budget, at most six previews, no undefined/NaN in the text, output schema respected. Coverage statements ("no ads collected for Mexico", "reviews collected for the United Kingdom only") come from lib/agent/coverage.mjs, which reads what the library holds, so a missing source is never reported as zero.