MCP · Claude · AI agents

Build an MCP tool for live web data

AI assistants such as Claude can use outside tools, but each app needs to know which tools exist and how to use them. The Model Context Protocol (MCP) is an open standard for exactly that: a tool provider offers one address, and every app that speaks MCP can find the tools behind it and use them.

A language model on its own only knows what it learned during training. With live data it can answer “What does this cost on Amazon right now?” or “How many views does this video have today?” from the real page instead of guessing. everydata.io runs a hosted MCP server with 31 ready-made tools for Amazon, Walmart, Zalando, Otto, Zillow, Yahoo Finance, YouTube and more. You add one address and your API key to your assistant – there is nothing to install or run.

Updated · by everydata.io

What you will have at the end

  • Claude Desktop or Claude Code connected to everydata.io, answering with live data.
  • The same tools in your own agent through the OpenAI or Anthropic API.
  • Know what to do when a tool call fails – and, if you need it, how to run your own server instead.

What you need

  • A free everydata.io API key – create one here.
  • An MCP-capable app or API: Claude Desktop (with Node.js installed), Claude Code, the OpenAI Responses API or the Anthropic Messages API.

01What happens when the assistant asks for data

  • Your app connects to https://api.everydata.io/mcp and asks which tools there are – for example amazon_product_by_asin, amazon_search, amazon_reviews, walmart_search, zalando_search, otto_search, youtube_video, youtube_comments and yahoo_quotes.
  • When a question needs live data, the model picks a tool and fills in its inputs, such as an ASIN or a video ID.
  • everydata.io loads the page, returns the data, and the model answers with it.
  • Your API key goes with every request, so each tool call counts against your plan like a normal API request – with the same weights. Calls that fail on our side are not charged.

Two tools cover everything else: list_endpoints lists every data endpoint with its inputs, and call_endpoint calls any of them. account_quota tells the model how much of your monthly quota is left. The full tool list is in the MCP server docs.

02Connect Claude Desktop

The quickest way: in Claude Desktop (or claude.ai) open Settings → Connectors → Add custom connector and enter https://api.everydata.io/mcp. Claude sends you to everydata.io, you sign in with your e-mail link and approve access – no key to copy. Prefer to use an API key instead? Connect through mcp-remote, a small bridge that Claude Desktop starts on your machine and that forwards every request – with your key – to the hosted server, as shown below.

Open Settings → Developer → Edit config, add the entry below to claude_desktop_config.json, put your key after Bearer and restart Claude Desktop.

claude_desktop_config.json
{
  "mcpServers": {
    "everydata": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.everydata.io/mcp",
        "--header",
        "Authorization:${EVERYDATA_AUTH}"
      ],
      "env": {
        "EVERYDATA_AUTH": "Bearer ds_your_key"
      }
    }
  }
}

The key sits in env and the header has no space after the colon on purpose: Claude Desktop on Windows does not pass spaces inside args through correctly, and mcp-remote fills in ${EVERYDATA_AUTH} from env. The same entry works on macOS.

After the restart, ask a question that needs live data (see the test below) – Claude asks for permission to use an everydata tool. If no tools show up, Settings → Developer shows whether the bridge is running and its last error. A missing Node.js (npx not found) is the most common cause.

03Connect Claude Code

Claude Code talks to remote MCP servers directly. One command registers the server with your key:

terminal
export EVERYDATA_KEY="ds_your_key"
claude mcp add --transport http everydata https://api.everydata.io/mcp \
  --header "Authorization: Bearer $EVERYDATA_KEY"

# check that it is connected
claude mcp list

Your shell fills in $EVERYDATA_KEY when you run the command, and Claude Code saves the header in its settings. Add --scope user to use the server in every project, not just the current one. Inside Claude Code, /mcp shows the connection and its tools.

04Use it from the OpenAI or Anthropic API

If you build your own agent, both APIs can call a remote MCP server for you: you pass the address and the key, and the provider lists the tools, calls them and hands the results to the model. You do not write any tool code yourself. Both examples read your key from the EVERYDATA_KEY environment variable.

OpenAI Responses API – an mcp tool with the key in headers:

openai_mcp.py
import os

from openai import OpenAI

client = OpenAI()

resp = client.responses.create(
    model="gpt-6-astra",
    input="How many views does the Despacito video on YouTube have right now?",
    tools=[{
        "type": "mcp",
        "server_label": "everydata",
        "server_url": "https://api.everydata.io/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['EVERYDATA_KEY']}"},
        "require_approval": "never",
    }],
)
print(resp.output_text)

Anthropic Messages API – the MCP connector takes the server in mcp_servers, a matching mcp_toolset in tools, and the mcp-client-2025-11-20 beta header (the SDK sets it from betas):

anthropic_mcp.py
import os

import anthropic

client = anthropic.Anthropic()

resp = client.beta.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "How many views does the Despacito video on YouTube have right now?"}],
    mcp_servers=[{
        "type": "url",
        "url": "https://api.everydata.io/mcp",
        "name": "everydata",
        "authorization_token": os.environ["EVERYDATA_KEY"],  # sent as "Authorization: Bearer …"
    }],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "everydata"}],
    betas=["mcp-client-2025-11-20"],
)
print(resp.content[-1].text)

In the ChatGPT app, add a custom connector with the URL https://api.everydata.io/mcp (the option depends on your ChatGPT plan). You'll sign in to everydata.io and approve access; you can revoke it any time in your dashboard under API keys.

05Try it: one question, one tool call

