tavus-cli 0.6.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.
- tavus_cli-0.7.0/.agents/plugins/marketplace.json +12 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/ci.yml +9 -0
- tavus_cli-0.7.0/.release-please-manifest.json +3 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/CHANGELOG.md +12 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/PKG-INFO +33 -9
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/README.md +32 -8
- tavus_cli-0.7.0/docs/chatgpt-plugin.md +165 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/packages/tavus/pyproject.toml +2 -2
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/packages/tavus-mcp/pyproject.toml +2 -2
- tavus_cli-0.7.0/plugins/tavus-pal/assets/icon-dark.svg +4 -0
- tavus_cli-0.7.0/plugins/tavus-pal/assets/icon.svg +4 -0
- tavus_cli-0.7.0/plugins/tavus-pal/mcp.json +9 -0
- tavus_cli-0.7.0/plugins/tavus-pal/plugin.json +45 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/pyproject.toml +1 -1
- tavus_cli-0.7.0/scripts/build_chatgpt_plugin.py +46 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/__init__.py +1 -1
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/uv.lock +1 -1
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/package-lock.json +4 -2
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/package.json +3 -1
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/index.ts +8 -6
- tavus_cli-0.7.0/workers/tavus-mcp/src/oauth-session.ts +151 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/oauth.ts +141 -70
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/tavus.ts +30 -33
- tavus_cli-0.7.0/workers/tavus-mcp/src/version.ts +1 -0
- tavus_cli-0.7.0/workers/tavus-mcp/test/oauth-session.test.ts +362 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/test/tavus.test.ts +36 -59
- tavus_cli-0.7.0/workers/tavus-mcp/test/worker-runtime.ts +41 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/wrangler.jsonc +10 -5
- tavus_cli-0.6.0/.release-please-manifest.json +0 -3
- tavus_cli-0.6.0/workers/tavus-mcp/src/version.ts +0 -1
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.env.example +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/deploy-cloudflare-worker.yml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/pr-reviews.yml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/pypi-cli.yml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/tail-cloudflare-worker.yml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.github/workflows/validate-staging-deployment.yml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/.gitignore +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/AGENTS.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/README.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/listing.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/docs/gemini-enterprise/test-queries.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/docs/usage-observability.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/packages/tavus/README.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/packages/tavus-mcp/README.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/release-please-config.json +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/scripts/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/scripts/check_release_versions.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/SKILL.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/agents/openai.yaml +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/build-and-verify.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/builder-workflow.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/chat-mode.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/skills/tavus-agentic-pals/references/examples.md +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/cli/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/cli/main.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/keyring_store.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/oauth.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/auth/session.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/client/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/client/http.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/daily_transport.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/env.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/errors.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/pal_urls.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/patch.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/build_and_verify.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/capabilities.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/carrier_builder.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/knowledge.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/options.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/quickstart.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/scaffold_embed.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/templates.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/recipes/tool_reuse.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/__init__.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/file_manifest.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/guardrail.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/objective.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/pal.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/pronunciation.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/sdk/schemas/tool.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/src/tavus_mcp/server.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/conftest.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/integration/test_cli.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/integration/test_client.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/integration/test_mcp_server.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/integration/test_oauth.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_auth.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_build_and_verify.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_builder.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_capabilities.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_daily_transport.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_env.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_guardrail_schema.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_objective_schema.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_pal_schema.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_patch.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_pronunciation_schema.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_release_versions.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_scaffold_embed.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_tool_reuse.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/tests/unit/test_tool_schema.py +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/.dev.vars.example +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/src/oauth-grant.ts +0 -0
- {tavus_cli-0.6.0 → tavus_cli-0.7.0}/workers/tavus-mcp/test/parity.test.ts +0 -0
- {tavus_cli-0.6.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
|
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
3
15
|
## [0.6.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.5.0...v0.6.0) (2026-10-07)
|
|
4
16
|
|
|
5
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tavus-cli
|
|
3
|
-
Version: 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
|
-
|
|
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
|
-
|
|
269
|
-
redirect, and MCP resource at `/token`,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
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
|
-
|
|
247
|
-
redirect, and MCP resource at `/token`,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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,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
|
+
}
|
|
@@ -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,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tavus/tavus-mcp-worker",
|
|
3
|
-
"version": "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.
|
|
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.
|
|
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"
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { createMcpHandler } from "agents/mcp";
|
|
2
2
|
|
|
3
|
-
import { handleOAuthRequest, oauthUnauthorizedHeaders } from "./oauth";
|
|
3
|
+
import { handleOAuthRequest, oauthUnauthorizedHeaders, resolveMcpApiKey } from "./oauth";
|
|
4
4
|
import {
|
|
5
5
|
authorizationError,
|
|
6
6
|
createTavusMcpServer,
|
|
7
7
|
Env,
|
|
8
|
-
isAuthorized,
|
|
9
|
-
resolveRequestApiKey,
|
|
10
8
|
resolveConfig,
|
|
11
9
|
} from "./tavus";
|
|
12
10
|
|
|
13
11
|
export { OAuthGrantStore } from "./oauth-grant";
|
|
12
|
+
export { OAuthSessionStore } from "./oauth-session";
|
|
14
13
|
|
|
15
14
|
const MCP_ROUTE = "/mcp";
|
|
16
15
|
|
|
@@ -40,20 +39,23 @@ export default {
|
|
|
40
39
|
});
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
if (url.pathname
|
|
42
|
+
if (url.pathname === MCP_ROUTE) {
|
|
44
43
|
const configError = authorizationError(env);
|
|
45
44
|
if (configError) {
|
|
46
45
|
return json({ error: configError.error }, configError.status);
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
const apiKey = url.pathname === MCP_ROUTE && request.method !== "OPTIONS"
|
|
50
|
+
? await resolveMcpApiKey(request, env, MCP_ROUTE)
|
|
51
|
+
: undefined;
|
|
52
|
+
if (url.pathname === MCP_ROUTE && request.method !== "OPTIONS" && !apiKey) {
|
|
51
53
|
return json({ error: "Unauthorized" }, 401, {
|
|
52
54
|
...oauthUnauthorizedHeaders(request, MCP_ROUTE),
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
const server = createTavusMcpServer(env,
|
|
58
|
+
const server = createTavusMcpServer(env, apiKey, new Headers(oauthUnauthorizedHeaders(request, MCP_ROUTE)).get("WWW-Authenticate")!);
|
|
57
59
|
return createMcpHandler(server, { route: MCP_ROUTE })(request, env, ctx);
|
|
58
60
|
},
|
|
59
61
|
} satisfies ExportedHandler<Env>;
|