Skip to content

feat(mcp): rewrite 51 remaining Meta Ads tool descriptions to lift TDQS#44

Merged
hyoshi merged 1 commit intomainfrom
feat/tdqs-improve-remaining-tool-descriptions
Apr 24, 2026
Merged

feat(mcp): rewrite 51 remaining Meta Ads tool descriptions to lift TDQS#44
hyoshi merged 1 commit intomainfrom
feat/tdqs-improve-remaining-tool-descriptions

Conversation

@hyoshi
Copy link
Copy Markdown
Collaborator

@hyoshi hyoshi commented Apr 24, 2026

Summary

Rewrite MCP tool descriptions for the remaining ~51 Meta Ads tools that PR #43 did not cover, applying the same TDQS template from docs/tdqs-style-guide.md.

Why

TDQS on the current state (post-PR #43):

  • Average 3.5/5 (C grade) - up from 3.1 but still C
  • Lowest tool: meta_ads.creatives.list at 2.1/5 - a C-grade laggard
  • Distribution: A=25, B=51, C=86 (53% C)

Most of the lowest-scoring tools live in the Meta Ads ecosystem. This PR rewrites every remaining Meta Ads tool so the TDQS re-score focuses on the most severe laggards first.

Scope

File Tools
_tools_meta_ads_creatives.py 9 (creatives / images / videos) - includes the 2.1 laggard
_tools_meta_ads_audiences.py 9 (audiences / pixels)
_tools_meta_ads_insights.py 8 (insights / analysis)
_tools_meta_ads_catalog.py 10 (catalogs / products / feeds)
_tools_meta_ads_conversions.py 3 (CAPI)
_tools_meta_ads_leads.py 5 (lead forms / leads)
_tools_meta_ads_other.py 14 (split tests / ad rules / page posts / Instagram)
Total 58 tools

Approach

Every rewritten tool covers the six TDQS dimensions:

  • Specific verb + resource (Purpose Clarity)
  • When to use vs sibling tools (Usage Guidelines) - e.g. creatives.create vs create_dynamic vs create_carousel
  • Read-only / mutating / destructive flags (Behavioral Transparency)
  • Parameter format hints (account_id = act_XXXX; image_hash vs image_url mutual exclusion; limit defaults; ISO 4217 currency codes for CAPI)
  • 50-100 word length (Conciseness)
  • Returned fields + sibling-tool pointers (Contextual Completeness)

Test plan

  • Python syntax validation (ast.parse) on all 7 rewritten files
  • black --check applied
  • docker build succeeds
  • docker run + MCP initialize + tools/list - all 173 tools still load
  • Merge then Glama rebuild; confirm TDQS average climbs above 3.5 and meta_ads.creatives.* family avg lifts from 2.88 toward B band
  • Follow-up PR for the remaining ~73 tools (google_ads.analysis, extensions, assets, search_console)

Non-goals

  • No runtime behavior changes
  • TOOLS: list[Tool] public interface unchanged
  • Schema hints added (enum, minimum, minItems, maxItems) - all backwards-compatible

… PR 2)

Applies the TDQS template from docs/tdqs-style-guide.md to every Meta
Ads tool not covered by PR #43. Files touched:

- _tools_meta_ads_creatives.py (9 tools: creatives, images, videos)
- _tools_meta_ads_audiences.py (9 tools: audiences, pixels)
- _tools_meta_ads_insights.py  (8 tools: insights, analysis)
- _tools_meta_ads_catalog.py   (10 tools: catalogs, products, feeds)
- _tools_meta_ads_conversions.py (3 tools: Conversions API)
- _tools_meta_ads_leads.py     (5 tools: lead forms, leads)
- _tools_meta_ads_other.py     (14 tools: split tests, ad rules, page posts, Instagram)

Notably rewrites meta_ads.creatives.list - the TDQS lowest-scoring
tool in mureo at 2.1/5 - to a full description covering returned
fields, read-only semantics, pagination defaults, and sibling-tool
differentiation.

