# Use okdata in LangChain: MCP tools or a small Python wrapper

> Give a LangChain agent okdata's social data in Python, either all endpoints through MCPAdapter or one endpoint as a @tool function with requests.

Canonical page: https://okdata.online/integrations/langchain/

This page ends with a Python agent that can answer "what are TikTok videos about portable blenders saying this week, and what do commenters complain about?" by searching TikTok, reading comments under the top videos and summarising them. It's the kind of script a growth analyst runs on Monday morning, or that an engineer drops into a larger pipeline. There are two ways to wire it: hand the agent the whole catalog through the MCP server, or wrap the one endpoint you need as a plain tool.

## Before you start

- Python 3.10 or newer, and a chat model the agent can use (the examples use Anthropic's, which needs `langchain-anthropic` and `ANTHROPIC_API_KEY`; any provider with tool calling works).
- An API key from okdata, starting with `okd_`. New keys come with $0.10 of credit. The [quickstart](/docs/quickstart/) explains how to get one.
- The key in the `OKDATA_API_KEY` environment variable, read by the code below, never written into it:

```bash
export OKDATA_API_KEY="okd_..."
```

## Way 1: every endpoint through MCP

LangChain's own MCP support lives in `langchain.mcp` (LangChain 1.4 or later, marked beta, so you'll see a `LangChainBetaWarning` once).

```bash
pip install "langchain[mcp]" langchain-anthropic
```

```python
import asyncio
import os

from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter

RULES = "Before any paid okdata call, say what it costs. Make at most four paid calls."

async def main() -> None:
    client = Client("https://api.okdata.online/mcp", auth=os.environ["OKDATA_API_KEY"])  # sent as Authorization: Bearer <key>
    async with MCPAdapter(client) as adapter:
        tools = await adapter.list_tools()  # find, describe, call, account
        agent = create_agent("claude-sonnet-5", tools, system_prompt=RULES)
        result = await agent.ainvoke({"messages": [{"role": "user", "content": (
            "Search TikTok for 'portable blender', one page. Read the comments under "
            "the three most liked videos and list the top complaints with links."
        )}]})
        print(result["messages"][-1].text)

asyncio.run(main())
```

The agent uses `find` and `describe` to pick endpoints and check prices, then `call` to fetch data.

Already on the older `langchain-mcp-adapters` package? Its `MultiServerMCPClient` still connects with `"transport": "streamable_http"`, `"url": "https://api.okdata.online/mcp"` and `"headers": {"Authorization": "Bearer " + os.environ["OKDATA_API_KEY"]}`, but the package is no longer maintained; LangChain's migration guide covers the move to `langchain.mcp`.

## Way 2: one endpoint as a tool

When a pipeline only ever needs one endpoint, a dozen lines with `requests` are easier to read and test than an MCP connection.

```bash
pip install langchain langchain-anthropic requests
```

```python
import os

import requests
from langchain.agents import create_agent
from langchain.tools import tool

API_URL = "https://api.okdata.online"

@tool
def tiktok_video_search(query: str) -> dict:
    """Search TikTok videos by keywords. One page of about 30 videos
    with likes, comments and author. Costs $0.002 per call."""
    response = requests.get(
        API_URL + "/v1/tiktok/videos/search",
        params={"query": query},
        headers={"Authorization": "Bearer " + os.environ["OKDATA_API_KEY"]},
        timeout=60,
    )
    # Errors come back as JSON too (code, message, retry_after_seconds),
    # so return them to the model instead of raising.
    return response.json()

agent = create_agent("claude-sonnet-5", [tiktok_video_search],
                     system_prompt="Make at most two searches per question.")
result = agent.invoke({"messages": [{"role": "user", "content": "What are TikTok videos about portable blenders showing this week?"}]})
print(result["messages"][-1].text)
```

Every endpoint follows the same pattern: `https://api.okdata.online/v1/` plus the endpoint id with dots as slashes, parameters in the query string. The parameter list is on each endpoint page.

## A first prompt to try

```text
Search TikTok for "portable blender", one page. Read the comments under the three
most liked videos and list the five most common complaints, each with a link.
Tell me the total okdata cost.
```

## What it costs

`find`, `describe` and `account` are free. The prompt above makes one [TikTok video search](/apis/tiktok/videos/search/) at $0.002 and reads comments on three videos at $0.002 each: $0.008 in total. A page of [Xiaohongshu note search](/apis/xiaohongshu/notes/search/) is $0.02. Failed calls are free. Each response tells you what it cost in `meta.billing.amount`, which is easy to log.

## When something goes wrong

- **`KeyError: 'OKDATA_API_KEY'`.** The variable isn't set in the shell that runs Python. Export it and run again.
- **`unauthorized` (401).** The key arrived but isn't valid: a typo, a missing character, or a revoked key.
- **`insufficient_balance` (402).** Not enough balance for the call. Nothing was charged. Top up and retry; prices are on the [pricing page](/pricing/).
- **`rate_limited` (429).** Too many calls at once, typical when you run agents in parallel. The error includes `retry_after_seconds`; in your own wrapper, sleep that long and send the same request again. No charge.
- **`list_tools()` returns nothing or fails to connect.** Check the URL ends in `/mcp`, that `langchain` is 1.4 or later (`pip show langchain`), and that outbound HTTPS to `https://api.okdata.online` is allowed where the code runs.

## Read next

- [The MCP server](/mcp/): the four tools and what to tell the agent.
- [TikTok video search](/apis/tiktok/videos/search/): parameters, fields and price.
