extract_listing_improvements
Derive specific, copyable listing improvements from the VOC report grounded in actual customer language.
Instructions
Differentiator tool — derive specific, copyable listing improvements from the VOC report, grounded in actual customer language.
Instead of raw search-volume tables (Data Dive style), Claude reads the full VOC report and produces a title, 5 bullets, a description paragraph, and missing keywords — each suggestion citing the pain point it preempts or selling point it amplifies.
Requires ANTHROPIC_API_KEY. Costs ~$0.05-0.20 per call (claude-opus-4-7).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| asin | Yes | ||
| market | No | US | |
| limit | No |
Implementation Reference
- mcp_server/tools.py:248-315 (handler)Core handler function for extract_listing_improvements. Calls voc_full() to get the VOC report, then invokes Claude (claude-opus-4-7) with structured-output parsing to produce a ListingImprovements model containing title, 5 bullets, description, keywords, and warnings. Returns JSON with improvements, sentiment, pain/selling points.
def extract_listing_improvements( asin: str, market: str = "US", limit: int = 100, *, _client: Any = None, # injected by tests ) -> dict[str, Any]: """Run the full VOC pipeline, then call Claude to extract structured listing copy suggestions. The differentiator vs. Data Dive's MCP: their MCP exposes keyword research; ours adds *actionable copy suggestions* directly grounded in the customer signal from real reviews. """ # 1. Get the analysis (re-uses voc_full, including its ASIN validation). report = voc_full(asin, market=market, limit=limit) # 2. Run Claude with structured-output coercion to a ListingImprovements # pydantic model. Uses prompt caching on the system rubric so # repeated extract_listing_improvements calls in the same session # share the cache. if _client is None: # Imported lazily so tests can run without the package installed. import anthropic _client = anthropic.Anthropic() user_content = ( f"ASIN: {report['asin']} ({report['market']} marketplace)\n\n" f"Here is the VOC analysis report for this listing:\n\n" f"---\n{report['report_markdown']}\n---\n\n" f"Produce the structured listing improvements per your rubric. " f"Cite the specific pain points and selling points from the report." ) result = _client.messages.parse( model="claude-opus-4-7", max_tokens=16000, thinking={"type": "adaptive"}, output_config={"effort": "high"}, system=[ { "type": "text", "text": _LISTING_SYSTEM_PROMPT, "cache_control": {"type": "ephemeral"}, } ], messages=[{"role": "user", "content": user_content}], output_format=ListingImprovements, ) improvements = result.parsed_output if improvements is None: raise RuntimeError( "Claude returned a refusal or unparseable structured output. " f"stop_reason={result.stop_reason}" ) return { "asin": report["asin"], "market": report["market"], "improvements": improvements.model_dump(), "source_report": { "sentiment": report["sentiment"], "pain_points": report["pain_points"], "selling_points": report["selling_points"], "summary_en": report["summary_en"], }, } - mcp_server/schemas.py:65-90 (schema)ListingImprovements Pydantic model defining the structured output schema: title_suggestion, title_reasoning, bullet_suggestions (list of BulletSuggestion), description_paragraph, keyword_opportunities, and warnings. Used as the output_format for Claude's structured-output parsing.
class ListingImprovements(BaseModel): """Structured listing copy suggestions derived from the VOC report. Every suggestion must cite the review evidence it addresses (the `addresses` field) so the seller can verify it's grounded in actual customer language, not hallucinated. """ title_suggestion: str = Field( description="A proposed new product title (max 200 chars per Amazon's limit), incorporating top selling points and key search terms surfaced in the reviews." ) title_reasoning: str = Field( description="One sentence on why this title — which pain points it preempts, which selling points it amplifies." ) bullet_suggestions: list[BulletSuggestion] = Field( description="5 proposed bullet points. Each bullet should preempt a top pain point or amplify a top selling point. Order by importance." ) description_paragraph: str = Field( description="A short product description paragraph (150-250 words) that incorporates the top 3 selling points and addresses the top 2 pain points head-on." ) keyword_opportunities: list[str] = Field( description="3-5 search keywords that buyers used in their reviews but are likely missing from the current listing. Pull from review language, not assumptions." ) warnings: list[str] = Field( default_factory=list, description="Any review signals the seller should NOT try to fix via listing copy (e.g., 'product quality complaints can't be solved by better copy — needs a product fix')." ) - mcp_server/server.py:90-102 (registration)MCP tool registration via @mcp.tool() decorator. The server entry point defines the tool signature (asin, market, limit) and delegates to tools.extract_listing_improvements.
@mcp.tool() def extract_listing_improvements(asin: str, market: str = "US", limit: int = 100) -> dict: """Differentiator tool — derive specific, copyable listing improvements from the VOC report, grounded in actual customer language. Instead of raw search-volume tables (Data Dive style), Claude reads the full VOC report and produces a title, 5 bullets, a description paragraph, and missing keywords — each suggestion citing the pain point it preempts or selling point it amplifies. Requires ANTHROPIC_API_KEY. Costs ~$0.05-0.20 per call (claude-opus-4-7). """ return tools.extract_listing_improvements(asin=asin, market=market, limit=limit) - mcp_server/schemas.py:56-62 (schema)BulletSuggestion Pydantic model used by ListingImprovements; each bullet has 'text' and 'addresses' fields to cite the pain/selling point it addresses.
class BulletSuggestion(BaseModel): """A single bullet point suggestion, with the source pain/selling point it addresses so the seller can verify the suggestion is review-grounded.""" text: str addresses: str = Field( description="The pain point or selling point this bullet addresses (verbatim from the report)" ) - mcp_server/dashboard.py:40-48 (helper)Dashboard renders a placeholder card if improvements are not provided, suggesting the user call extract_listing_improvements to populate listing optimizations.
return ( '<div class="listing-card">' '<h3>Listing Optimization</h3>' '<p style="color:var(--text-muted);">Call ' '<code>extract_listing_improvements</code> to populate this section ' 'with copy-ready title / bullets / description rewrites grounded ' 'in actual customer language.</p>' '</div>' )