All 173 tools still load; docker build + MCP initialize + tools/list
verified end-to-end. No behavioral changes - descriptions and
parameter schema hints only.
@hyoshi hyoshi merged commit 2988b04 into main Apr 24, 2026
7 checks passed
@hyoshi hyoshi deleted the feat/tdqs-improve-remaining-tool-descriptions branch April 24, 2026 01:38
hyoshi added a commit that referenced this pull request Apr 24, 2026
* feat(mcp): rewrite lowest-5 TDQS tool descriptions (PR 3 pilot)

Targets the five tools currently bottlenecking the Glama server-level
Tool Definition Quality Score (TDQS = 0.6*mean + 0.4*min = 3.36, B):

  - google_ads.landing_page.analyze     (was 2.4/5, the min)
  - google_ads.performance.report       (was 2.5/5)
  - google_ads.schedule_targeting.list  (was 2.5/5)
  - search_console.sitemaps.submit      (was 2.5/5)
  - google_ads.search_terms.report      (was 2.6/5)

Rewrites follow docs/tdqs-style-guide.md: specific verb, returned
fields, side effects, sibling differentiation, parameter format hints.
Adds _CUSTOMER_ID_PARAM and _PERIOD_PARAM reusable fragments to
_tools_google_ads_analysis.py (same pattern already adopted by
_tools_google_ads_campaigns.py and _tools_meta_ads_campaigns.py in
PRs #43 and #44).

No tool name, required-field, or handler dispatch changes -- this is
purely description and schema metadata. Tool count remains 173.

Goal: lift server TDQS to A tier (>= 3.5) by raising the minimum.
If effective, the remaining ~46 C/B- tools get the same treatment
in a follow-up PR to carry quality_grade from B to A (AAB to AAA
composite grade).

* fix(mcp): correct factual claims in TDQS pilot descriptions

Code review flagged CRITICAL/HIGH/MEDIUM factual errors in the return-
shape and side-effect claims added by the previous commit. A TDQS
rewrite whose goal is "help agents call the tool correctly on first
try" cannot ship with descriptions that contradict the mapper. All
changes are description-only; schemas, tool names, required fields,
and handlers remain unchanged.

CRITICAL

- google_ads.performance.report: return shape is
  {campaign_id, campaign_name, metrics:{...}} per mappers.map_performance_report
  and client.get_performance_report GAQL. Previous description claimed
  flat fields and added status / conversion_value / conversion_rate
  that are neither SELECTed nor mapped. Rewritten to match the actual
  nested metrics object (impressions, clicks, cost_micros, cost,
  conversions, ctr, average_cpc_micros, average_cpc,
  cost_per_conversion_micros, cost_per_conversion).

- google_ads.search_terms.report: return shape is
  {search_term, metrics:{impressions, clicks, cost_micros, cost,
  conversions, ctr}} per mappers.map_search_term. Previous description
  invented keyword, match_type, ad_group, and conversion_value fields.
  Rewritten to match; clarifies that campaign_id / ad_group_id filters
  do not echo back in the output rows.

- search_console.sitemaps.submit: actual return is
  {"status": "submitted", "sitemap": feedpath} per
  SearchConsoleApiClient.submit_sitemap, not an empty object.
  Description corrected.

HIGH

- google_ads.schedule_targeting.list: end_hour range is 0-24 (not
  1-24; 24 denotes end-of-day per Google Ads). start_minute /
  end_minute are string forms of the MinuteOfHour enum
  ('ZERO' / 'FIFTEEN' / 'THIRTY' / 'FORTY_FIVE') per
  _extensions_targeting.list_schedule_targeting, not integers.
  bid_modifier is float-or-null. All now disclosed.

MEDIUM

- search_console.sitemaps.submit: softened the "idempotent" overclaim
  to "safe to call repeatedly; re-submitting re-queues a crawl without
  creating a duplicate entry".

- google_ads.landing_page.analyze: added truncation caps per
  lp_analyzer.py (features <= 30, structured_data <= 5 JSON-LD
  blocks, max_redirects = 5, User-Agent 'MarketingAgent/1.0') and
  expanded the SSRF disclosure to cover link-local / reserved ranges
  and the post-redirect re-validation.

Verified: ast.parse OK, ruff clean, black unchanged, pytest 1774
passed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant