Metadata-Version: 2.5
Name: tavus-cli
Version: 0.3.4
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 & MCP

Agent-facing surfaces for building and managing Tavus PALs. PAL Maker is the
human, in-product builder; this toolkit lets an agent (Claude, Codex, or any
MCP-aware client) drive the same platform through the API:

- **MCP server.** The full PAL surface as MCP tools: the guided build
  (`tavus_pal_build_and_verify`), chat-mode text testing, and CRUD for PALs,
  tools, knowledge, guardrails, objectives, pronunciation dictionaries,
  capabilities, faces, and voices. Run it locally over stdio, or connect to
  the hosted server at `https://mcp.tavus.io/mcp`.
- **`tavus` CLI.** The same surface as shell commands, published to PyPI as
  [`tavus-cli`](https://pypi.org/project/tavus-cli/). Scripted PAL authoring
  and publishing, JSON round-tripping, browser login with OS-keychain storage.
- **Codex skill.** A publishable skill in `skills/tavus-agentic-pals/` that
  teaches an external agent both surfaces without reading the full Tavus API.

The Tavus API exposes `/v2/pals` and `/v2/faces` as backwards-compatible
aliases over `/v2/personas` and `/v2/replicas`. Everything in this repo speaks
the pal/face vocabulary.

## Hosted MCP server

The fastest way to use this toolkit is the hosted connector. Point any
MCP client at `https://mcp.tavus.io/mcp`:

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

Claude.ai and ChatGPT custom connectors use the same URL. Do not put a Tavus
API key or shared bearer token in client config: the Worker exposes standard
OAuth metadata and dynamic client registration, so the client sends you
through Tavus browser sign-in. The developer portal mints a per-user API key
that stays server-side, scoped to your account. Claude and ChatGPT callback
URLs are accepted automatically; other hosted clients must be registered
through `MCP_OAUTH_CLIENTS`.

## Local MCP server

For IDE-embedded clients, run the stdio server from a checkout:

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

Or from PyPI without a checkout: `uvx --from 'tavus-cli[daily]' tavus-mcp`.

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

## Building a PAL

The standard way to build a PAL is `tavus_pal_build_and_verify` (MCP) or
`tavus pal build` (CLI). It runs the guided PAL Maker build: it creates the
artifact set (sectioned system prompt, objectives, guardrails, and greeting),
publishes the PAL, selects a face, runs a CVI chat smoke test, and returns a
judge verdict. Creation responses include `pal_url`, a direct link to the PAL
Maker editor for that environment (`maker.tavus.io` in production).

The transport differs by surface. The CLI and local MCP server drive the
builder conversation by joining its Daily room from your machine, which needs
the `daily` extra (see Setup below). On the hosted connector, the calling
agent interviews the creator itself, then passes the transcript and artifact
briefs to the Worker, which runs the rest of the flow over Tavus HTTP
endpoints. `tavus_chat_turn` works the same way on both surfaces: Daily
locally, the Tavus HTTP bridge when hosted.

Defaults and constraints:

- Full-pipeline builds default to the `tavus-gemma-4` model 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 rejected by both the MCP server and the CLI.
- Reserve raw `tavus_pal_create` for deliberate low-level use.

## CLI

Install from PyPI, or run without installing:

```bash
uv tool install tavus-cli
uvx --from tavus-cli tavus doctor
```

Sign in with `tavus auth login`. It opens the developer portal at
`/dev/cli-authorize` with a loopback callback; the portal mints an API key for
your signed-in user and the CLI stores it in the OS keychain, per environment.
For automation, set `TAVUS_API_KEY` instead — it wins over the keychain.

Command groups:

| Command | What it covers |
| --- | --- |
| `tavus pal` | `list`, `get`, `create`, `patch`, `delete`, `options`, `paths`, `build`, `preview`, plus `tools`, `skills`, `capabilities`, and `knowledge` subgroups |
| `tavus chat` | `start`, `turn`, `end` — drive a PAL through text, no video rendering |
| `tavus builder` | builder-session administration: `create`, `list`, `get`, `history`, `append-messages`, `publish`, `delete` |
| `tavus document` | Knowledge documents: `list`, `get`, `create`, `upload`, `tags`, `chunks`, `recrawl` |
| `tavus guardrail`, `tavus objective`, `tavus tool`, `tavus pronunciation-dictionary` | CRUD for each resource |
| `tavus face`, `tavus resource`, `tavus skill` | account resource discovery |
| `tavus conversation` | create or end CVI conversations |
| `tavus auth`, `tavus doctor`, `tavus quickstart`, `tavus embed` | login, environment checks, one-call PAL + conversation, embed scaffolding |

Examples:

```bash
tavus doctor
tavus pal build --prompt "A patient SQL tutor for junior analysts" --json
tavus chat start --pal-id p123
tavus chat turn c123 --message "What can you help me with?"
tavus chat end c123
tavus pal list
tavus pal options <pal_id>
tavus pal patch <pal_id> --op replace --path /pal_name --value '"New Name"'
tavus pal capabilities list <pal_id>
tavus pal capabilities attach <pal_id> web_search
tavus pal capabilities attach <pal_id> slide_presenter --document-id <document_id> --slides-trigger walk_the_deck
tavus document create --url https://example.com/handbook.pdf --tag onboarding
tavus pal knowledge add <pal_id> --document-id <document_id>
```

`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`). All but
Perception map to platform PAL skills; Perception maps to
`layers.perception`.

