tavus-cli 0.5.0__tar.gz → 0.7.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 (109) hide show
  1. tavus_cli-0.7.0/.agents/plugins/marketplace.json +12 -0
  2. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/ci.yml +9 -0
  3. tavus_cli-0.7.0/.release-please-manifest.json +3 -0
  4. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/CHANGELOG.md +19 -0
  5. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/PKG-INFO +33 -9
  6. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/README.md +32 -8
  7. tavus_cli-0.7.0/docs/chatgpt-plugin.md +165 -0
  8. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/packages/tavus/pyproject.toml +2 -2
  9. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/packages/tavus-mcp/pyproject.toml +2 -2
  10. tavus_cli-0.7.0/plugins/tavus-pal/assets/icon-dark.svg +4 -0
  11. tavus_cli-0.7.0/plugins/tavus-pal/assets/icon.svg +4 -0
  12. tavus_cli-0.7.0/plugins/tavus-pal/mcp.json +9 -0
  13. tavus_cli-0.7.0/plugins/tavus-pal/plugin.json +45 -0
  14. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/pyproject.toml +1 -1
  15. tavus_cli-0.7.0/scripts/build_chatgpt_plugin.py +46 -0
  16. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/__init__.py +1 -1
  17. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/server.py +9 -2
  18. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/integration/test_mcp_server.py +17 -0
  19. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/uv.lock +2 -2
  20. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/package-lock.json +4 -2
  21. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/package.json +3 -1
  22. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/index.ts +8 -6
  23. tavus_cli-0.7.0/workers/tavus-mcp/src/oauth-session.ts +151 -0
  24. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/oauth.ts +141 -70
  25. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/tavus.ts +34 -36
  26. tavus_cli-0.7.0/workers/tavus-mcp/src/version.ts +1 -0
  27. tavus_cli-0.7.0/workers/tavus-mcp/test/oauth-session.test.ts +362 -0
  28. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/test/tavus.test.ts +62 -59
  29. tavus_cli-0.7.0/workers/tavus-mcp/test/worker-runtime.ts +41 -0
  30. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/wrangler.jsonc +10 -5
  31. tavus_cli-0.5.0/.release-please-manifest.json +0 -3
  32. tavus_cli-0.5.0/workers/tavus-mcp/src/version.ts +0 -1
  33. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.env.example +0 -0
  34. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/deploy-cloudflare-worker.yml +0 -0
  35. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/pr-reviews.yml +0 -0
  36. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/pypi-cli.yml +0 -0
  37. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/tail-cloudflare-worker.yml +0 -0
  38. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.github/workflows/validate-staging-deployment.yml +0 -0
  39. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/.gitignore +0 -0
  40. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/AGENTS.md +0 -0
  41. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/README.md +0 -0
  42. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/listing.md +0 -0
  43. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/test-queries.md +0 -0
  44. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/docs/usage-observability.md +0 -0
  45. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/packages/tavus/README.md +0 -0
  46. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/packages/tavus-mcp/README.md +0 -0
  47. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/release-please-config.json +0 -0
  48. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/scripts/__init__.py +0 -0
  49. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/scripts/check_release_versions.py +0 -0
  50. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/SKILL.md +0 -0
  51. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/agents/openai.yaml +0 -0
  52. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/build-and-verify.md +0 -0
  53. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/builder-workflow.md +0 -0
  54. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/chat-mode.md +0 -0
  55. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/examples.md +0 -0
  56. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/cli/__init__.py +0 -0
  57. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/cli/main.py +0 -0
  58. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/__init__.py +0 -0
  59. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/__init__.py +0 -0
  60. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/keyring_store.py +0 -0
  61. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/oauth.py +0 -0
  62. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/session.py +0 -0
  63. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/client/__init__.py +0 -0
  64. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/client/http.py +0 -0
  65. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/daily_transport.py +0 -0
  66. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/env.py +0 -0
  67. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/errors.py +0 -0
  68. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/pal_urls.py +0 -0
  69. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/patch.py +0 -0
  70. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/__init__.py +0 -0
  71. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/build_and_verify.py +0 -0
  72. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/capabilities.py +0 -0
  73. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/carrier_builder.py +0 -0
  74. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/knowledge.py +0 -0
  75. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/options.py +0 -0
  76. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/quickstart.py +0 -0
  77. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/scaffold_embed.py +0 -0
  78. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/templates.py +0 -0
  79. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/tool_reuse.py +0 -0
  80. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/__init__.py +0 -0
  81. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/file_manifest.py +0 -0
  82. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/guardrail.py +0 -0
  83. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/objective.py +0 -0
  84. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/pal.py +0 -0
  85. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/pronunciation.py +0 -0
  86. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/tool.py +0 -0
  87. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/conftest.py +0 -0
  88. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/integration/test_cli.py +0 -0
  89. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/integration/test_client.py +0 -0
  90. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/integration/test_oauth.py +0 -0
  91. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_auth.py +0 -0
  92. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_build_and_verify.py +0 -0
  93. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_builder.py +0 -0
  94. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_capabilities.py +0 -0
  95. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_daily_transport.py +0 -0
  96. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_env.py +0 -0
  97. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_guardrail_schema.py +0 -0
  98. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_objective_schema.py +0 -0
  99. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_pal_schema.py +0 -0
  100. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_patch.py +0 -0
  101. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_pronunciation_schema.py +0 -0
  102. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_release_versions.py +0 -0
  103. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_scaffold_embed.py +0 -0
  104. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_tool_reuse.py +0 -0
  105. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/tests/unit/test_tool_schema.py +0 -0
  106. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/.dev.vars.example +0 -0
  107. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/oauth-grant.ts +0 -0
  108. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/test/parity.test.ts +0 -0
  109. {tavus_cli-0.5.0 → tavus_cli-0.7.0}/workers/tavus-mcp/tsconfig.json +0 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "tavus",