Ask your assistant “How many views does the Despacito video on YouTube have right now?”. The model picks youtube_video and sends the video ID:

tool call
{
  "name": "youtube_video",
  "arguments": { "id": "kJQP7kiw5Fk" }
}

The tool returns the same answer as the REST endpoint, and the assistant replies with the current numbers. Shortened documented example:

Example response · GET /ytb/youtube-video-details
{
  "responseStatus": "PAGE_FOUND",
  "responseMessage": "Page successfully found!",
  "videoId": "kJQP7kiw5Fk",
  "title": "Luis Fonsi - Despacito ft. Daddy Yankee",
  "channelName": "LuisFonsiVEVO",
  "viewCount": 9125159593,
  "likeCount": 56673581,
  "commentCount": 4300000,
  "publishedAt": "2017-01-12T21:00:02-08:00"
}

This call counts as one request. Very long answers – many reviews or search results – are shortened for the model, and the tool tells it to ask for less, for example a smaller page.

06When a tool call fails

Errors come back to the model as a failed tool call with the status code in the text, so the assistant can usually tell you what went wrong.

  • 401 – the key or sign-in is missing or wrong. Check that the header reads Authorization: Bearer ds_… (or send the key as x-api-key). With a connector sign-in, disconnect and connect again.
  • 429 – too many requests at once for your plan. Wait for the number of seconds in the message and try again. A 403 means this month's quota is used up; account_quota shows what is left.
  • 503 or another 5xx – the site could not be loaded right now. These calls are not charged; simply ask again a little later.
  • Timeout – a tool call gets 50 seconds. Slow pages (many reviews, large searches) can take longer; the call then fails, is not charged, and a narrower request usually works.

The limits per plan are in Limits & quota.

07Alternative: run your own MCP server

If you want to decide exactly which endpoints and fields the model sees, you can write a small server yourself with the official MCP Python SDK (pip install "mcp[cli]>=2" requests, or let uv install both). Each tool is one function: one everydata.io request, a few selected fields. The docstring is what the model reads.

server.py
"""A minimal MCP server that gives AI assistants live product and video data from everydata.io."""
import os

import requests
from mcp.server.mcpserver import MCPServer

API = "https://api.everydata.io"
KEY = os.environ["EVERYDATA_API_KEY"]

mcp = MCPServer("everydata")


def _get(path: str, params: dict) -> dict:
    """One everydata.io request. Errors come back as data, so the assistant can explain them."""
    try:
        resp = requests.get(f"{API}{path}", params=params, headers={"x-api-key": KEY}, timeout=60)
    except requests.RequestException as exc:
        return {"error": "network", "detail": str(exc)[:300]}
    if resp.status_code >= 400:  # e.g. 429 = too many requests at once, 5xx = page could not be loaded
        return {"error": resp.status_code, "detail": resp.text[:300]}
    return resp.json()


def _pick(data: dict, keys: tuple) -> dict:
    return data if "error" in data else {k: data.get(k) for k in keys}


@mcp.tool()
def amazon_product(asin: str, domainCode: str = "com") -> dict:
    """Live title, price, list price, availability and rating of an Amazon product.
    asin is the 10-character product ID; domainCode is the marketplace (com, de, co.uk …).
    A price of 0 means the page shows no price right now."""
    data = _get("/amz/amazon-lookup-product-by-asin", {"asin": asin, "domainCode": domainCode})
    return _pick(data, ("productTitle", "asin", "price", "retailPrice", "currency",
                        "productRating", "countReview", "warehouseAvailability"))


@mcp.tool()
def zalando_search(keyword: str, page: int = 1) -> dict:
    """Search the Zalando shop (zalando.de by default) and return up to 10 products with price and link."""
    data = _get("/zal/zalando-search-by-keyword", {"keyword": keyword, "page": page})
    if "error" in data:
        return data
    keep = ("productDescription", "manufacturer", "price", "retailPrice", "currency", "dpUrl")
    return {"results": [{k: p.get(k) for k in keep} for p in data.get("searchProductDetails", [])[:10]]}


@mcp.tool()
def youtube_video(video: str) -> dict:
    """Current view, like and comment counts of a YouTube video. video is the video ID or its URL."""
    data = _get("/ytb/youtube-video-details", {"id": video})
    return _pick(data, ("videoId", "title", "channelName", "viewCount", "likeCount", "commentCount", "publishedAt"))


if __name__ == "__main__":
    mcp.run()  # the assistant app starts this script and talks to it directly

Claude Desktop starts the script itself. Use full paths (which uv shows where uv is), because Claude Desktop does not start from your terminal:

claude_desktop_config.json
{
  "mcpServers": {
    "everydata-local": {
      "command": "/Users/you/.local/bin/uv",
      "args": ["run", "--with", "mcp[cli]>=2", "--with", "requests",
               "python", "/Users/you/everydata-mcp/server.py"],
      "env": { "EVERYDATA_API_KEY": "ds_your_key" }
    }
  }
}

In Claude Code:

terminal
claude mcp add everydata-local --env EVERYDATA_API_KEY=ds_your_key -- uv run --with "mcp[cli]>=2" --with requests python /absolute/path/to/server.py

Endpoints used in this guide

GET/ytb/youtube-video-details

Video Details · YouTube API

GET/amz/amazon-lookup-product-by-asin

Product Details by ASIN · Amazon API

GET/zal/zalando-search-by-keyword

Search products by keyword · Zalando API

All parameters in the API reference

Try it with your own data

The free plan includes 100 requests a month, usable on every platform – enough to follow this guide end to end.