跳到正文
DEV Community· Wrenfield Data·· 4 小時前AI 評分60

Wrenfield Data 示範如何以 MCP 和函數呼叫為 AI 智能體接入搜尋量及 AI 回答工具

Give your AI agent search-demand and AI-answer tools: MCP and function calling, with real output

AI 導讀

Wrenfield Data 示範如何把搜尋量及 AI 回答工具接入 AI 智能體,提供免寫程式的 MCP 方案,以及約 60 行 Python 的函數呼叫實作;MCP 配置網址為 https://mcp.apify.com?

正文

Disclosure: I build the tools used here (Keyword Search Volume, AI Answer Scraper and AI Search Visibility Tracker on Apify). The sample output below comes from real runs I made on October 19 and 22, 2026; each tool function was run against those saved rows (no new calls), so you see exactly what your agent would read.

An agent with a browser tool can read any page. There are two questions it still cannot answer on its own:

  1. How many people actually search for this? (demand, CPC)
  2. What do ChatGPT, Perplexity and the other AI assistants tell buyers about it, and which sources do they cite?

This post wires both into an agent two ways: through MCP (no code) and as plain function-calling tools (about 60 lines of Python). It does not replace a page-content tool: for crawling and RAG ingestion, use something like Apify's Website Content Crawler or RAG Web Browser, Tavily, Exa or Firecrawl. These tools sit next to them.

Option 1: MCP, no code

Apify runs a hosted MCP server and exposes any Actor as a tool. Load only the tools you need, because fewer tools means better tool selection:

https://mcp.apify.com?tools=wrenfield-data/keyword-search-volume,wrenfield-data/ai-answer-scraper,wrenfield-data/ai-search-visibility-tracker
  • Claude Code: claude mcp add --transport http wrenfield "<the URL above>", then type /mcp and sign in to Apify.
  • Claude Desktop, Cursor, VS Code, ChatGPT apps: add the URL as a remote MCP server and sign in with Apify (OAuth). Clients without OAuth can send Authorization: Bearer <APIFY_TOKEN>.
  • Each tool shows the agent its input schema, so a prompt like this works as written:

Get US search volume for "crm software" and "email marketing tools". Then check whether Perplexity recommends HubSpot for "What is the best CRM for a small business?" and tell me which keyword to write about first.

Option 2: function tools in your own agent loop

If you run your own loop (OpenAI-style tool calls, Anthropic tool use, LangGraph, anything), each tool is one HTTP call to the Apify API. The helper below runs an Actor synchronously, returns its rows, and passes maxTotalChargeUsd so Apify stops the run at that spend, which is the guardrail you want when a model decides how often to call it.

"""Three agent tools backed by Wrenfield Data Actors on Apify. Each returns a short Markdown string an LLM can read.
Needs: pip install requests ; export APIFY_TOKEN=...   Every call is capped with maxTotalChargeUsd."""
import os
import requests

def run_actor(actor: str, payload: dict, max_usd: float = 0.50) -> list[dict]:
    """Run an Apify Actor synchronously and return its dataset rows. Aborts spending beyond max_usd."""
    r = requests.post(
        f"https://api.apify.com/v2/acts/{actor.replace('/', '~')}/run-sync-get-dataset-items",
        params={"maxTotalChargeUsd": max_usd},
        headers={"Authorization": f"Bearer {os.environ['APIFY_TOKEN']}"},
        json=payload, timeout=300)
    r.raise_for_status()
    return r.json()

def keyword_demand(keywords: list[str], country: str = "United States") -> str:
    """Monthly Google search volume and CPC per keyword."""
    rows = run_actor("wrenfield-data/keyword-search-volume", {"keywords": keywords, "location": country}, max_usd=0.50)
    out = ["| keyword | searches / month | CPC (USD) | competition |", "|---|---|---|---|"]
    for r in rows:
        if r.get("type") != "keyword":
            continue
        vol = f"{r['search_volume']:,}" if r.get("found") and r.get("search_volume") is not None else "no data"
        cpc = f"{r['cpc']:.2f}" if r.get("cpc") is not None else "-"
        out.append(f"| {r['keyword']} | {vol} | {cpc} | {r.get('competition') or '-'} |")
    return "\n".join(out)

def ai_answer(prompt: str, engines: tuple[str, ...] = ("perplexity", "chatgpt")) -> str:
    """What AI engines answer to a prompt, with the sources they cite."""
    rows = run_actor("wrenfield-data/ai-answer-scraper", {"prompts": [prompt], "engines": list(engines)}, max_usd=0.25)
    out = []
    for r in rows:
        if r.get("status") != "ok":
            out.append(f"## {r.get('engine_name')}: no answer ({r.get('note')})")
            continue
        src = ", ".join(r.get("cited_domains", [])[:5]) or "none"
        out.append(f"## {r['engine_name']}\n{r['answer_markdown'][:1500]}\n\nCited domains: {src}")
    return "\n\n".join(out)

