Metadata-Version: 2.5
Name: tavus-cli
Version: 0.3.3
Summary: Tavus CLI and MCP server for agentic PAL creation and editing.
Requires-Python: >=3.11
Requires-Dist: fastmcp>=2.0.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: jsonpatch>=1.33
Requires-Dist: keyring>=25.0.0
Requires-Dist: pydantic>=2.7.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: rich>=13.7.0
Requires-Dist: typer>=0.12.0
Provides-Extra: daily
Requires-Dist: daily-python>=0.31.0; extra == 'daily'
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.2.0; extra == 'dev'
Requires-Dist: respx>=0.21.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Description-Content-Type: text/markdown

# tavus-cli

Agent-facing surfaces that let another agent (Claude, Codex, or any MCP-aware client) drive Tavus PAL creation end-to-end — separate from the human-facing PAL Maker.

## What's here

- **MCP server.** PAL CRUD plus mutations for tools, KB, guardrails, pronunciation dicts, layers, and objectives. Local stdio for IDE-embedded clients, remote (Cloudflare Worker) for hosted agents.
- **CLI.** Scripted PAL authoring + publish. `tavus pal list / options / patch`, JSON round-tripping, OS-keychain auth.
- **Codex skill.** Publishable skill so an external agent can invoke the MCP server and CLI without reading the full Tavus API.

## Why standalone (not under PAL Maker)

The PAL Maker project is the **human** builder — face-driven, in-product. This repo is for **agents driving the API** without that UI. Adjacent in code and concepts, but a different deliverable and audience.

> The Tavus API exposes `/v2/pals` and `/v2/faces` as backwards-compatible
> vocabulary aliases over `/v2/personas` and `/v2/replicas`. This toolkit speaks
> the new pal/face vocabulary throughout.

## Out of scope (for now)

- Marketplace / sharing UX
- Multi-tenant auth beyond the existing dev-portal token model
- Deploying customer applications or infrastructure

## Local Setup

```bash
uv sync --extra dev
cp .env.example .env
```

By default the CLI targets production (`PROD`). To switch to the test DB, either set
`TAVUS_ENV=TEST` in `.env` / your shell or pass `--env TEST` to the CLI. You can set
`TAVUS_API_KEY` directly for automation or run:

```bash
uv run tavus auth login
```

Examples:

```bash
# Production defaults; only the API key is required.
TAVUS_API_KEY=... uv run tavus pal list

# Test DB without URL overrides.
TAVUS_ENV=TEST TAVUS_API_KEY=... uv run tavus pal list
uv run tavus --env TEST pal list
```

PAL creation responses include `pal_url`, a direct link to the matching
`dev.maker.tavus.io`, `stage.maker.tavus.io`, or `maker.tavus.io` editor.
Set `TAVUS_PAL_MAKER_URL` (or its environment-specific variant) only when a
custom PAL Maker deployment should override that default.

The login flow opens the dev-portal at `/dev/cli-authorize` with a loopback callback URL and an
anti-CSRF state. The dev-portal mints an API key for your signed-in user (tagged `source: cli`) and
POSTs it back to the loopback receiver. The CLI stores that key in the OS keychain under the
selected environment. No Firebase config lives in the CLI — the browser side handles all of it.

## CLI

Install the CLI from PyPI:

```bash
uv tool install tavus-cli
```

Or run it without installing:

```bash
uvx --from tavus-cli tavus doctor
```

Local development commands:

```bash
uv run tavus doctor
uv run tavus pal list
uv run tavus pal options <pal_id>
uv run tavus pal patch <pal_id> --op replace --path /pal_name --value '"New Name"'
uv run tavus pal capabilities list <pal_id>
uv run tavus pal capabilities attach <pal_id> web_search
uv run tavus pal capabilities attach <pal_id> slide_presenter --document-id <document_id> --slides-trigger walk_the_deck
uv run tavus document create --url https://example.com/handbook.pdf --tag onboarding
TAVUS_PORTAL_BEARER_TOKEN=<firebase-id-token> uv run tavus document upload ./handbook.pdf --tag onboarding
uv run tavus pal knowledge add <pal_id> --document-id <document_id>
TAVUS_PORTAL_BEARER_TOKEN=<firebase-id-token> uv run tavus pal knowledge upload <pal_id> ./handbook.pdf
```

