diff --git a/docs.json b/docs.json
index 98fa51a..2829f24 100644
--- a/docs.json
+++ b/docs.json
@@ -38,6 +38,7 @@
"speed-and-price",
"mcp-server",
"n8n",
+ "langchain",
"agent-skills",
"agent-self-signup",
"agent-payments"
diff --git a/langchain.mdx b/langchain.mdx
new file mode 100644
index 0000000..1b60088
--- /dev/null
+++ b/langchain.mdx
@@ -0,0 +1,195 @@
+---
+title: "LangChain"
+description: "Give a LangChain agent the whole AnyAPI catalog through five tools, one key, and a USD wallet."
+---
+
+`langchain-anyapi` is the official LangChain integration for AnyAPI. It gives an agent
+hundreds of data and scraping APIs through five tools, one key, and a wallet billed per
+request in real US dollars.
+
+| | |
+|---|---|
+| **Package** | [`langchain-anyapi`](https://pypi.org/project/langchain-anyapi/) |
+| **Source** | [`getanyapi-com/integrations`](https://github.com/getanyapi-com/integrations) |
+| **Python** | 3.10 or newer |
+| **Auth** | `ANYAPI_API_KEY`, or `api_key=` on any tool or the toolkit |
+| **Tools** | `anyapi_search_apis`, `anyapi_list_apis`, `anyapi_get_api`, `anyapi_run_api`, `anyapi_get_balance` |
+
+## Five tools, not one per API
+
+AnyAPI publishes hundreds of APIs. Binding one tool per API would exhaust an agent's
+context before it asked its first question, so this package teaches the loop instead:
+search or list to find an API, read its input schema, then run it. An agent that learns
+those five tools once can reach the entire catalog.
+
+Input schemas are strict. They reject unknown fields rather than ignoring them, so an
+input built from a description instead of a schema usually fails. Always call
+`anyapi_get_api` before the first `anyapi_run_api` on an API.
+
+## Install
+
+The package depends on `langchain-core`, not on `langchain` itself. Install `langchain`
+alongside it if you want the `create_agent` helper used below.
+
+```bash
+pip install langchain langchain-anyapi
+```
+
+## Authenticate
+
+Set `ANYAPI_API_KEY` in the environment, or pass `api_key=` to the toolkit or to any
+individual tool. Need a key? Create one in the [dashboard](https://getanyapi.com/dashboard),
+or see the [Quickstart](/quickstart).
+
+```bash
+export ANYAPI_API_KEY=YOUR_ANYAPI_KEY
+```
+
+The client is built on first use, so importing the package and constructing a tool need
+neither a key nor a network connection. A missing key surfaces only when a tool is
+actually called.
+
+Alongside `api_key`, every tool and the toolkit accept `base_url`, `timeout`, and
+`max_retries`. Omit them to keep the SDK defaults.
+
+## Build an agent
+
+`AnyAPIToolkit().get_tools()` returns all five tools, and `ANYAPI_INSTRUCTIONS` is a
+system prompt that teaches the discover, inspect, run loop and its cost discipline.
+
+```python
+from langchain.agents import create_agent
+from langchain_anyapi import ANYAPI_INSTRUCTIONS, AnyAPIToolkit
+
+agent = create_agent(
+ "anthropic:claude-sonnet-4-5",
+ tools=AnyAPIToolkit().get_tools(),
+ system_prompt=ANYAPI_INSTRUCTIONS,
+)
+```
+
+## Or call one tool at a time
+
+Each tool is a plain LangChain `BaseTool`, so you can invoke it directly or bind a subset
+to your own model.
+
+```python
+from langchain_anyapi import AnyAPIGetAPI, AnyAPIRunAPI, AnyAPISearchAPIs
+
+AnyAPISearchAPIs().invoke({"query": "reddit trending posts"})
+AnyAPIGetAPI().invoke({"sku_id": "reddit.trending_posts"})
+AnyAPIRunAPI().invoke({"sku_id": "reddit.trending_posts", "input": {"limit": 2}})
+```
+
+## Tools
+
+
+
+ Ranked search across the catalog, returning matches with their descriptions and
+ without their schemas. Never charges.
+
+ | Field | Type | Required | Description |
+ |---|---|---|---|
+ | `query` | string | yes | What you need, in your own words |
+ | `category` | string | no | Category slug to narrow the search |
+ | `platform` | string | no | Platform slug to narrow the search |
+ | `limit` | integer | no | Cap on matches returned |
+
+ **Returns** `results`, `total`, and `ranking`. Each result carries `id`, `platform`,
+ `name`, `description`, `category`, `pricing`, `execution`, and `relevance`.
+
+ This tool requires `query`. The REST endpoint behind it also accepts `category` or
+ `platform` on their own, so reach for `anyapi_list_apis` when you want to enumerate a
+ category rather than search it.
+
+
+ Browse APIs as lightweight summaries, optionally filtered by category. Descriptions
+ and schemas are omitted, so listing stays cheap in context. Never charges.
+
+ | Field | Type | Required | Description |
+ |---|---|---|---|
+ | `category` | string | no | Category slug to filter by |
+
+ **Returns** `apis`, an array of `id`, `name`, `category`, `pricing`, `heavy`, and
+ `execution`.
+
+
+ Get one API in full, including the strict input schema you need to build a valid
+ payload. Never charges.
+
+ | Field | Type | Required | Description |
+ |---|---|---|---|
+ | `sku_id` | string | yes | The API slug to describe |
+
+ **Returns** the summary fields plus `description`, `provider`, `method`, `path`,
+ `inputSchema`, `outputSchema`, `lanes`, and `latency`, which is `null` when there are
+ no successful observations to report.
+
+
+ Execute one API with a normalized input payload. This is the only tool that touches
+ your wallet.
+
+ | Field | Type | Required | Description |
+ |---|---|---|---|
+ | `sku_id` | string | yes | The API slug to execute |
+ | `input` | object | yes | Payload matching that API's input schema |
+ | `fields` | array of strings | no | Keys to keep on each result item |
+ | `max_items` | integer | no | Cap the number of result rows returned |
+ | `summary` | boolean | no | Return a structural outline instead of the full data |
+
+ **Returns** `found`, `data`, `provider`, `costUsd`, `items`, and `resultId`.
+
+ `fields`, `max_items`, and `summary` are response-budget controls. They keep a large
+ result from flooding the context window and change only what comes back to you, never
+ what you are charged.
+
+
+ Get the remaining wallet balance for the key you authenticate with. Takes no
+ arguments and never charges.
+
+ **Returns** `usd`, the remaining balance.
+
+
+
+## Async
+
+Every tool has a real async path built on the SDK's async client, not the sync client on
+a worker thread. Use `ainvoke` anywhere you would use `invoke`.
+
+```python
+from langchain_anyapi import AnyAPISearchAPIs
+
+results = await AnyAPISearchAPIs().ainvoke({"query": "tiktok profile"})
+```
+
+## Errors
+
+A failed call returns a readable payload rather than aborting the agent's run. The
+payload carries `error` and `status`, plus `code` and `requestId` when the gateway sends
+them. An agent can read that, adjust, and carry on within the same turn.
+
+Calling a tool with no key resolves at call time and returns this, with nothing charged:
+
+```python
+{"error": "no API key: pass api_key= or set ANYAPI_API_KEY", "status": 0}
+```
+
+## Prices
+
+Prices come off the wire exactly as AnyAPI published them, and this package never
+recomputes one from another. Every static price is quoted twice: `maxUsd` is what one
+request is billed, and `maxPer1kUsd` is the same price per 1,000 requests. Per 1,000 is
+the denomination AnyAPI quotes customers in, because most of the catalog costs a fraction
+of a cent per call.
+
+There is no quote tool here. `anyapi_get_api` already publishes `pricing.from.maxUsd`,
+the most a first-choice run is billed, and `pricing.failoverMaxUsd`, the ceiling for any
+run, so an agent can bound its spend before it calls. A completed run reports its actual
+charge as `costUsd`.
+
+
+ Not using LangChain? The same loop is available over the
+ [MCP server](/mcp-server), through the typed [Python and TypeScript SDKs](/sdks), and as
+ an [agent skill](/agent-skills). Need help? Reach out at
+ [support@getanyapi.com](mailto:support@getanyapi.com).
+
diff --git a/mcp-server.mdx b/mcp-server.mdx
index 8487265..17d23f6 100644
--- a/mcp-server.mdx
+++ b/mcp-server.mdx
@@ -24,9 +24,12 @@ registry-driven tool surface that covers the entire catalog — no tool-per-API
The MCP surface is **API-key only** — session tokens are not accepted. Send your key as
- `Authorization: Bearer `. Discovery (`list_apis`, `search_apis`, `get_api`) works
- **without a key**, so an agent can browse the catalog and read schemas before credentials are
- set up; `run_api` and `get_balance` require authentication.
+ `Authorization: Bearer `. Connecting is keyless: `initialize` and `tools/list`
+ answer without a credential, so a client can finish the handshake and read the tool list
+ before your key is in place. Every tool call needs a key, including the discovery tools
+ (`list_apis`, `search_apis`, `get_api`); without one they return `unauthorized`. To browse
+ the catalog with no key at all, use the public REST endpoints `GET /catalog` and
+ `GET /catalog/search` instead.
## Connect
@@ -123,6 +126,80 @@ registry-driven tool surface that covers the entire catalog — no tool-per-API
+## Run it locally over stdio
+
+Some MCP clients can only launch a local server and speak to it over stdio. For those,
+AnyAPI publishes a small local server that forwards everything to the hosted endpoint
+above.
+
+| | |
+|---|---|
+| **npm** | [`anyapi-mcp`](https://www.npmjs.com/package/anyapi-mcp) |
+| **Image** | `ghcr.io/getanyapi-com/mcp` |
+| **Source** | [`getanyapi-com/mcp`](https://github.com/getanyapi-com/mcp) |
+| **Transport** | stdio |
+| **Auth** | `ANYAPI_API_KEY` in the environment |
+| **Node** | 20 or newer |
+
+It declares no tools of its own. Every listing and every call is forwarded to
+`https://api.getanyapi.com/mcp`, so you get whatever the hosted server publishes, and a
+catalog change reaches you without upgrading anything.
+
+
+
+ ```json
+ {
+ "mcpServers": {
+ "anyapi": {
+ "command": "npx",
+ "args": ["-y", "anyapi-mcp"],
+ "env": { "ANYAPI_API_KEY": "YOUR_ANYAPI_KEY" }
+ }
+ }
+ }
+ ```
+
+
+ ```bash
+ claude mcp add anyapi -e ANYAPI_API_KEY=YOUR_ANYAPI_KEY -- npx -y anyapi-mcp
+ ```
+
+
+ ```json
+ {
+ "mcpServers": {
+ "anyapi": {
+ "command": "docker",
+ "args": [
+ "run", "-i", "--rm",
+ "-e", "ANYAPI_API_KEY",
+ "ghcr.io/getanyapi-com/mcp"
+ ],
+ "env": { "ANYAPI_API_KEY": "YOUR_ANYAPI_KEY" }
+ }
+ }
+ }
+ ```
+
+ The image is public, so the pull needs no credential. It is built for `linux/amd64`,
+ so Docker runs it under emulation on an Apple Silicon machine and prints a platform
+ warning on startup.
+
+
+
+`ANYAPI_API_KEY` is optional at startup. Without it the server still starts and lists its
+tools, because the hosted server answers `initialize` and `tools/list` unauthenticated.
+Set the key before your agent calls a tool: every tool call needs one.
+
+The server is listed in the official
+[MCP Registry](https://registry.modelcontextprotocol.io) as
+`io.github.getanyapi-com/anyapi`, which declares the hosted endpoint and both packages.
+
+
+ Prefer the hosted endpoint when your client speaks remote Streamable HTTP. It is one less
+ moving part, with nothing to install and nothing to keep up to date.
+
+
## Tools
Discovery (`list_apis`, `search_apis`, `get_api`) is free; only `run_api` touches your
diff --git a/quickstart.mdx b/quickstart.mdx
index d2422ab..ee328b3 100644
--- a/quickstart.mdx
+++ b/quickstart.mdx
@@ -146,10 +146,17 @@ curl -s "https://api.getanyapi.com/catalog?category=social"
# Search by intent
curl -s "https://api.getanyapi.com/catalog/search?q=tiktok&limit=10"
+# Or scope with no query at all: everything one platform can do
+curl -s "https://api.getanyapi.com/catalog/search?platform=reddit"
+
# Inspect one API's input and output schemas
curl -s https://api.getanyapi.com/v1/apis/tiktok.profile -H "X-API-Key: YOUR_ANYAPI_KEY"
```
+On `/catalog/search`, `q` is optional. Name any of `q`, `category`, or `platform`, in any
+combination: a scope on its own is a complete question, and only a request naming none of
+the three is rejected. Both endpoints are free and need no key.
+
Treat `inputSchema` as the request contract. Send only properties it declares. A field used by
one search API, including `limit`, `cursor`, `page`, or `sort`, may be invalid for another.