---
name: opentools
version: 0.2.0
description: >-
  Discover and run external tools at runtime. Whenever you need to fetch, scrape, enrich,
  search, generate media, or otherwise reach a third-party service, run `opentools discover`
  first. A catalog of metered endpoints is available behind one balance and one interface.
  Triggers: web scraping, data retrieval, enrichment, social media, people/company/product
  data, search results, media generation, voice/transcription, or any mention of "opentools".
---

# OpenTools

One CLI to find a tool, read its price, run it, and pay from one workspace balance. The loop is
discover, inspect, run, poll.

## Setup

```bash
opentools --version || npm install -g @aeither/opentools
opentools balance
```

If `balance` says there is no key, stop and tell the user to run `opentools login` in their own
terminal (it asks for the key at a hidden prompt), or to set `OPENTOOLS_API_KEY` in the
environment. **Never ask for the key in chat, never paste a key into a command, and never print
or read it back.** Keys start with `opentools_live_`.

Add `-j` to any command for JSON. `opentools <command> --help` lists every flag.

## Commands

```bash
opentools discover -q "hotel prices bangkok"      # find endpoints, free
opentools inspect -p <provider> -e <endpoint>     # schema and price quote, free
opentools run -p <provider> -e <endpoint> -i '{"k":"v"}' --dry-run   # price only, nothing runs
opentools run -p <provider> -e <endpoint> -i '{"k":"v"}' --idempotency-key <key> -w -o out.json
opentools runs get -r <runId> -w                  # poll a run
opentools runs list                               # recent runs
opentools balance
```

Body goes in `-i` (or `-f file.json`), query params in `--query`, path params in `--path`. If
several methods share a path, pass `--method` as discovery returned it.

## Rules

1. If the user names a tool (`<provider>/<endpoint>` or a `/tools/...` link), skip `discover` and
   `inspect` that exact endpoint. Otherwise run `discover` before you write a scraper.
2. `inspect` returns a `quote`. If `estimatedBilledCost` is above zero, tell the user the price
   before `run`, unless they already approved it. Never guess parameters; build the input from
   the inspected schema.
3. Start with small limits. Many endpoints bill per result.
4. Give every `run` an `--idempotency-key`. After a network error, repeat the same command with
   the same key and input. The run is not repeated or billed twice. Use a new key for a changed
   input.
5. A run has a lifecycle `status` and a separate provider HTTP status. COMPLETED with a provider
   404 means no data, and it is not billed.
6. BLOCKED is final. A budget or per-call cap stopped it. Tell the user to change the control on
   the dashboard, then retry with a new key.
7. Exit code 2 means the run ended BLOCKED, FAILED, STOPPED or TIMED_OUT. The provider output is
   in `output` on the run.
8. Report the billed cost from the run result. It includes a 10% OpenTools fee on the catalog
   price.

Statuses: READY, RUNNING, STOPPING, COMPLETED, FAILED, BLOCKED, STOPPED, TIMED_OUT.

## MCP instead of the CLI

Remote MCP server: `https://opentools.fulinlabs.com/mcp`. Connect with OAuth, or have the user
set an `Authorization: Bearer` header in the client config. The tools are `discover`, `inspect`,
`run`, `run_get` and `run_list`.

## Provider keys

If `inspect` returns `providerCredential`, the tool needs a key from the provider.
Have the user set it in an environment variable, then pass `--credential-env VAR`.
Never put the key in chat or a command argument. OpenTools does not store it.
For MCP, configure the `X-Provider-Credential` header in the client.