`document` and `pal knowledge` mirror PAL Maker's Knowledge section. With a
normal Tavus API key you can create Knowledge documents from any reachable
URL. Uploading a local file (`tavus document upload`, `tavus pal knowledge
upload`) uses the same portal-only flow as PAL Maker, so it also requires
`TAVUS_PORTAL_BEARER_TOKEN` (a Firebase ID token). PAL Knowledge attachment
uses `document_ids` and `document_tags`; RAG tuning lives under
`layers.knowledge_base`.

## Environments

The CLI and local MCP server target production (`PROD`) by default. Switch
with `TAVUS_ENV=TEST` (or `STG`) in `.env` / your shell, or `--env TEST` on
the CLI:

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

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

`.env.example` documents the per-environment URL defaults and the optional
overrides (`TAVUS_PUBLIC_API_BASE_URL`, `TAVUS_PAL_MAKER_URL`, and friends).
Explicit URLs always win over the environment defaults.

## Codex skill

A publishable Codex skill lives at `skills/tavus-agentic-pals/`. It documents
the CLI and MCP workflows, safe PAL patching, environment setup, and concrete
examples. Install it by copying the folder into
`${CODEX_HOME:-$HOME/.codex}/skills/`, or publish it through your own skill
distribution flow.

## Development

### Setup

```bash
uv sync --extra dev
cp .env.example .env
uv run tavus doctor --skip-network
```

Chat mode and the guided build join the conversation's Daily room from this
machine, which needs the `daily` extra:

```bash
uv sync --extra dev --extra daily
```

`uv sync` installs only the extras named on that run, so list every extra you
need together. daily-python ships macOS/Linux wheels only. The hosted
connector uses the Tavus HTTP bridge and does not need a local Daily client.

Checks, all run by CI on every pull request:

```bash
uv run ruff check .
uv run pytest -q
cd workers/tavus-mcp && npm run build && npm test
```

### Worker development

The hosted MCP server is a Cloudflare Worker in `workers/tavus-mcp/`
(configured in `wrangler.jsonc`) using the stateless `createMcpHandler`
transport at `/mcp`.

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

The local endpoint is `http://127.0.0.1:8787/mcp`. To test the full
browser-auth path against TEST with a local developer portal on port 3000:

```bash
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: a TEST key must hit a Worker running with `--env test`, otherwise
downstream Tavus API calls return 401. Direct Wrangler commands default to
production; use `--env test` to point at TEST.

| Environment | 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` |

The public endpoint is always `https://mcp.tavus.io/mcp`.
`mcp.tavus-preview.io` belongs only to the `stg` Worker and must not be
published as a production fallback.

### How hosted OAuth works

The authorize step redirects to the developer portal at
`/dev/cli-authorize?mode=oauth`. The portal verifies the Worker's signed
request, shows the connector destination, and after sign-in posts a per-user
API key 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
the Tavus API as `x-api-key`. A SQLite-backed Durable Object makes both the
authorization request and the code one-time to prevent replay. Tavus API keys
stay user-scoped and never appear in MCP client configuration or browser
callback URLs.

### Local and hosted parity

Every remotely usable Tavus feature must land in the Python MCP server/CLI
and the hosted Worker in the same change. A parity test compares both tool
manifests and fails CI when a new difference is not explicitly classified.
The current documented exceptions are local-file uploads, the builder-session
administration tools, and two tools that keep backward-compatible local names
(`tavus_pal_capability_catalog` / `tavus_pal_knowledge_settings_patch`
locally; `tavus_pal_capabilities_catalog` / `tavus_pal_knowledge_settings`
hosted).

### Deploys and releases

Merges to `main` automatically build, test, deploy, and smoke-test the `stg`
Worker. The deploy workflow can also target `test` or `stg` manually; it
cannot deploy production. After a feature merge, confirm the staging
connector still completes a real OAuth login and the feature's
write/read/cleanup cycle; repeat that smoke test at `mcp.tavus.io` after the
release ships.

Release Please keeps one version for the CLI and the hosted Worker. It opens
or updates a release pull request after each non-release merge to `main`.
Merging that pull request creates the GitHub release and starts the release
workflow, which validates the tag (versions consistent across both packages,
only release files changed, parent commit successfully staged), builds both
deliverables from the exact tag, and waits for the `prod` environment
approval. One approved job then deploys the Worker, smoke-tests
`https://mcp.tavus.io`, and publishes the same version of `tavus-cli` to
PyPI. A manual release run accepts only an existing GitHub release tag and is
the recovery path for a failed production job.

Secrets:

- GitHub environment secrets `CLOUDFLARE_API_TOKEN` and
  `CLOUDFLARE_ACCOUNT_ID` for each deployable environment (`test`, `stg`,
  `prod`).
- Worker runtime secrets are set with
  `npx wrangler secret put <NAME> --env <environment>` and persist across
  deploys; the workflows never read or overwrite them. Every deployed
  environment needs `MCP_OAUTH_SIGNING_SECRET` (random, at least 32
  characters, different per environment, never committed). The legacy
  `TAVUS_API_KEY` / `MCP_BEARER_TOKEN` fallback is also a runtime secret.

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
pointing at the protected-resource metadata URL. A `404` at discovery usually
means the Worker serving the domain predates the OAuth routes.

### More docs

- `docs/usage-observability.md` — how MCP and CLI API usage is attributed
  and observed.
- `docs/gemini-enterprise/` — Gemini Enterprise marketplace listing copy.
