tavus-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. tavus_cli-0.1.0/.env.example +38 -0
  2. tavus_cli-0.1.0/.github/workflows/ci.yml +40 -0
  3. tavus_cli-0.1.0/.github/workflows/deploy-cloudflare-worker.yml +68 -0
  4. tavus_cli-0.1.0/.github/workflows/pr-reviews.yml +29 -0
  5. tavus_cli-0.1.0/.github/workflows/pypi-cli.yml +39 -0
  6. tavus_cli-0.1.0/.gitignore +17 -0
  7. tavus_cli-0.1.0/PKG-INFO +192 -0
  8. tavus_cli-0.1.0/README.md +172 -0
  9. tavus_cli-0.1.0/docs/gemini-enterprise/README.md +181 -0
  10. tavus_cli-0.1.0/docs/gemini-enterprise/listing.md +90 -0
  11. tavus_cli-0.1.0/docs/gemini-enterprise/test-queries.md +161 -0
  12. tavus_cli-0.1.0/pyproject.toml +47 -0
  13. tavus_cli-0.1.0/skills/tavus-agentic-personas/SKILL.md +208 -0
  14. tavus_cli-0.1.0/skills/tavus-agentic-personas/agents/openai.yaml +4 -0
  15. tavus_cli-0.1.0/skills/tavus-agentic-personas/references/build-and-verify.md +183 -0
  16. tavus_cli-0.1.0/skills/tavus-agentic-personas/references/builder-workflow.md +172 -0
  17. tavus_cli-0.1.0/skills/tavus-agentic-personas/references/chat-mode.md +313 -0
  18. tavus_cli-0.1.0/skills/tavus-agentic-personas/references/examples.md +223 -0
  19. tavus_cli-0.1.0/src/tavus_mcp/__init__.py +4 -0
  20. tavus_cli-0.1.0/src/tavus_mcp/cli/__init__.py +1 -0
  21. tavus_cli-0.1.0/src/tavus_mcp/cli/main.py +1467 -0
  22. tavus_cli-0.1.0/src/tavus_mcp/sdk/__init__.py +6 -0
  23. tavus_cli-0.1.0/src/tavus_mcp/sdk/auth/__init__.py +1 -0
  24. tavus_cli-0.1.0/src/tavus_mcp/sdk/auth/keyring_store.py +20 -0
  25. tavus_cli-0.1.0/src/tavus_mcp/sdk/auth/oauth.py +131 -0
  26. tavus_cli-0.1.0/src/tavus_mcp/sdk/auth/session.py +46 -0
  27. tavus_cli-0.1.0/src/tavus_mcp/sdk/client/__init__.py +3 -0
  28. tavus_cli-0.1.0/src/tavus_mcp/sdk/client/http.py +451 -0
  29. tavus_cli-0.1.0/src/tavus_mcp/sdk/env.py +126 -0
  30. tavus_cli-0.1.0/src/tavus_mcp/sdk/errors.py +46 -0
  31. tavus_cli-0.1.0/src/tavus_mcp/sdk/patch.py +92 -0
  32. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/__init__.py +6 -0
  33. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/build_and_verify.py +618 -0
  34. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/options.py +67 -0
  35. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/quickstart.py +48 -0
  36. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/scaffold_embed.py +115 -0
  37. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/templates.py +58 -0
  38. tavus_cli-0.1.0/src/tavus_mcp/sdk/recipes/tool_reuse.py +124 -0
  39. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/__init__.py +16 -0
  40. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/file_manifest.py +21 -0
  41. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/guardrail.py +84 -0
  42. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/objective.py +131 -0
  43. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/persona.py +174 -0
  44. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/pronunciation.py +73 -0
  45. tavus_cli-0.1.0/src/tavus_mcp/sdk/schemas/tool.py +349 -0
  46. tavus_cli-0.1.0/src/tavus_mcp/server.py +877 -0
  47. tavus_cli-0.1.0/tests/conftest.py +16 -0
  48. tavus_cli-0.1.0/tests/integration/test_cli.py +86 -0
  49. tavus_cli-0.1.0/tests/integration/test_client.py +138 -0
  50. tavus_cli-0.1.0/tests/integration/test_mcp_server.py +15 -0
  51. tavus_cli-0.1.0/tests/integration/test_oauth.py +132 -0
  52. tavus_cli-0.1.0/tests/unit/test_auth.py +42 -0
  53. tavus_cli-0.1.0/tests/unit/test_build_and_verify.py +515 -0
  54. tavus_cli-0.1.0/tests/unit/test_builder.py +155 -0
  55. tavus_cli-0.1.0/tests/unit/test_conversation_chat.py +82 -0
  56. tavus_cli-0.1.0/tests/unit/test_env.py +86 -0
  57. tavus_cli-0.1.0/tests/unit/test_guardrail_schema.py +66 -0
  58. tavus_cli-0.1.0/tests/unit/test_objective_schema.py +102 -0
  59. tavus_cli-0.1.0/tests/unit/test_patch.py +56 -0
  60. tavus_cli-0.1.0/tests/unit/test_persona_schema.py +47 -0
  61. tavus_cli-0.1.0/tests/unit/test_pronunciation_schema.py +56 -0
  62. tavus_cli-0.1.0/tests/unit/test_scaffold_embed.py +18 -0
  63. tavus_cli-0.1.0/tests/unit/test_tool_reuse.py +123 -0
  64. tavus_cli-0.1.0/tests/unit/test_tool_schema.py +214 -0
  65. tavus_cli-0.1.0/uv.lock +1542 -0
  66. tavus_cli-0.1.0/workers/tavus-mcp/.dev.vars.example +6 -0
  67. tavus_cli-0.1.0/workers/tavus-mcp/package-lock.json +5241 -0
  68. tavus_cli-0.1.0/workers/tavus-mcp/package.json +24 -0
  69. tavus_cli-0.1.0/workers/tavus-mcp/src/index.ts +58 -0
  70. tavus_cli-0.1.0/workers/tavus-mcp/src/oauth.ts +460 -0
  71. tavus_cli-0.1.0/workers/tavus-mcp/src/tavus.ts +936 -0
  72. tavus_cli-0.1.0/workers/tavus-mcp/test/tavus.test.ts +323 -0
  73. tavus_cli-0.1.0/workers/tavus-mcp/tsconfig.json +16 -0
  74. tavus_cli-0.1.0/workers/tavus-mcp/wrangler.jsonc +51 -0