`pal capabilities` mirrors PAL Maker's built-in capability surface:
Magic Canvas (`magic_canvas`), Slide Presenter (`slide_presenter`), Web Search
(`web_search`), Perception (`perception`), and Memory (`memory`). The first,
second, third, and fifth map to RQH PAL skills; Perception maps to
`layers.perception`.

`document` and `pal knowledge` mirror PAL Maker's Knowledge section. With a
normal Tavus API key, create Knowledge documents from an already reachable URL
via RQH `/v2/documents`. Local file upload uses the same portal-only flow as
PAL Maker (local file -> tavus-api upload/S3 URL -> RQH document record), so it
requires `TAVUS_PORTAL_BEARER_TOKEN`. PAL Knowledge attachment uses
`document_ids` and `document_tags`; RAG tuning lives under
`layers.knowledge_base`.

## MCP

```json
{
  "mcpServers": {
    "tavus": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/tavus-mcp", "tavus-mcp"]
    }
  }
}
```

MCP tools return data and file manifests. They do not write files.

Full-pipeline PAL creation defaults to `tavus-gemma-4` with speculative
inference enabled. Tools are first-class
`/v2/tools` resources and attach through top-level `tool_ids` or
`tavus_pal_tools_attach`; inline `layers.llm.tools` and perception tool arrays
are not accepted by the MCP or CLI. `tavus_voice_list` exposes new stock Voice
releases directly instead of requiring callers to discover the generic
`tavus_resource_list` form.

## Cloudflare Worker

The remote MCP server lives in `workers/tavus-mcp/` and uses Cloudflare's
stateless `createMcpHandler` transport at `/mcp`.

```bash
cd workers/tavus-mcp
npm install
cp .dev.vars.example .dev.vars
npm run dev
```

The local remote-MCP endpoint is `http://127.0.0.1:8787/mcp`.

### Hosted remote MCP

Hosted remote MCP clients should point directly at the HTTPS `/mcp` URL. Do not
put a Tavus API key or shared bearer token in client config. The Worker exposes
standard OAuth metadata, dynamic client registration, authorize, and token
endpoints so MCP clients can authenticate through Tavus browser auth.

Claude Code example:

```bash
claude mcp add -s user --transport http tavus https://mcp.tavus.io/mcp
```

Claude.ai and ChatGPT custom connectors use the same URL:
`https://mcp.tavus.io/mcp`. Their remote HTTPS OAuth callback URLs are accepted
through dynamic client registration. The Worker accepts only the documented
Claude and ChatGPT callback shapes; other hosted clients must be explicitly
registered with `MCP_OAUTH_CLIENTS`. No manually copied OAuth client ID is
required for Claude or ChatGPT.

The OAuth authorize step redirects to Tavus developer portal
`/dev/cli-authorize?mode=oauth`. After the user signs in, the portal mints a
per-user Tavus API key and returns it to the Worker's trusted
`/oauth/callback`. The Worker issues an opaque, short-lived authorization code,
verifies PKCE plus the client, redirect, and MCP resource at `/token`, then
forwards the resulting bearer to RQH as `x-api-key`. This keeps Tavus API keys
user-scoped and out of MCP client configuration and browser callback URLs.
The portal first verifies the Worker's signed request, posts the API key only to
the callback for the matching environment, and shows the final connector
destination before the user authorizes it. A SQLite-backed Durable Object makes
both the authorization request and code one-time to prevent replay.

Developer portal must support the `mode=oauth` authorize flow for remote MCP
auth to complete. If a local portal is running on port 3000, test the full
browser-auth path against TEST with:

```bash
cd workers/tavus-mcp
npm run dev -- --env test --var TAVUS_DEV_PORTAL_URL:http://localhost:3000

claude mcp add -s user --transport http tavus-dev http://127.0.0.1:8787/mcp
```

Keep the Worker environment aligned with the portal environment that minted the
key. For example, a TEST key from a local or dev portal must hit a Worker running
with `--env test`, otherwise downstream Tavus API calls will return 401.

For Tavus deployment, configure these GitHub environment secrets for each
deployable environment (`test`, `stg`, `prod`):

- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`

Worker runtime secrets, such as the legacy `TAVUS_API_KEY` or
`MCP_BEARER_TOKEN` fallback, should be set in Cloudflare with
`wrangler secret put <NAME> --env <environment>`. They persist across deploys;
the GitHub workflow does not read or overwrite them.

Remote OAuth also requires a random secret of at least 32 characters in every
deployed Worker environment:

```bash
npx wrangler secret put MCP_OAUTH_SIGNING_SECRET --env stg
npx wrangler secret put MCP_OAUTH_SIGNING_SECRET --env prod
```

Use different values in staging and production. Do not store either value in
Git or a Wrangler vars block.

Merges to `main` automatically run the `Deploy Tavus MCP Worker` workflow for
`prod`. You can also run the workflow manually for `test`, `stg`, or `prod`.
The public MCP endpoint is always `https://mcp.tavus.io/mcp`. The
`mcp.tavus-preview.io` custom domain belongs only to the `stg` Worker and must
not be published as a production fallback.

| Deployment | Worker | Hosted endpoint | Tavus API |
| --- | --- | --- | --- |
| `test` | `tavus-mcp-test` | Workers.dev URL | `https://test.rqh.tavusapi.com/v2` |
| `stg` | `tavus-mcp-stg` | `https://mcp.tavus-preview.io/mcp` | `https://stg.rqh.tavusapi.com/v2` |
| `prod` | `tavus-mcp-prod` | `https://mcp.tavus.io/mcp` | `https://tavusapi.com/v2` |

For direct Wrangler usage, the default config targets production; use
`wrangler deploy --env test` or `wrangler dev --env test` to point at TEST.

Useful production checks:

```bash
curl https://mcp.tavus.io/.well-known/oauth-protected-resource/mcp
curl https://mcp.tavus.io/.well-known/oauth-authorization-server
curl -i https://mcp.tavus.io/mcp
```

Unauthenticated `/mcp` should return `401` with a `WWW-Authenticate` header that
points at the protected-resource metadata URL. A `404 Not Found` at discovery
usually means the Worker version serving the custom domain does not include the
OAuth routes yet.

### Keeping local and hosted MCP current

Every remotely usable Tavus feature must be added to the Python MCP/CLI and the
hosted Worker in the same change. The Worker parity test compares both tool
manifests and fails CI when a new difference is not explicitly classified.
Local-file uploads and the legacy Builder flow are the current documented
exceptions.

For each feature release:

1. Add or update the local SDK/MCP/CLI contract and the hosted Worker tool.
2. Add schema and transport tests, including the hosted tool name in the parity
   test automatically by registering it in `tavus.ts`.
3. Run `uv run ruff check .`, `uv run pytest -q`, `npm run build`, and
   `npm test`. CI runs both Python and Worker suites on every PR.
4. Deploy and test `mcp.tavus-preview.io/mcp` first, including a real connector
   OAuth login and the feature's write/read/cleanup cycle.
5. Merge to deploy production, then repeat the connector and MCP tool smoke test
   at `mcp.tavus.io/mcp`.

## Codex Skill

A publishable Codex skill for this repo lives at `skills/tavus-agentic-pals/`.
It documents the CLI and MCP workflows, safe PAL patching, environment setup,
and concrete examples for agents using this toolkit.

Install it by copying that folder into `${CODEX_HOME:-$HOME/.codex}/skills/`, or
publish the folder directly through whatever skill distribution flow you use.
