MCP · REST API · SDK
API Documentation
Base URL, API key, account, search, call, errors.
The public site, docs, and Skill URL are agentools.uno. clawdtools.uno is a legacy host that still serves /v1, /mcp, and redirects human pages to agentools.uno.
Not writing code?
Connecting an existing agent? Use the connect page — no key required.
https://agentools.uno/SKILL.mdFor agents in a terminal: Claude Code, Codex CLI, Cursor, OpenClaw
https://agentools.uno/mcpFor agents with a client app: ChatGPT, Codex, Claude, Cursor
Authentication
Tool calls, ratings and account endpoints require a Bearer token (API Key). Search & browse are public. Get a key from the API Keys page.
Base URL https://agentools.uno · Authorization: Bearer uno_…
GET /v1/auth/me
Who you are and how many credits you have left.
curl -s https://agentools.uno/v1/auth/me \
-H "Authorization: Bearer uno_…"{
"id": "usr_…",
"email": "you@example.com",
"name": "You",
"plan": "free",
"free_credits_remaining": 500,
"balance": 0,
"api_keys": [{ "id": "…", "prefix": "uno_", "name": "Default", "active": true }]
}For CLI Agents (Device Code Flow)
# 1. Request device code
curl -s -X POST https://agentools.uno/oauth/device/code \
-H "Content-Type: application/json" \
-d '{"client_id":"my-agent"}'
# 2. User authorizes, then poll — access_token is a uno_… key
curl -s -X POST https://agentools.uno/oauth/token \
-H "Content-Type: application/json" \
-d '{"device_code":"DEVICE_CODE","client_id":"my-agent"}'Programmatic access
REST API · Quick Start
Two product endpoints: search, then call. Auth and account sit beside them.
1. Search Tools
/v1/toolscurl -s "https://agentools.uno/v1/tools?q=weather&limit=5&mode=hybrid" \
-H "Authorization: Bearer uno_…"Returns tools with input_schema (JSON Schema) so you know exactly what arguments to pass.
Query params: q (keyword), category, server (server slug filter), mode=keyword|semantic|hybrid (default hybrid), limit (≤50), offset. Search is public — Bearer token is optional and only used to log usage.
{
"tools": [
{
"tool": "weather-free.get_current_weather",
"name": "get_current_weather",
"desc": "Get current weather for a city",
"desc_en": "Get current weather for a city",
"input_schema": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] },
"server": "weather-free",
"server_name": "Weather Free",
"category": "weather",
"auth_required": false,
"operation": { "type": "read", "idempotency_mode": "none", "idempotency_key_field": null },
"stats": { "avg_ms": 234, "calls_7d": 1200, "success_rate": 0.99, "rating": 4.5 },
"pricing": { "mode": "per_call", "cost": 1.0 }
}
],
"total": 1,
"mode": "hybrid"
}2. Call a Tool
/v1/callcurl -s -X POST https://agentools.uno/v1/call \
-H "Authorization: Bearer uno_…" \
-H "Content-Type: application/json" \
-d '{"tool": "amap-maps.weather", "arguments": {"city": "北京"}}'Response Format
{
"data": {"temperature": "22C", "weather": "晴"},
"error": null,
"meta": {
"latency_ms": 234,
"credits_used": 1.0,
"outcome": "executed",
"retryable": false
}
}meta tells you what the call cost and whether repeating it is safe: latency_ms, credits_used, outcome (executed / not_executed / outcome_unknown) and retryable. A successful call does not return view by default. Pass view: true, or use uno call --view-only (uno-cli ≥ 1.0.7), when you need it. view has readable, title, text, and items (body text at most 500 characters, lists at most 10). Errors, including soft failures, omit it.
Retry Safety
Search returns an operation block for every tool: type is read or write, idempotency_mode is none, native, gateway or keyed. Retry a failed call only when the tool is read or explicitly idempotent, or when meta.outcome is not_executed. Never repeat a write that came back outcome_unknown — the gateway sets retryable: false for exactly that case.
Rate Limits
POST /v1/call allows 120 requests per minute per user; other authenticated endpoints allow 60. Over the limit you get rate_limit_exceeded with meta.retry_after_seconds and meta.limit_per_minute — back off instead of hammering.
More Endpoints
Beyond search & call, these are the endpoints agents and SDKs use most. All require a Bearer token except where noted.
GET /v1/serversList hosted servers with tool counts, grouped by category (public)GET /v1/tools/{tool_slug}Single tool detail with full pricing & stats (public)POST /v1/rateRate a tool 0.0–5.0; upserts your rating and updates aggregatesGET /v1/auth/meCurrent user info — credits, plan, balanceGET /v1/usage/summaryUsage totals for today / 7d / 30dGET /v1/usage/historyPaginated call history — filter by tool, server or success. Catalog search rows are hidden by default; pass include_search=true to show them. uno logs does the same; uno logs --include-search (uno-cli ≥ 1.0.7) sends include_search=true.GET /v1/auth/keysList your API keysPOST /v1/auth/keysCreate a new API key (returns raw key once)Python SDK
The SDK wraps the same two endpoints and adds typed errors, local schema validation, a retry policy and concurrency control. pip install uno-sdk
from uno_sdk import Uno
uno = Uno(api_key="uno_…")
# Search first so the SDK knows whether retries are safe
tool = uno.search("weather")[0]
result = uno.call(tool.slug, {"location": "Beijing"}, timeout=30)
print(result.data, result.credits_used)
# Validate args against the tool's JSON Schema before sending
uno.call_tool(tool, {"location": "Beijing"}) # validates by default
# Retry only reads or tools explicitly marked idempotent
uno.call_tool(tool, {"location": "Beijing"}, retry=3)Account, credits and cost
Every result knows what it cost; me() and usage() answer the rest.
account = uno.me()
account["plan"], account["free_credits_remaining"], account["balance"]
spent = uno.usage()
spent["summary"]["today"]["credits"] # credits burned today
spent["trend"] # last 7 days, per day
# Cost and latency of the call you just made
result.credits_used, result.latency_ms, result.outcome
# Feed the catalog back: rate a tool 0.0–5.0
uno.rate(tool.slug, 4.5, "accurate and fast")Handling errors in your code
Each gateway error code maps to a typed exception. The one you must handle is AuthRequiredError: the tool needs your user to authorize a third-party app, and auth_url is where they do it.
from uno_sdk import (
AuthError, AuthRequiredError, QuotaError,
RateLimitError, InvalidArgumentsError, UpstreamTimeoutError,
)
try:
result = uno.call_tool(tool, {"location": "Beijing"})
except AuthRequiredError as exc:
# The tool needs a third-party app. Send your user to exc.auth_url,
# then call again — no code change needed after they authorize.
send_to_user(exc.auth_url)
except QuotaError:
top_up() # out of credits
except RateLimitError as exc:
sleep(exc.retry_after or 60) # 120 calls/min per user
except InvalidArgumentsError as exc:
log(exc) # caught locally, no credits spent
except (AuthError, UpstreamTimeoutError) as exc:
alert(exc.code)Async, batch and long-running jobs
from uno_sdk import AsyncUno
async with AsyncUno(api_key="uno_…") as uno:
# Concurrent batch with concurrency cap & order preservation
results = await uno.call_batch([
("tikhub-douyin.fetch_video_stats", {"aweme_id": "aaa"}),
("tikhub-douyin.fetch_video_stats", {"aweme_id": "bbb"}),
], max_concurrency=10, return_exceptions=True)
# Submit + poll long-running jobs to completion (transcription, etc.)
transcript = await uno.call_async(
"qingdou-video-text.qingdou_submit",
{"urls": "https://v.douyin.com/xxx/"},
"qingdou-video-text.qingdou_result",
max_wait=180,
)Emit function-calling schemas for OpenAI / Anthropic directly:
from uno_sdk import OpenAIAdapter
functions = uno.search("weather", adapter=OpenAIAdapter())MCP Clients
Connect ChatGPT, Codex, Claude, Cursor, or any other MCP client to use all Uno tools — no code needed.
OAuth login opens automatically in your browser. After authorization, tools are available instantly.
Clients that can set headers may send Authorization: Bearer uno_… and skip OAuth entirely. For other clients see the connect page.
Agent Integration (uno-cli)
Any agent can install Uno with one sentence on the homepage, or fetch the guide:
curl -s https://agentools.uno/SKILL.mdFollow it: pip install uno-cli, then uno search / uno call. Device-code login, no raw curl.
Error Handling
| error | Meaning |
|---|---|
tool_not_found | Tool slug doesn't exist |
auth_required | Tool needs OAuth — check auth_url in response |
insufficient_credits | Out of credits — check recharge_url |
rate_limit_exceeded | Rate limit exceeded — retry after retry_after_seconds |
tool_disabled / server_disabled | Tool or server is marked inactive |
invalid_arguments | Arguments failed JSON Schema validation (client-side) |
invalid_api_key | Bearer token missing or not a valid uno_… key |
upstream_timeout / upstream_cancelled | Upstream timed out / connection cancelled — retry reads or explicitly idempotent operations only; never retry outcome_unknown writes |
Pricing
- Free: 500 credits daily, auto-reset
- Most tools: 1 credit per call
- AI generation: AI Image Generation 10–200 credits/call; GPT Image 2 is 200 credits per image; AI Video Generation 10–500 credits/call; AI Speech / Music 100–500 credits/call
- per_token pricing (LLM tools): credits = (request + response chars / 4) × token_price