@@ -0,0 +1,38 @@
1
+ # Target environment. Defaults to PROD when unset.
2
+ # Set TAVUS_ENV=TEST to use the test DB.
3
+ # Accepted values: TEST, TEST_DB, STG, PROD.
4
+ # TAVUS_ENV=TEST
5
+
6
+ # Defaults are selected from TAVUS_ENV, but explicit URLs always win.
7
+ # TEST defaults:
8
+ # TAVUS_PUBLIC_API_BASE_URL=https://test.rqh.tavusapi.com/v2
9
+ # TAVUS_PORTAL_API_BASE_URL=https://test-api.tavus.io/api
10
+ # TAVUS_DEV_PORTAL_URL=https://dev.platform.tavus.io
11
+ # STG defaults:
12
+ # TAVUS_PUBLIC_API_BASE_URL=https://stg.rqh.tavusapi.com/v2
13
+ # TAVUS_PORTAL_API_BASE_URL=https://stg-api.tavus.io/api
14
+ # TAVUS_DEV_PORTAL_URL=https://stage.platform.tavus.io
15
+ # PROD defaults:
16
+ # TAVUS_PUBLIC_API_BASE_URL=https://tavusapi.com/v2
17
+ # TAVUS_PORTAL_API_BASE_URL=https://prod-api.tavus.io/api
18
+ # TAVUS_DEV_PORTAL_URL=https://platform.tavus.io
19
+ TAVUS_PUBLIC_API_BASE_URL=
20
+ TAVUS_PORTAL_API_BASE_URL=
21
+ TAVUS_DEV_PORTAL_URL=
22
+
23
+ # Optional per-env overrides. These beat the defaults but not the generic vars above.
24
+ TAVUS_TEST_PUBLIC_API_BASE_URL=
25
+ TAVUS_TEST_PORTAL_API_BASE_URL=
26
+ TAVUS_TEST_DEV_PORTAL_URL=
27
+ TAVUS_STG_PUBLIC_API_BASE_URL=
28
+ TAVUS_STG_PORTAL_API_BASE_URL=
29
+ TAVUS_STG_DEV_PORTAL_URL=
30
+ TAVUS_PROD_PUBLIC_API_BASE_URL=
31
+ TAVUS_PROD_PORTAL_API_BASE_URL=
32
+ TAVUS_PROD_DEV_PORTAL_URL=
33
+
34
+ # Optional auth fallback. If set, it wins over keyring for the selected env.
35
+ TAVUS_API_KEY=
36
+ TAVUS_TEST_API_KEY=
37
+ TAVUS_STG_API_KEY=
38
+ TAVUS_PROD_API_KEY=
@@ -0,0 +1,40 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ lint-and-test:
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 10
17
+ strategy:
18
+ matrix:
19
+ python-version: ['3.11', '3.13']
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+ - name: Install uv
27
+ run: pip install uv
28
+ - name: Install dependencies
29
+ run: uv sync --extra dev
30
+ - name: Ruff
31
+ run: uv run ruff check .
32
+ - name: Pytest
33
+ env:
34
+ # Rich/typer reads COLUMNS to decide help-text wrap width. CI's
35
+ # default of 80 wraps option names like --limit across lines,
36
+ # which breaks substring assertions in test_cli.py.
37
+ COLUMNS: '200'
38
+ run: uv run pytest -q
39
+ - name: Build
40
+ run: uv build
@@ -0,0 +1,68 @@
1
+ name: Deploy Tavus MCP Worker
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ environment:
7
+ description: Cloudflare Worker environment to deploy
8
+ required: true
9
+ default: test
10
+ type: choice
11
+ options:
12
+ - test
13
+ - stg
14
+ - prod
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ deploy:
21
+ runs-on: ubuntu-latest
22
+ environment: ${{ inputs.environment }}
23
+ env:
24
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
25
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
26
+ CLOUDFLARE_ENV: ${{ inputs.environment }}
27
+ TAVUS_API_KEY: ${{ secrets.TAVUS_API_KEY }}
28
+ MCP_BEARER_TOKEN: ${{ secrets.MCP_BEARER_TOKEN }}
29
+ defaults:
30
+ run:
31
+ working-directory: workers/tavus-mcp
32
+
33
+ steps:
34
+ - name: Checkout
35
+ uses: actions/checkout@v4
36
+
37
+ - name: Setup Node.js
38
+ uses: actions/setup-node@v4
39
+ with:
40
+ node-version: 24
41
+ cache: npm
42
+ cache-dependency-path: workers/tavus-mcp/package-lock.json
43
+
44
+ - name: Install dependencies
45
+ run: npm ci
46
+
47
+ - name: Type-check
48
+ run: npm run build
49
+
50
+ - name: Test
51
+ run: npm run test
52
+
53
+ - name: Configure legacy shared-token fallback secrets
54
+ run: |
55
+ if [ -n "${TAVUS_API_KEY:-}" ]; then
56
+ printf '%s' "$TAVUS_API_KEY" | npx wrangler secret put TAVUS_API_KEY --env "$CLOUDFLARE_ENV"
57
+ else
58
+ echo "Skipping TAVUS_API_KEY; OAuth user bearer tokens do not require the legacy fallback."
59
+ fi
60
+
61
+ if [ -n "${MCP_BEARER_TOKEN:-}" ]; then
62
+ printf '%s' "$MCP_BEARER_TOKEN" | npx wrangler secret put MCP_BEARER_TOKEN --env "$CLOUDFLARE_ENV"
63
+ else
64
+ echo "Skipping MCP_BEARER_TOKEN; OAuth user bearer tokens do not require the legacy fallback."
65
+ fi
66
+
67
+ - name: Deploy Worker
68
+ run: npx wrangler deploy --env "$CLOUDFLARE_ENV"
@@ -0,0 +1,29 @@
1
+ name: PR Review Notifications
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, ready_for_review, closed]
6
+
7
+ permissions:
8
+ pull-requests: write
9
+ contents: read
10
+
11
+ jobs:
12
+ notify:
13
+ runs-on: ubuntu-latest
14
+ if: github.event.pull_request.user.login != 'cvi-bot[bot]'
15
+ steps:
16
+ - name: Send PR notification
17
+ uses: Tavus-Engineering/pr-changelog-action/review@main
18
+ with:
19
+ slack-bot-token: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
20
+ slack-channel-id: C0AFT2E9D5Y
21
+ github-token: ${{ secrets.GITHUB_TOKEN }}
22
+ repo: ${{ github.repository }}
23
+ pr-number: ${{ github.event.pull_request.number }}
24
+ pr-title: ${{ github.event.pull_request.title }}
25
+ pr-url: ${{ github.event.pull_request.html_url }}
26
+ pr-author: ${{ github.event.pull_request.user.login }}
27
+ pr-merged: ${{ github.event.pull_request.merged }}
28
+ pr-draft: ${{ github.event.pull_request.draft }}
29
+ event-action: ${{ github.event.action }}
@@ -0,0 +1,39 @@
1
+ name: Publish Tavus CLI to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+ id-token: write
9
+
10
+ concurrency:
11
+ group: pypi-cli
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ publish:
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 10
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+ - name: Install uv
25
+ run: pip install uv
26
+ - name: Install dependencies
27
+ run: uv sync --extra dev
28
+ - name: Ruff
29
+ run: uv run ruff check .
30
+ - name: Pytest
31
+ env:
32
+ COLUMNS: '200'
33
+ run: uv run pytest -q
34
+ - name: Build
35
+ run: |
36
+ rm -rf dist
37
+ uv build
38
+ - name: Publish
39
+ run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/
@@ -0,0 +1,17 @@
1
+ .env
2
+ .venv/
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ __pycache__/
6
+ *.py[cod]
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ node_modules/
11
+ workers/**/.dev.vars
12
+ workers/**/.wrangler/
13
+
14
+ # Claude Code local/runtime state (keep shared config in .claude/)
15
+ .claude/scheduled_tasks.lock
16
+ .claude/scheduled_tasks.json
17
+ .claude/settings.local.json
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: tavus-cli
3
+ Version: 0.1.0
4
+ Summary: Tavus CLI and MCP server for agentic persona creation and editing.
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: fastmcp>=2.0.0
7
+ Requires-Dist: httpx>=0.27.0
8
+ Requires-Dist: jsonpatch>=1.33
9
+ Requires-Dist: keyring>=25.0.0
10
+ Requires-Dist: pydantic>=2.7.0
11
+ Requires-Dist: python-dotenv>=1.0.0
12
+ Requires-Dist: rich>=13.7.0
13
+ Requires-Dist: typer>=0.12.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
16
+ Requires-Dist: pytest>=8.2.0; extra == 'dev'
17
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
18
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # tavus-cli
22
+
23
+ Agent-facing surfaces that let another agent (Claude, Codex, or any MCP-aware client) drive Tavus persona creation end-to-end — separate from the human-facing Conversational Persona Builder.
24
+
25
+ ## What's here
26
+
27
+ - **MCP server.** Persona CRUD plus mutations for tools, KB, guardrails, pronunciation dicts, layers, and objectives. Local stdio for IDE-embedded clients, remote (Cloudflare Worker) for hosted agents.
28
+ - **CLI.** Scripted persona authoring + publish. `tavus persona list / options / patch`, JSON round-tripping, OS-keychain auth.
29
+ - **Codex skill.** Publishable skill so an external agent can invoke the MCP server and CLI without reading the full Tavus API.
30
+
31
+ ## Why standalone (not under Conversational Persona Builder)
32
+
33
+ The CPB project is the **human** builder — replica-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.
34
+
35
+ ## Out of scope (for now)
36
+
37
+ - Replica/video preview surfaces (lives in CPB)
38
+ - Marketplace / sharing UX
39
+ - Multi-tenant auth beyond the existing dev-portal token model
40
+
41
+ ## Local Setup
42
+
43
+ ```bash
44
+ uv sync --extra dev
45
+ cp .env.example .env
46
+ ```
47
+
48
+ By default the CLI targets production (`PROD`). To switch to the test DB, either set
49
+ `TAVUS_ENV=TEST` in `.env` / your shell or pass `--env TEST` to the CLI. You can set
50
+ `TAVUS_API_KEY` directly for automation or run:
51
+
52
+ ```bash
53
+ uv run tavus auth login
54
+ ```
55
+
56
+ Examples:
57
+
58
+ ```bash
59
+ # Production defaults; only the API key is required.
60
+ TAVUS_API_KEY=... uv run tavus persona list
61
+
62
+ # Test DB without URL overrides.
63
+ TAVUS_ENV=TEST TAVUS_API_KEY=... uv run tavus persona list
64
+ uv run tavus --env TEST persona list
65
+ ```
66
+
67
+ The login flow opens the dev-portal at `/dev/cli-authorize` with a loopback callback URL and an
68
+ anti-CSRF state. The dev-portal mints an API key for your signed-in user (tagged `source: cli`) and
69
+ POSTs it back to the loopback receiver. The CLI stores that key in the OS keychain under the
70
+ selected environment. No Firebase config lives in the CLI — the browser side handles all of it.
71
+
72
+ ## CLI
73
+
74
+ Install the CLI from PyPI:
75
+
76
+ ```bash
77
+ uv tool install tavus-cli
78
+ ```
79
+
80
+ Or run it without installing:
81
+
82
+ ```bash
83
+ uvx --from tavus-cli tavus doctor
84
+ ```
85
+
86
+ Local development commands:
87
+
88
+ ```bash
89
+ uv run tavus doctor
90
+ uv run tavus persona list
91
+ uv run tavus persona options <persona_id>
92
+ uv run tavus persona patch <persona_id> --op replace --path /persona_name --value '"New Name"'
93
+ ```
94
+
95
+ ## MCP
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "tavus": {
101
+ "command": "uv",
102
+ "args": ["run", "--directory", "/absolute/path/to/tavus-mcp", "tavus-mcp"]
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ MCP tools return data and file manifests. They do not write files.
109
+
110
+ ## Cloudflare Worker
111
+
112
+ The remote MCP server lives in `workers/tavus-mcp/` and uses Cloudflare's
113
+ stateless `createMcpHandler` transport at `/mcp`.
114
+
115
+ ```bash
116
+ cd workers/tavus-mcp
117
+ npm install
118
+ cp .dev.vars.example .dev.vars
119
+ npm run dev
120
+ ```
121
+
122
+ The local remote-MCP endpoint is `http://127.0.0.1:8787/mcp`.
123
+
124
+ ### Hosted remote MCP
125
+
126
+ Hosted remote MCP clients should point directly at the HTTPS `/mcp` URL. Do not
127
+ put a Tavus API key or shared bearer token in client config. The Worker exposes
128
+ standard OAuth metadata, dynamic client registration, authorize, and token
129
+ endpoints so MCP clients can authenticate through Tavus browser auth.
130
+
131
+ Claude Code example:
132
+
133
+ ```bash
134
+ claude mcp add -s user --transport http tavus https://mcp.tavus-preview.io/mcp
135
+ ```
136
+
137
+ The OAuth authorize step redirects to Tavus developer portal
138
+ `/dev/cli-authorize?mode=oauth`. After the user signs in, the portal mints a
139
+ per-user Tavus API key and redirects back to the MCP client's loopback callback.
140
+ The Worker exchanges that code for an MCP bearer token, then forwards the bearer
141
+ to RQH as `x-api-key`. This keeps Tavus API keys user-scoped and out of MCP
142
+ client configuration.
143
+
144
+ Developer portal must support the `mode=oauth` authorize flow for remote MCP
145
+ auth to complete. If a local portal is running on port 3000, test the full
146
+ browser-auth path against TEST with:
147
+
148
+ ```bash
149
+ cd workers/tavus-mcp
150
+ npm run dev -- --env test --var TAVUS_DEV_PORTAL_URL:http://localhost:3000
151
+
152
+ claude mcp add -s user --transport http tavus-dev http://127.0.0.1:8787/mcp
153
+ ```
154
+
155
+ Keep the Worker environment aligned with the portal environment that minted the
156
+ key. For example, a TEST key from a local or dev portal must hit a Worker running
157
+ with `--env test`, otherwise downstream Tavus API calls will return 401.
158
+
159
+ For Tavus deployment, configure these Cloudflare/GitHub environment secrets:
160
+
161
+ - `CLOUDFLARE_API_TOKEN`
162
+ - `CLOUDFLARE_ACCOUNT_ID`
163
+ - `TAVUS_API_KEY` and `MCP_BEARER_TOKEN` only if you need the legacy shared-token fallback
164
+
165
+ Then run the `Deploy Tavus MCP Worker` workflow for `test`, `stg`, or `prod`.
166
+ The `prod` Wrangler route is configured as a custom domain on `mcp.tavus.io`;
167
+ use `https://mcp.tavus-preview.io/mcp` as the Cloudflare-owned endpoint until
168
+ `mcp.tavus.io` DNS resolves.
169
+ For direct Wrangler usage, the default config targets production; use
170
+ `wrangler deploy --env test` or `wrangler dev --env test` to point at TEST.
171
+
172
+ Useful production checks:
173
+
174
+ ```bash
175
+ curl https://mcp.tavus-preview.io/.well-known/oauth-protected-resource/mcp
176
+ curl https://mcp.tavus-preview.io/.well-known/oauth-authorization-server
177
+ curl -i https://mcp.tavus-preview.io/mcp
178
+ ```
179
+
180
+ Unauthenticated `/mcp` should return `401` with a `WWW-Authenticate` header that
181
+ points at the protected-resource metadata URL. A `404 Not Found` at discovery
182
+ usually means the Worker version serving the custom domain does not include the
183
+ OAuth routes yet.
184
+
185
+ ## Codex Skill
186
+
187
+ A publishable Codex skill for this repo lives at `skills/tavus-agentic-personas/`.
188
+ It documents the CLI and MCP workflows, safe persona patching, environment setup,
189
+ and concrete examples for agents using this toolkit.
190
+
191
+ Install it by copying that folder into `${CODEX_HOME:-$HOME/.codex}/skills/`, or
192
+ publish the folder directly through whatever skill distribution flow you use.
@@ -0,0 +1,172 @@
1
+ # tavus-cli
2
+
3
+ Agent-facing surfaces that let another agent (Claude, Codex, or any MCP-aware client) drive Tavus persona creation end-to-end — separate from the human-facing Conversational Persona Builder.
4
+
5
+ ## What's here
6
+
7
+ - **MCP server.** Persona CRUD plus mutations for tools, KB, guardrails, pronunciation dicts, layers, and objectives. Local stdio for IDE-embedded clients, remote (Cloudflare Worker) for hosted agents.
8
+ - **CLI.** Scripted persona authoring + publish. `tavus persona list / options / patch`, JSON round-tripping, OS-keychain auth.
9
+ - **Codex skill.** Publishable skill so an external agent can invoke the MCP server and CLI without reading the full Tavus API.
10
+
11
+ ## Why standalone (not under Conversational Persona Builder)
12
+
13
+ The CPB project is the **human** builder — replica-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.
14
+
15
+ ## Out of scope (for now)
16
+
17
+ - Replica/video preview surfaces (lives in CPB)
18
+ - Marketplace / sharing UX
19
+ - Multi-tenant auth beyond the existing dev-portal token model
20
+
21
+ ## Local Setup
22
+
23
+ ```bash
24
+ uv sync --extra dev
25
+ cp .env.example .env
26
+ ```
27
+
28
+ By default the CLI targets production (`PROD`). To switch to the test DB, either set
29
+ `TAVUS_ENV=TEST` in `.env` / your shell or pass `--env TEST` to the CLI. You can set
30
+ `TAVUS_API_KEY` directly for automation or run:
31
+
32
+ ```bash
33
+ uv run tavus auth login
34
+ ```
35
+
36
+ Examples:
37
+
38
+ ```bash
39
+ # Production defaults; only the API key is required.
40
+ TAVUS_API_KEY=... uv run tavus persona list
41
+
42
+ # Test DB without URL overrides.
43
+ TAVUS_ENV=TEST TAVUS_API_KEY=... uv run tavus persona list
44
+ uv run tavus --env TEST persona list
45
+ ```
46
+
47
+ The login flow opens the dev-portal at `/dev/cli-authorize` with a loopback callback URL and an
48
+ anti-CSRF state. The dev-portal mints an API key for your signed-in user (tagged `source: cli`) and
49
+ POSTs it back to the loopback receiver. The CLI stores that key in the OS keychain under the
50
+ selected environment. No Firebase config lives in the CLI — the browser side handles all of it.
51
+
52
+ ## CLI
53
+
54
+ Install the CLI from PyPI:
55
+
56
+ ```bash
57
+ uv tool install tavus-cli
58
+ ```
59
+
60
+ Or run it without installing:
61
+
62
+ ```bash
63
+ uvx --from tavus-cli tavus doctor
64
+ ```
65
+
66
+ Local development commands:
67
+
68
+ ```bash
69
+ uv run tavus doctor
70
+ uv run tavus persona list
71
+ uv run tavus persona options <persona_id>
72
+ uv run tavus persona patch <persona_id> --op replace --path /persona_name --value '"New Name"'
73
+ ```
74
+
75
+ ## MCP
76
+
77
+ ```json
78
+ {
79
+ "mcpServers": {
80
+ "tavus": {
81
+ "command": "uv",
82
+ "args": ["run", "--directory", "/absolute/path/to/tavus-mcp", "tavus-mcp"]
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ MCP tools return data and file manifests. They do not write files.
89
+
90
+ ## Cloudflare Worker
91
+
92
+ The remote MCP server lives in `workers/tavus-mcp/` and uses Cloudflare's
93
+ stateless `createMcpHandler` transport at `/mcp`.
94
+
95
+ ```bash
96
+ cd workers/tavus-mcp
97
+ npm install
98
+ cp .dev.vars.example .dev.vars
99
+ npm run dev
100
+ ```
101
+
102
+ The local remote-MCP endpoint is `http://127.0.0.1:8787/mcp`.
103
+
104
+ ### Hosted remote MCP
105
+
106
+ Hosted remote MCP clients should point directly at the HTTPS `/mcp` URL. Do not
107
+ put a Tavus API key or shared bearer token in client config. The Worker exposes
108
+ standard OAuth metadata, dynamic client registration, authorize, and token
109
+ endpoints so MCP clients can authenticate through Tavus browser auth.
110
+
111
+ Claude Code example:
112
+
113
+ ```bash
114
+ claude mcp add -s user --transport http tavus https://mcp.tavus-preview.io/mcp
115
+ ```
116
+
117
+ The OAuth authorize step redirects to Tavus developer portal
118
+ `/dev/cli-authorize?mode=oauth`. After the user signs in, the portal mints a
119
+ per-user Tavus API key and redirects back to the MCP client's loopback callback.
120
+ The Worker exchanges that code for an MCP bearer token, then forwards the bearer
121
+ to RQH as `x-api-key`. This keeps Tavus API keys user-scoped and out of MCP
122
+ client configuration.
123
+
124
+ Developer portal must support the `mode=oauth` authorize flow for remote MCP
125
+ auth to complete. If a local portal is running on port 3000, test the full
126
+ browser-auth path against TEST with:
127
+
128
+ ```bash
129
+ cd workers/tavus-mcp
130
+ npm run dev -- --env test --var TAVUS_DEV_PORTAL_URL:http://localhost:3000
131
+
132
+ claude mcp add -s user --transport http tavus-dev http://127.0.0.1:8787/mcp
133
+ ```
134
+
135
+ Keep the Worker environment aligned with the portal environment that minted the
136
+ key. For example, a TEST key from a local or dev portal must hit a Worker running
137
+ with `--env test`, otherwise downstream Tavus API calls will return 401.
138
+
139
+ For Tavus deployment, configure these Cloudflare/GitHub environment secrets:
140
+
141
+ - `CLOUDFLARE_API_TOKEN`
142
+ - `CLOUDFLARE_ACCOUNT_ID`
143
+ - `TAVUS_API_KEY` and `MCP_BEARER_TOKEN` only if you need the legacy shared-token fallback
144
+
145
+ Then run the `Deploy Tavus MCP Worker` workflow for `test`, `stg`, or `prod`.
146
+ The `prod` Wrangler route is configured as a custom domain on `mcp.tavus.io`;
147
+ use `https://mcp.tavus-preview.io/mcp` as the Cloudflare-owned endpoint until
148
+ `mcp.tavus.io` DNS resolves.
149
+ For direct Wrangler usage, the default config targets production; use
150
+ `wrangler deploy --env test` or `wrangler dev --env test` to point at TEST.
151
+
152
+ Useful production checks:
153
+
154
+ ```bash
155
+ curl https://mcp.tavus-preview.io/.well-known/oauth-protected-resource/mcp
156
+ curl https://mcp.tavus-preview.io/.well-known/oauth-authorization-server
157
+ curl -i https://mcp.tavus-preview.io/mcp
158
+ ```
159
+
160
+ Unauthenticated `/mcp` should return `401` with a `WWW-Authenticate` header that
161
+ points at the protected-resource metadata URL. A `404 Not Found` at discovery
162
+ usually means the Worker version serving the custom domain does not include the
163
+ OAuth routes yet.
164
+
165
+ ## Codex Skill
166
+
167
+ A publishable Codex skill for this repo lives at `skills/tavus-agentic-personas/`.
168
+ It documents the CLI and MCP workflows, safe persona patching, environment setup,
169
+ and concrete examples for agents using this toolkit.
170
+
171
+ Install it by copying that folder into `${CODEX_HOME:-$HOME/.codex}/skills/`, or
172
+ publish the folder directly through whatever skill distribution flow you use.