def brand_check(brand: str, domain: str, prompts: list[str], competitors: list[str] | None = None,
                engines: tuple[str, ...] = ("perplexity", "chatgpt")) -> str:
    """Does each engine name the brand for each prompt, in what position, and which competitors does it name instead?"""
    rows = run_actor("wrenfield-data/ai-search-visibility-tracker",
                     {"brands": [brand], "domains": [domain], "prompts": prompts, "engines": list(engines),
                      "competitors": competitors or []},   # e.g. ["Salesforce | salesforce.com", "Pipedrive | pipedrive.com"]
                     max_usd=1.00)
    out = []
    for r in rows:
        if r.get("type") != "check":
            continue
        if r.get("status") != "ok":
            out.append(f"- {r['engine_name']} | {r['prompt']}: no answer")
            continue
        said = f"named (position {r['brand_position']})" if r.get("brand_mentioned") else "not named"
        rivals = ", ".join(r.get("competitors_mentioned") or r.get("other_brands_mentioned") or []) or "no competitors named"
        out.append(f"- {r['engine_name']} | {r['prompt']}: {brand} {said}; others: {rivals}")
    return "\n".join(out)

Two design choices that matter for agents:

  • Return Markdown or short text, not raw rows. A 31-field JSON row costs tokens and the model ignores most of it. Each function keeps the fields the model needs.
  • Cap every call. The caps above are $0.50, $0.25 and $1.00 per call. At current Free-plan prices, keyword_demand costs $0.004 per keyword, ai_answer $0.015 per answer, and brand_check $0.04 per prompt per engine (the tracker price is scheduled to change to $0.06 on November 2, 2026; check the Actor page).

What the agent reads

keyword_demand(["crm software", "email marketing tools"]) (real rows, Google Ads live source, run on Oct 22, 2026):

| keyword | searches / month | CPC (USD) | competition |
|---|---|---|---|
| crm software | 201,000 | 37.13 | LOW |
| email marketing tools | 4,400 | 101.75 | LOW |

ai_answer("What is the best CRM for a small business?", ("perplexity",)) (real Perplexity answer from Oct 19, 2026, cut in this post; the function itself returns up to 1,500 characters):

## Perplexity
**For most small businesses, HubSpot CRM is the best starting point**: it offers a free entry point, contact management, deal pipelines, and marketing/service features in one ecosystem.[4][6] Choose **Zoho CRM** instead if keeping costs low and gaining broad functionality matter most; choose **Pipedrive** if your main priority is a simple, sales-focused pipeline.[2][4]

| Best for | CRM | Why choose it |
|---|---|---|
| Best overall starting point | **HubSpot CRM** | Easy to adopt, with free tools and sales, marketing, and service capabilities.[4][6] |
[... 4 more rows and a short recommendation list cut for this post ...]

Cited domains: salesforce.com, pcmag.com, techradar.com, wise.com, microsoft.com

brand_check("HubSpot", "hubspot.com", ["What is the best CRM for a small business?"], ["Salesforce | salesforce.com", "Pipedrive | pipedrive.com"]) (real run, Oct 22, 2026):

- Perplexity | What is the best CRM for a small business?: HubSpot named (position 1); others: Salesforce, Pipedrive
- ChatGPT | What is the best CRM for a small business?: HubSpot named (position 1); others: Salesforce, Pipedrive

The brand check returns booleans and positions, not prose, so the agent can branch on brand_mentioned instead of reading an essay.

Putting it together in one prompt

You are a content strategist. For each candidate topic, call keyword_demand. For the best one, call ai_answer and brand_check and write a three-line brief: the demand, who the AI assistants recommend today, and one source they cite that we should try to get listed on.

The loop is: demand first (cheap), then AI answers only for the topic that earns it (more expensive per call). That ordering keeps the cost per brief at well under a dollar.

Limits, so you can trust what you see

  • AI answers are samples. The same prompt gives a different answer next time and differs between engines. One answer is an anecdote; ten prompts across two engines, tracked weekly, is a signal.
  • The volume sample is a paid-plan source. Free Apify plan runs of Keyword Search Volume read a keyword database and are capped at 10 keywords per run.
  • Perplexity and ChatGPT agree here (HubSpot first in both), but that is one question in one category, not a general finding.
  • Not a replacement for page tools. If your agent needs the text of a page, use a crawler or a search API that returns page content.

Links

If a field you need is missing, tell me in the comments and I will look at it.

來源:DEV Community · dev.to