# LangChain

Give a [LangChain](https://docs.langchain.com) agent Onekey's tools through the hosted [MCP server](https://onekey.dev/docs/mcp.md). The MCP adapters turn the eleven tools into LangChain tools; the agent finds endpoints, reads their contracts and fetches data.

## Prerequisites

- A Onekey [API key](https://onekey.dev/docs/authentication.md) in `ONEKEY_KEY`. For unattended agents, use a key with a [credit limit](https://onekey.dev/docs/key-limits.md).
- A chat model and its API key (any provider LangChain supports).
- Python: `pip install langchain langchain-mcp-adapters`, plus your model provider's package. JavaScript: `npm install @langchain/mcp-adapters langchain`, plus your provider's package.

## The 5-minute path

The adapters connect over the MCP "http" transport (Streamable HTTP) with custom headers, which is how Onekey authenticates.

```python
import asyncio, os
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient

async def main():
    client = MultiServerMCPClient({
        "onekey": {
            "transport": "http",
            "url": "https://api.onekey.dev/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['ONEKEY_KEY']}"},
        }
    })
    tools = await client.get_tools()
    agent = create_agent("anthropic:claude-sonnet-5", tools)  # or any model string your provider supports
    result = await agent.ainvoke({"messages": "Find the Onekey endpoint for the latest release of a GitHub repo and use it for facebook/react. Say what it cost."})
    print(result["messages"][-1].content)

asyncio.run(main())
```

```javascript
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";

const client = new MultiServerMCPClient({
  onekey: {
    transport: "http",
    url: "https://api.onekey.dev/mcp",
    headers: { Authorization: `Bearer ${process.env.ONEKEY_KEY}` },
  },
});

const tools = await client.getTools();
const agent = createAgent({ model: "anthropic:claude-sonnet-5", tools });
const result = await agent.invoke({
  messages: [{ role: "user", content: "Find the Onekey endpoint for the latest release of a GitHub repo and use it for facebook/react. Say what it cost." }],
});
console.log(result.messages.at(-1)?.content);
```

The agent will typically run `search_endpoints` (free) to find `github.latest_release`, `describe_endpoint` (free) to read its parameters, then `call_endpoint` with `platform: "github"`, `endpoint: "latest_release"` and `params: {"owner": "facebook", "repo": "react"}`. Each tool result includes `credits_used` and `credits_remaining`, so the agent can report the cost.

## Example: a dependency check

Prompt the agent with a list and let it fan out:

> For each of facebook/react, vuejs/core and sveltejs/svelte, get the latest release name and date and the current star count. Use the cheapest Onekey endpoints and tell me the total credits before you start.

What that costs: [`github.latest_release`](https://onekey.dev/docs/api/github/latest_release.md) is 1 credit and [`github.repo`](https://onekey.dev/docs/api/github/repo.md) is 1 credit, so 6 credits for three repositories, plus nothing for the discovery calls. If the agent instead uses [`github.search_repos`](https://onekey.dev/docs/api/github/search_repos.md) (5 credits) to find repositories by name, it is 5 credits per search. Tell it the exact endpoints to keep the bill predictable.

To fetch a whole list in one go from your own code rather than through an agent, use [batch](https://onekey.dev/docs/batch.md): it is not exposed as an MCP tool.

## Cost notes

- The five free tools (`list_platforms`, `search_endpoints`, `describe_endpoint`, `get_status`, `get_credits`) cost nothing; the six tools that spend credits (`call_endpoint`, `lookup_url`, `search_multi`, `creator_card`, `search_universal`, `report`) spend credits.
- A cache hit is free and a failed call is refunded.
- Prompt for a plan and a price before a job that pages or fans out over platforms. Results carry a `pagination.next_cursor` when there is more; the agent should page only as far as it needs.
- To enrich rows with sentiment or similar signals, see [Labels](https://onekey.dev/docs/labels.md). It is separate from the tools above and is not available through MCP.

## Troubleshooting

| Symptom | Likely error | What to do |
| --- | --- | --- |
| Every call is refused | [`UNAUTHORIZED`](https://onekey.dev/docs/errors.md#unauthorized) | The key is missing, misspelled or revoked. Check the header name and that the value has no stray spaces or quotes. |
| Calls stop working partway through a job | [`INSUFFICIENT_CREDITS`](https://onekey.dev/docs/errors.md#insufficient-credits) or [`KEY_BUDGET_EXCEEDED`](https://onekey.dev/docs/errors.md#key-budget-exceeded) | Nothing was charged for the refused call. Top up, or raise the key's [credit limit](https://onekey.dev/docs/key-limits.md). Do not retry in a loop. |
| "Too many requests" | [`RATE_LIMITED`](https://onekey.dev/docs/errors.md#rate-limited) | Wait the `Retry-After` seconds. Loops that call once per item should add a pause. See [Rate limits](https://onekey.dev/docs/rate-limits.md). |
| A parameter is rejected | [`INVALID_PARAMS`](https://onekey.dev/docs/errors.md#invalid-params) | Read the parameter names from the endpoint's page (or `describe_endpoint`); do not guess them. |
| A platform fails intermittently | [`UPSTREAM_ERROR`](https://onekey.dev/docs/errors.md#upstream-error) / [`UPSTREAM_TIMEOUT`](https://onekey.dev/docs/errors.md#upstream-timeout) | The source platform, not you. Refunded; retry with backoff and check [status](https://onekey.dev/docs/status.md). |
| The adapter raises an exception instead of the model seeing an error | any | The adapters raise on tool failure rather than passing it to the model. Wrap the agent call in `try/except` (`try/catch` in JavaScript), and log the `error.type` from the message. |
| Results end with a `truncated` field | none | The result was shortened to about 30,000 characters. Ask for fewer rows, or page with `cursor` ([`INVALID_CURSOR`](https://onekey.dev/docs/errors.md#invalid-cursor) means the cursor was edited or stale; restart from the first page). |

## Untested

- The connection shape (`transport: "http"`, `url`, `headers`), `get_tools` / `getTools` and `create_agent` / `createAgent` follow LangChain's current MCP documentation ([Python repository](https://github.com/langchain-ai/langchain-mcp-adapters), [JavaScript guide](https://docs.langchain.com/oss/javascript/langchain/mcp)) as of 2026-09-30. **These snippets were not run.** Package and function names move quickly, so check the linked pages if an import fails.
- The model string `anthropic:claude-sonnet-5` is copied from LangChain's page; use the model you have access to.
- The hosted MCP server was tested with the official MCP client, not with LangChain's adapters.

## Next

[MCP server](https://onekey.dev/docs/mcp.md), [Credits & pricing](https://onekey.dev/docs/credits.md), [Errors](https://onekey.dev/docs/errors.md).