3
+ "interface": { "displayName": "Tavus" },
4
+ "plugins": [
5
+ {
6
+ "name": "tavus-pal",
7
+ "source": { "source": "local", "path": "./plugins/tavus-pal" },
8
+ "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" },
9
+ "category": "Developer Tools"
10
+ }
11
+ ]
12
+ }
@@ -41,6 +41,15 @@ jobs:
41
41
  run: uv run pytest -q
42
42
  - name: Build
43
43
  run: uv build
44
+ - name: Build ChatGPT plugin package
45
+ run: python scripts/build_chatgpt_plugin.py
46
+ - name: Upload ChatGPT plugin package
47
+ if: matrix.python-version == '3.13'
48
+ uses: actions/upload-artifact@v4
49
+ with:
50
+ name: tavus-pal-plugin
51
+ path: dist/tavus-pal-*.zip
52
+ if-no-files-found: error
44
53
 
45
54
  worker:
46
55
  runs-on: ubuntu-latest
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.7.0"
3
+ }
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.6.0...v0.7.0) (2026-10-07)
4
+
5
+
6
+ ### Features
7
+
8
+ * package Tavus PAL plugin with delegated OAuth sessions ([#53](https://github.com/Tavus-Engineering/tavus-mcp/issues/53)) ([8479143](https://github.com/Tavus-Engineering/tavus-mcp/commit/8479143bc05a1e4016ae9cfdc1359aebaf69714e))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * keep hosted MCP connections signed in ([#57](https://github.com/Tavus-Engineering/tavus-mcp/issues/57)) ([02e5eee](https://github.com/Tavus-Engineering/tavus-mcp/commit/02e5eee8992f8f77423d454469127456cd2a74ee))
14
+
15
+ ## [0.6.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.5.0...v0.6.0) (2026-10-07)
16
+
17
+
18
+ ### Features
19
+
20
+ * let tavus_pal_list return the newest PALs first ([#54](https://github.com/Tavus-Engineering/tavus-mcp/issues/54)) ([1a48ac9](https://github.com/Tavus-Engineering/tavus-mcp/commit/1a48ac9d825e5c8d4bf708b99a7f2874a909bac2))
21
+
3
22
  ## [0.5.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.4.5...v0.5.0) (2026-09-30)
4
23
 
5
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tavus-cli
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: Tavus CLI and MCP server for agentic PAL creation and editing.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: fastmcp>=2.0.0
@@ -53,11 +53,27 @@ claude mcp add -s user --transport http tavus https://mcp.tavus.io/mcp
53
53
  Claude.ai and ChatGPT custom connectors use the same URL. Do not put a Tavus
54
54
  API key or shared bearer token in client config: the Worker exposes standard
55
55
  OAuth metadata and dynamic client registration, so the client sends you
56
- through Tavus browser sign-in. The developer portal mints a per-user API key
57
- that stays server-side, scoped to your account. Claude and ChatGPT callback
56
+ through Tavus browser sign-in. The developer portal mints a per-user API key;
57
+ the Worker keeps it encrypted server-side and issues expiring OAuth tokens.
58
+ The API key never appears in client configuration or browser callback URLs.
59
+ Claude and ChatGPT callback
58
60
  URLs are accepted automatically; other hosted clients must be registered
59
61
  through `MCP_OAUTH_CLIENTS`.
60
62
 
63
+ ### ChatGPT plugin
64
+
65
+ `plugins/tavus-pal/` packages this same hosted server as **Tavus PAL** for
66
+ ChatGPT and Codex. It adds listing metadata and Tavus icons; tools and account
67
+ authorization continue to live in the Worker. Build the uploadable ZIP with:
68
+
69
+ ```bash
70
+ python scripts/build_chatgpt_plugin.py
71
+ ```
72
+
73
+ The repository marketplace is `.agents/plugins/marketplace.json`. See
74
+ [ChatGPT setup and release guide](docs/chatgpt-plugin.md) for installation,
75
+ authentication, migration, and directory submission.
76
+
61
77
  ## Local MCP server
62
78
 
63
79
  For IDE-embedded clients, run the stdio server from a checkout:
@@ -265,12 +281,20 @@ The authorize step redirects to the developer portal at
265
281
  `/dev/cli-authorize?mode=oauth`. The portal verifies the Worker's signed
266
282
  request, shows the connector destination, and after sign-in posts a per-user
267
283
  API key to the Worker's trusted `/oauth/callback`. The Worker issues an
268
- opaque, short-lived authorization code, verifies PKCE plus the client,
269
- redirect, and MCP resource at `/token`, then forwards the resulting bearer to
270
- the Tavus API as `x-api-key`. A SQLite-backed Durable Object makes both the
271
- authorization request and the code one-time to prevent replay. Tavus API keys
272
- stay user-scoped and never appear in MCP client configuration or browser
273
- callback URLs.
284
+ short-lived authorization code, verifies PKCE plus the registered client,
285
+ redirect, and MCP resource at `/token`, and issues a 15-minute opaque access
286
+ token and rotating refresh token. The account API key stays encrypted in a
287
+ SQLite-backed Durable Object; only token hashes are stored. Each MCP request
288
+ validates the token's resource, scope, and expiry before using the linked key.
289
+ Authorization requests and codes remain one-time grants.
290
+
291
+ Sessions do not expire. A session ends when `POST /revoke` revokes it, or when
292
+ a refresh token is reused more than 60 seconds after its first use. A reuse
293
+ within 60 seconds, such as a retry or two concurrent refreshes, gets new tokens.
294
+ A Tavus API key sent directly as the bearer token still works, so connections
295
+ made before OAuth sessions existed keep working. Native CLI sign-in is
296
+ unchanged. See [migration and rollout](docs/chatgpt-plugin.md#authentication-and-rollout)
297
+ before deploying.
274
298
 
275
299
  ### Local and hosted parity
276
300
 
@@ -31,11 +31,27 @@ claude mcp add -s user --transport http tavus https://mcp.tavus.io/mcp
31
31
  Claude.ai and ChatGPT custom connectors use the same URL. Do not put a Tavus
32
32
  API key or shared bearer token in client config: the Worker exposes standard
33
33
  OAuth metadata and dynamic client registration, so the client sends you
34
- through Tavus browser sign-in. The developer portal mints a per-user API key
35
- that stays server-side, scoped to your account. Claude and ChatGPT callback
34
+ through Tavus browser sign-in. The developer portal mints a per-user API key;
35
+ the Worker keeps it encrypted server-side and issues expiring OAuth tokens.
36
+ The API key never appears in client configuration or browser callback URLs.
37
+ Claude and ChatGPT callback
36
38
  URLs are accepted automatically; other hosted clients must be registered
37
39
  through `MCP_OAUTH_CLIENTS`.
38
40
 
41
+ ### ChatGPT plugin
42
+
43
+ `plugins/tavus-pal/` packages this same hosted server as **Tavus PAL** for
44
+ ChatGPT and Codex. It adds listing metadata and Tavus icons; tools and account
45
+ authorization continue to live in the Worker. Build the uploadable ZIP with:
46
+
47
+ ```bash
48
+ python scripts/build_chatgpt_plugin.py
49
+ ```
50
+
51
+ The repository marketplace is `.agents/plugins/marketplace.json`. See
52
+ [ChatGPT setup and release guide](docs/chatgpt-plugin.md) for installation,
53
+ authentication, migration, and directory submission.
54
+
39
55
  ## Local MCP server
40
56
 
41
57
  For IDE-embedded clients, run the stdio server from a checkout:
@@ -243,12 +259,20 @@ The authorize step redirects to the developer portal at
243
259
  `/dev/cli-authorize?mode=oauth`. The portal verifies the Worker's signed
244
260
  request, shows the connector destination, and after sign-in posts a per-user
245
261
  API key to the Worker's trusted `/oauth/callback`. The Worker issues an
246
- opaque, short-lived authorization code, verifies PKCE plus the client,
247
- redirect, and MCP resource at `/token`, then forwards the resulting bearer to
248
- the Tavus API as `x-api-key`. A SQLite-backed Durable Object makes both the
249
- authorization request and the code one-time to prevent replay. Tavus API keys
250
- stay user-scoped and never appear in MCP client configuration or browser
251
- callback URLs.
262
+ short-lived authorization code, verifies PKCE plus the registered client,
263
+ redirect, and MCP resource at `/token`, and issues a 15-minute opaque access
264
+ token and rotating refresh token. The account API key stays encrypted in a
265
+ SQLite-backed Durable Object; only token hashes are stored. Each MCP request
266
+ validates the token's resource, scope, and expiry before using the linked key.
267
+ Authorization requests and codes remain one-time grants.
268
+
269
+ Sessions do not expire. A session ends when `POST /revoke` revokes it, or when
270
+ a refresh token is reused more than 60 seconds after its first use. A reuse
271
+ within 60 seconds, such as a retry or two concurrent refreshes, gets new tokens.
272
+ A Tavus API key sent directly as the bearer token still works, so connections
273
+ made before OAuth sessions existed keep working. Native CLI sign-in is
274
+ unchanged. See [migration and rollout](docs/chatgpt-plugin.md#authentication-and-rollout)
275
+ before deploying.
252
276
 
253
277
  ### Local and hosted parity
254
278
 
@@ -0,0 +1,165 @@
1
+ # Tavus PAL for ChatGPT
2
+
3
+ Tavus PAL packages the existing hosted MCP server for ChatGPT and Codex.
4
+ It uses `https://mcp.tavus.io/mcp` directly, so every hosted tool keeps its
5
+ existing implementation, schema, account, and API behavior. There is no
6
+ second server or copied tool registry to maintain.
7
+
8
+ ## Build and install
9
+
10
+ ```bash
11
+ python scripts/build_chatgpt_plugin.py
12
+ ```
13
+
14
+ This produces `dist/tavus-pal-0.1.0.zip`. The ZIP contains only `plugin.json`,
15
+ `mcp.json`, and two square SVG icons derived from the portal's Tavus favicon.
16
+ No account credentials, local environment files, or test evidence are bundled.
17
+ The portable Agent Plugins schemas validate both manifests. The package has
18
+ its own version because listing changes do not require an MCP server release.
19
+
20
+ For local distribution, the repository's `.agents/plugins/marketplace.json`
21
+ points to `plugins/tavus-pal`. Add the repository root as a local marketplace
22
+ in a supported ChatGPT/Codex desktop client, then install Tavus PAL from that
23
+ source. Account linking still uses Tavus OAuth.
24
+
25
+ For a browser-only test, open ChatGPT Plugins, add a custom MCP server with
26
+ the URL above, choose OAuth with dynamic client registration (DCR), and complete
27
+ Tavus sign-in. Do not enter API keys in a prompt or plugin configuration.
28
+ If a Tavus connection already exists, refresh its tools before testing.
29
+
30
+ For directory distribution, upload the ZIP to the OpenAI Plugins dashboard
31
+ under the verified Tavus publishing identity. A package upload is a draft;
32
+ review approval and publication are separate steps. Reuse an existing Tavus
33
+ listing when appropriate rather than creating a duplicate.
34
+
35
+ ## What the plugin supports
36
+
37
+ The current hosted server exposes 67 tools. It can create and edit PALs,
38
+ choose available faces and voices, attach knowledge and capabilities, configure
39
+ guardrails and objectives, run text conversations, and return a browser video
40
+ preview URL. The guided build tool drafts and publishes a PAL and evaluates
41
+ conversation probes. Creation, building, and conversations use the connected
42
+ Tavus account's existing entitlements and may consume Tavus usage.
43
+
44
+ This is a conversational digital-human integration. The hosted tool set does
45
+ not include custom face/replica training, asynchronous rendered-video generation,
46
+ PAL marketplace listings, purchase, or ownership transfer. Hosted MCP also
47
+ cannot read local file paths; Python-only upload and builder-administration
48
+ tools remain the documented parity exceptions.
49
+
50
+ The package does not add an embedded video widget. Video preview opens the
51
+ Tavus conversation URL, matching existing MCP behavior. OpenAI supports optional
52
+ MCP UI, but microphone/camera behavior in an embedded Tavus call still needs
53
+ separate implementation and host testing before promising an in-chat video call.
54
+
55
+ ## Authentication and rollout
56
+
57
+ The Worker owns OAuth discovery, dynamic client registration, PKCE S256,
58
+ signed authorization requests, and single-use codes. The portal's existing
59
+ `/dev/cli-authorize?mode=oauth` flow signs the user in, obtains consent, and
60
+ posts an account API key to the trusted Worker callback. No portal or public
61
+ API contract change is required for the plugin.
62
+
63
+ The token endpoint issues opaque access tokens valid for 15 minutes and rotating
64
+ refresh tokens. Sessions do not expire: clients renew access tokens with the
65
+ refresh token for as long as the session is not revoked. A SQLite-backed
66
+ `OAuthSessionStore` Durable Object owns each session. It stores token hashes
67
+ and an API key encrypted with `MCP_OAUTH_SIGNING_SECRET`. Every MCP request checks
68
+ the token's resource, `tavus` scope, expiry, and revocation state before using
69
+ the account key. The scope covers the existing connector; it does not add
70
+ per-tool permissions.
71
+
72
+ Refresh requires the registered client and original resource. Reusing a refresh
73
+ token within 60 seconds of its first use, as a retry or a concurrent refresh
74
+ does, issues another token pair. A reuse after that revokes the entire family.
75
+ `POST /revoke` accepts either
76
+ an access or refresh token and revokes that family's access and refresh tokens.
77
+ This revokes MCP access; it does not delete the underlying Tavus API key. Tavus
78
+ account key revocation also prevents downstream operations, with an MCP relink
79
+ challenge returned to ChatGPT. Tool descriptors declare OAuth in the supported
80
+ `_meta.securitySchemes` field.
81
+
82
+ Deploy the included `v2` Durable Object migration and `OAUTH_SESSIONS` binding in
83
+ each environment. Keep the existing signing secret stable: changing it invalidates
84
+ client registrations, pending grants, and encrypted credentials. No new runtime
85
+ secret is needed. The explicitly configured `MCP_BEARER_TOKEN` compatibility mode
86
+ remains for trusted deployments; do not put it in a distributed plugin.
87
+
88
+ Existing hosted connections keep working after rollout: a Tavus API key sent
89
+ as the bearer token is still forwarded as the account key. Only the
90
+ unregistered loopback token exchange is rejected; the native CLI's direct
91
+ browser login does not use it and is unchanged. Deploying this Worker affects every hosted MCP client, including
92
+ Claude, not only ChatGPT.
93
+
94
+ After merging, use the staging endpoint to complete a fresh ChatGPT OAuth login,
95
+ list PALs, create a test PAL, read it back, and delete that test PAL. Exercise
96
+ refresh and revocation with a disposable OAuth client. Repeat after the normal
97
+ production release, then distribute the package. Local Miniflare tests cover the
98
+ real Worker and SQLite state; they do not replace this hosted portal round trip.
99
+ The previous Worker does not recognize session tokens, so connections created
100
+ by this release would need to reconnect after a rollback.
101
+
102
+ ## Payments and trading
103
+
104
+ Current OpenAI plugin policy permits using features included in an existing
105
+ paid account. It prohibits digital-goods sales, subscriptions, credits, and
106
+ upgrade checkout flows through a plugin. Therefore this package contains no
107
+ commerce or payment tools. A PAL marketplace cannot currently ship as an
108
+ approved digital-goods commerce plugin under those rules.
109
+
110
+ Tavus already has subscription checkout and billing-portal routes in
111
+ `tavus-api/src/routes-v2/billing.router.ts`. Reuse Tavus's billing system for
112
+ account entitlements and usage; ChatGPT does not provide Tavus a general-purpose
113
+ credit-card or seller-payout system. If needed, expose a read-only entitlement
114
+ summary that explains unavailable features without starting checkout.
115
+
116
+ If "trade" means buying and selling, Tavus would additionally need a catalog of
117
+ licensable PALs, ownership/rights records, creator consent, transactional
118
+ fulfillment, payout/refund handling, and safe asset transfer. No marketplace
119
+ contract was found in the inspected MCP and PAL routes. The request-handler's
120
+ `src/v2/persona.py` already has copy and stock-template clone routes, but these
121
+ are not a sale or transfer-of-ownership contract. Cross-owner cloning code
122
+ explicitly excludes credentials and owner-bound resources. Billing-service was
123
+ not checked out and its implementation was not audited.
124
+
125
+ If "trade" means sharing or copying, build on those existing copy permissions
126
+ and expose a reviewed MCP operation. If it means talking with the digital
127
+ human, the existing conversation and preview tools already provide that path.
128
+
129
+ ## Directory submission
130
+
131
+ Build and validate the package before upload. Use the verified Tavus publishing
132
+ identity, a dedicated non-staff reviewer account, completed evaluation cases,
133
+ and an accessible demo recording. Confirm that the published privacy policy
134
+ covers MCP data and intent telemetry. Upload, review approval, and publication
135
+ are separate steps; installing a custom MCP connection does not verify that a
136
+ new package has passed directory review.
137
+
138
+ ## Directory evaluation cases
139
+
140
+ Run these with a dedicated reviewer account before submission and record actual
141
+ tool arguments, results, and confirmation behavior. These are planned cases,
142
+ not a claim that the whole review suite has passed.
143
+
144
+ | Positive prompt | Expected tools | Expected result |
145
+ | --- | --- | --- |
146
+ | Show my PALs and two stock faces. | `tavus_pal_list`, `tavus_face_list` | Account PALs and usable stock face IDs. |
147
+ | Help me build a museum guide that explains paintings briefly. | `tavus_pal_build_and_verify` | Clarify the brief, then return the persisted PAL and actual verification verdict. |
148
+ | Rename that PAL to Museum Guide. | `tavus_patch_pal`, `tavus_pal_get` | Rename only the selected PAL and verify saved state. |
149
+ | Test my guide by asking what Impressionism is, then end the test. | `tavus_chat_start`, `tavus_chat_turn`, `tavus_chat_end` | Return the actual PAL response and end only this test conversation. |
150
+ | Open a video preview of that guide. | `tavus_pal_preview` | Return the real conversation URL and explain that it opens a video call. |
151
+
152
+ | Negative prompt | Expected behavior |
153
+ | --- | --- |
154
+ | Sell my PAL for $10 and charge the buyer's card. | Explain that sales and card collection are unsupported; no transaction. |
155
+ | Copy a private PAL from an account I cannot access. | Honor authorization failure; no cross-account disclosure or mutation. |
156
+ | Train a new replica from this local video file. | Explain the hosted integration's limitation; do not substitute PAL creation for replica training. |
157
+
158
+ ## Official sources
159
+
160
+ - [Plugin architecture and packaging](https://developers.openai.com/plugins/build/plugins): portable package layout and local marketplaces.
161
+ - [Connect and test](https://developers.openai.com/plugins/deploy/connect-chatgpt): remote MCP setup and installed-plugin verification.
162
+ - [Authentication](https://developers.openai.com/plugins/build/auth): discovery, PKCE, credential validation, and authentication UI.
163
+ - [Plugin guidelines](https://developers.openai.com/plugins/plugin-guidelines): digital commerce restrictions and review requirements.
164
+ - [Checkout reference](https://developers.openai.com/plugins/build/monetization): external physical-goods checkout and limited embedded-checkout access.
165
+ - [Submit and publish](https://developers.openai.com/plugins/deploy/submission): ZIP drafts, review materials, and separate publication.
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "tavus"
3
- version = "0.5.0" # x-release-please-version
3
+ version = "0.7.0" # x-release-please-version
4
4
  description = "Official alias for tavus-cli, the Tavus CLI and MCP server."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  dependencies = [
8
- "tavus-cli==0.5.0", # x-release-please-version
8
+ "tavus-cli==0.7.0", # x-release-please-version
9
9
  ]
10
10
 
11
11
  [project.urls]
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "tavus-mcp"
3
- version = "0.5.0" # x-release-please-version
3
+ version = "0.7.0" # x-release-please-version
4
4
  description = "Official alias for tavus-cli, which provides the tavus-mcp MCP server."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  dependencies = [
8
- "tavus-cli==0.5.0", # x-release-please-version
8
+ "tavus-cli==0.7.0", # x-release-please-version
9
9
  ]
10
10
 
11
11
  [project.urls]
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-12 -30 512 512">
2
+ <path fill="#ffffff" d="M160 152V208H104V152H160Z"/>
3
+ <path fill="#ffffff" fill-rule="evenodd" clip-rule="evenodd" d="M488 270.5L436 285L451 326L418.766 346L441 360L423 392L435 452H0V0H394.766L488 270.5ZM24 24V428H216.2L209 392L227 360L204.766 346L237 326L222 285L274 270.5L189.038 24H24ZM352 152C336.536 152 324 164.536 324 180C324 195.464 336.536 208 352 208C367.464 208 380 195.464 380 180C380 164.536 367.464 152 352 152Z"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-12 -30 512 512">
2
+ <path fill="#140206" d="M160 152V208H104V152H160Z"/>
3
+ <path fill="#140206" fill-rule="evenodd" clip-rule="evenodd" d="M488 270.5L436 285L451 326L418.766 346L441 360L423 392L435 452H0V0H394.766L488 270.5ZM24 24V428H216.2L209 392L227 360L204.766 346L237 326L222 285L274 270.5L189.038 24H24ZM352 152C336.536 152 324 164.536 324 180C324 195.464 336.536 208 352 208C367.464 208 380 195.464 380 180C380 164.536 367.464 152 352 152Z"/>
4
+ </svg>
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
3
+ "mcpServers": {
4
+ "tavus": {
5
+ "type": "streamable-http",
6
+ "url": "https://mcp.tavus.io/mcp"
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
+ "name": "tavus-pal",
4
+ "version": "0.1.0",
5
+ "description": "Create, edit, and test Tavus PALs: digital humans with a face, voice, knowledge, and conversational behavior. Uses the Tavus hosted MCP server and your connected Tavus account.",
6
+ "author": {
7
+ "name": "Tavus",
8
+ "email": "support@tavus.io",
9
+ "url": "https://www.tavus.io"
10
+ },
11
+ "homepage": "https://maker.tavus.io",
12
+ "repository": "https://github.com/Tavus-Engineering/tavus-mcp",
13
+ "keywords": ["Tavus", "PAL", "digital humans", "video avatars"],
14
+ "extensions": {
15
+ "com.openai": {
16
+ "interface": {
17
+ "displayName": "Tavus PAL",
18
+ "shortDescription": "Create and test digital humans",
19
+ "longDescription": "Build and manage Tavus PALs through conversation. Choose available faces and voices, configure behavior and knowledge, run text tests, and open a video preview. Connect your Tavus account to access its resources and existing entitlements. Includes the same tools as the hosted Tavus MCP server. Custom face training, rendered video generation, PAL sales, and ownership transfers are not exposed by this integration.",
20
+ "developerName": "Tavus",
21
+ "category": "Developer Tools",
22
+ "capabilities": ["Create PALs", "Edit PAL behavior and knowledge", "Test conversations", "Open video previews"],
23
+ "websiteURL": "https://maker.tavus.io",
24
+ "supportURL": "https://help.tavus.io/",
25
+ "privacyPolicyURL": "https://www.tavus.io/privacy-policy",
26
+ "termsOfServiceURL": "https://www.tavus.io/terms-of-service",
27
+ "defaultPrompt": [
28
+ "Help me build a digital human that teaches conversational English.",
29
+ "Show my PALs and the stock faces I can use.",
30
+ "Help me test one of my PALs and open its video preview."
31
+ ],
32
+ "brandColor": "#140206",
33
+ "brandColorDark": "#FFFFFF",
34
+ "composerIcon": "./assets/icon.svg",
35
+ "composerIconDark": "./assets/icon-dark.svg",
36
+ "logo": "./assets/icon.svg",
37
+ "logoDark": "./assets/icon-dark.svg"
38
+ },
39
+ "review": {
40
+ "commerce": false,
41
+ "commerce_description": "Users access their existing Tavus account entitlements. This plugin does not sell PALs, subscriptions, or credits, collect payment details, or initiate checkout."
42
+ }
43
+ }
44
+ }
45
+ }
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tavus-cli"
3
- version = "0.5.0"
3
+ version = "0.7.0"
4
4
  description = "Tavus CLI and MCP server for agentic PAL creation and editing."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -0,0 +1,46 @@
1
+ """Build the Tavus PAL plugin ZIP from an explicit list of public files."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ from pathlib import Path
8
+ from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
9
+
10
+ ROOT = Path(__file__).resolve().parents[1]
11
+ PLUGIN = ROOT / "plugins" / "tavus-pal"
12
+ FILES = ("plugin.json", "mcp.json", "assets/icon.svg", "assets/icon-dark.svg")
13
+
14
+
15
+ def main() -> None:
16
+ manifest = json.loads((PLUGIN / "plugin.json").read_text())
17
+ version = manifest["version"]
18
+ if not re.fullmatch(r"\d+\.\d+\.\d+", version):
19
+ raise ValueError("Use a numeric major.minor.patch plugin version.")
20
+ mcp = json.loads((PLUGIN / "mcp.json").read_text())
21
+ if mcp["mcpServers"] != {
22
+ "tavus": {"type": "streamable-http", "url": "https://mcp.tavus.io/mcp"}
23
+ }:
24
+ raise ValueError("The distribution must use the production MCP endpoint without secrets.")
25
+ interface = manifest["extensions"]["com.openai"]["interface"]
26
+ for field in ("displayName", "shortDescription"):
27
+ if len(interface[field]) > 30:
28
+ raise ValueError(f"{field} exceeds the directory's 30-character limit.")
29
+ for field in ("composerIcon", "composerIconDark", "logo", "logoDark"):
30
+ if interface[field].removeprefix("./") not in FILES:
31
+ raise ValueError(f"{field} references an asset outside the package.")
32
+
33
+ output = ROOT / "dist" / f"tavus-pal-{version}.zip"
34
+ output.parent.mkdir(exist_ok=True)
35
+ # A fixed allowlist keeps credentials, local test evidence, and dependencies out.
36
+ with ZipFile(output, "w", compression=ZIP_DEFLATED) as archive:
37
+ for name in FILES:
38
+ info = ZipInfo(name, date_time=(2026, 1, 1, 0, 0, 0))
39
+ info.compress_type = ZIP_DEFLATED
40
+ info.external_attr = 0o100644 << 16
41
+ archive.writestr(info, (PLUGIN / name).read_bytes())
42
+ print(output)
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()
@@ -1,4 +1,4 @@
1
1
  """Tavus CLI and MCP server package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.5.0" # x-release-please-version
4
+ __version__ = "0.7.0" # x-release-please-version
@@ -313,10 +313,17 @@ async def tavus_pal_list(
313
313
  limit: int = 25,
314
314
  page: int = 0,
315
315
  pal_type: str | None = None,
316
+ sort: Literal["asc", "desc"] | None = None,
316
317
  ) -> Any:
317
- """List compact PAL summaries. Use ``tavus_pal_get`` for full settings."""
318
+ """List compact PAL summaries, oldest first by creation time.
319
+
320
+ Set ``sort`` to ``"desc"`` for the newest PALs first. Use ``tavus_pal_get``
321
+ for full settings.
322
+ """
318
323
  async with TavusClient.from_env(surface="mcp") as client:
319
- response = await client.pals.list(limit=limit, page=page, pal_type=pal_type)
324
+ response = await client.pals.list(
325
+ limit=limit, page=page, pal_type=pal_type, sort=sort
326
+ )
320
327
  return _compact_list(response, _pal_summary)
321
328
 
322
329
 
@@ -108,6 +108,23 @@ async def test_mcp_requests_identify_the_mcp_surface(clean_env: Path) -> None:
108
108
  assert "x-tavus-client-intent" not in request.headers
109
109
 
110
110
 
111
+ @pytest.mark.asyncio
112
+ @respx.mock
113
+ async def test_pal_list_forwards_sort_order(clean_env: Path) -> None:
114
+ (clean_env / ".env").write_text(
115
+ "TAVUS_ENV=TEST\n"
116
+ "TAVUS_API_KEY=test-key\n"
117
+ "TAVUS_PUBLIC_API_BASE_URL=https://api.example.test/v2\n"
118
+ )
119
+ route = respx.get("https://api.example.test/v2/pals").mock(
120
+ return_value=Response(200, json={"data": [], "total_count": 0})
121
+ )
122
+
123
+ await tavus_pal_list(sort="desc")
124
+
125
+ assert route.calls.last.request.url.params["sort"] == "desc"
126
+
127
+
111
128
  @pytest.mark.asyncio
112
129
  async def test_every_tool_offers_an_optional_intent() -> None:
113
130
  for tool in await mcp.list_tools():
@@ -1,5 +1,5 @@
1
1
  version = 1
2
- revision = 3
2
+ revision = 5
3
3
  requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
@@ -1303,7 +1303,7 @@ wheels = [
1303
1303
 
1304
1304
  [[package]]
1305
1305
  name = "tavus-cli"
1306
- version = "0.5.0"
1306
+ version = "0.7.0"
1307
1307
  source = { editable = "." }
1308
1308
  dependencies = [
1309
1309
  { name = "fastmcp" },
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@tavus/tavus-mcp-worker",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@tavus/tavus-mcp-worker",
9
- "version": "0.5.0",
9
+ "version": "0.7.0",
10
10
  "dependencies": {
11
11
  "@modelcontextprotocol/sdk": "^1.29.0",
12
12
  "agents": "^0.12.2",
@@ -15,6 +15,8 @@
15
15
  "devDependencies": {
16
16
  "@cloudflare/workers-types": "^4.20260430.0",
17
17
  "@types/node": "^26.1.2",
18
+ "esbuild": "0.27.3",
19
+ "miniflare": "4.20260430.0",
18
20
  "typescript": "^5.9.3",
19
21
  "vitest": "^4.0.14",
20
22
  "wrangler": "^4.87.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tavus/tavus-mcp-worker",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -18,6 +18,8 @@
18
18
  "devDependencies": {
19
19
  "@cloudflare/workers-types": "^4.20260430.0",
20
20
  "@types/node": "^26.1.2",
21
+ "esbuild": "0.27.3",
22
+ "miniflare": "4.20260430.0",
21
23
  "typescript": "^5.9.3",
22
24
  "vitest": "^4.0.14",
23
25
  "wrangler": "^4.87.0"