tavus-cli 0.10.3__tar.gz → 0.10.4__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 (117) hide show
  1. tavus_cli-0.10.4/.release-please-manifest.json +3 -0
  2. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/CHANGELOG.md +7 -0
  3. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/PKG-INFO +1 -1
  4. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/packages/tavus/pyproject.toml +2 -2
  5. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/packages/tavus-mcp/pyproject.toml +2 -2
  6. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/pyproject.toml +1 -1
  7. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/SKILL.md +15 -1
  8. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/references/build-and-verify.md +4 -0
  9. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/__init__.py +1 -1
  10. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/pal.py +10 -0
  11. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/server.py +14 -1
  12. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/integration/test_mcp_server.py +21 -0
  13. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_pal_schema.py +24 -0
  14. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/uv.lock +1 -1
  15. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/package-lock.json +2 -2
  16. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/package.json +1 -1
  17. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/src/tavus.ts +13 -5
  18. tavus_cli-0.10.4/workers/tavus-mcp/src/version.ts +1 -0
  19. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/test/tavus.test.ts +42 -1
  20. tavus_cli-0.10.3/.release-please-manifest.json +0 -3
  21. tavus_cli-0.10.3/workers/tavus-mcp/src/version.ts +0 -1
  22. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.agents/plugins/marketplace.json +0 -0
  23. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.env.example +0 -0
  24. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/ci.yml +0 -0
  25. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/deploy-cloudflare-worker.yml +0 -0
  26. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/pr-reviews.yml +0 -0
  27. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/pypi-cli.yml +0 -0
  28. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/tail-cloudflare-worker.yml +0 -0
  29. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.github/workflows/validate-staging-deployment.yml +0 -0
  30. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/.gitignore +0 -0
  31. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/AGENTS.md +0 -0
  32. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/PROMPT.md +0 -0
  33. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/README.md +0 -0
  34. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/builder-guidance.md +0 -0
  35. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/chatgpt-plugin.md +0 -0
  36. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/gemini-enterprise/README.md +0 -0
  37. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/gemini-enterprise/listing.md +0 -0
  38. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/gemini-enterprise/test-queries.md +0 -0
  39. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/docs/usage-observability.md +0 -0
  40. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/packages/tavus/README.md +0 -0
  41. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/packages/tavus-mcp/README.md +0 -0
  42. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/plugins/tavus-pal/assets/icon-dark.svg +0 -0
  43. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/plugins/tavus-pal/assets/icon.svg +0 -0
  44. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/plugins/tavus-pal/mcp.json +0 -0
  45. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/plugins/tavus-pal/plugin.json +0 -0
  46. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/release-please-config.json +0 -0
  47. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/scripts/__init__.py +0 -0
  48. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/scripts/build_chatgpt_plugin.py +0 -0
  49. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/scripts/check_release_versions.py +0 -0
  50. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/agents/openai.yaml +0 -0
  51. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/references/builder-workflow.md +0 -0
  52. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/references/chat-mode.md +0 -0
  53. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/skills/tavus-agentic-pals/references/examples.md +0 -0
  54. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/builder_guidance.json +0 -0
  55. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/builder_guidance.py +0 -0
  56. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/cli/__init__.py +0 -0
  57. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/cli/main.py +0 -0
  58. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/__init__.py +0 -0
  59. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/auth/__init__.py +0 -0
  60. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/auth/keyring_store.py +0 -0
  61. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/auth/oauth.py +0 -0
  62. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/auth/session.py +0 -0
  63. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/client/__init__.py +0 -0
  64. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/client/http.py +0 -0
  65. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/daily_transport.py +0 -0
  66. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/env.py +0 -0
  67. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/errors.py +0 -0
  68. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/pal_urls.py +0 -0
  69. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/patch.py +0 -0
  70. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/__init__.py +0 -0
  71. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/build_and_verify.py +0 -0
  72. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/capabilities.py +0 -0
  73. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/carrier_builder.py +0 -0
  74. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/deployments.py +0 -0
  75. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/knowledge.py +0 -0
  76. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/options.py +0 -0
  77. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/quickstart.py +0 -0
  78. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/scaffold_embed.py +0 -0
  79. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/templates.py +0 -0
  80. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/recipes/tool_reuse.py +0 -0
  81. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/__init__.py +0 -0
  82. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/deployment.py +0 -0
  83. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/file_manifest.py +0 -0
  84. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/guardrail.py +0 -0
  85. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/objective.py +0 -0
  86. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/pronunciation.py +0 -0
  87. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/src/tavus_mcp/sdk/schemas/tool.py +0 -0
  88. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/conftest.py +0 -0
  89. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/integration/test_cli.py +0 -0
  90. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/integration/test_client.py +0 -0
  91. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/integration/test_oauth.py +0 -0
  92. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_auth.py +0 -0
  93. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_build_and_verify.py +0 -0
  94. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_builder.py +0 -0
  95. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_capabilities.py +0 -0
  96. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_daily_transport.py +0 -0
  97. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_deployments.py +0 -0
  98. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_env.py +0 -0
  99. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_guardrail_schema.py +0 -0
  100. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_objective_schema.py +0 -0
  101. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_patch.py +0 -0
  102. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_pronunciation_schema.py +0 -0
  103. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_release_versions.py +0 -0
  104. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_scaffold_embed.py +0 -0
  105. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_tool_reuse.py +0 -0
  106. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/tests/unit/test_tool_schema.py +0 -0
  107. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/.dev.vars.example +0 -0
  108. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/src/index.ts +0 -0
  109. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/src/oauth-grant.ts +0 -0
  110. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/src/oauth-session.ts +0 -0
  111. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/src/oauth.ts +0 -0
  112. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/test/builder-guidance.test.ts +0 -0
  113. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/test/oauth-session.test.ts +0 -0
  114. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/test/parity.test.ts +0 -0
  115. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/test/worker-runtime.ts +0 -0
  116. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/tsconfig.json +0 -0
  117. {tavus_cli-0.10.3 → tavus_cli-0.10.4}/workers/tavus-mcp/wrangler.jsonc +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.10.4"
3
+ }
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.4](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.10.3...v0.10.4) (2026-10-19)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * support PAL meeting setup, dispatch, and all verification probes ([#80](https://github.com/Tavus-Engineering/tavus-mcp/issues/80)) ([c635462](https://github.com/Tavus-Engineering/tavus-mcp/commit/c635462493098269f3361c2f0ff2d2fc3869bece))
9
+
3
10
  ## [0.10.3](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.10.2...v0.10.3) (2026-10-16)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tavus-cli
3
- Version: 0.10.3
3
+ Version: 0.10.4
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
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "tavus"
3
- version = "0.10.3" # x-release-please-version
3
+ version = "0.10.4" # 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.10.3", # x-release-please-version
8
+ "tavus-cli==0.10.4", # 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.10.3" # x-release-please-version
3
+ version = "0.10.4" # 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.10.3", # x-release-please-version
8
+ "tavus-cli==0.10.4", # x-release-please-version
9
9
  ]
10
10
 
11
11
  [project.urls]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tavus-cli"
3
- version = "0.10.3"
3
+ version = "0.10.4"
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"
@@ -136,7 +136,7 @@ Knowledge document tools:
136
136
  Conversation and resource tools:
137
137
 
138
138
  - `tavus_face_list(limit, stock)`
139
- - `tavus_conversation_create(pal_id, face_id, conversation_name)`
139
+ - `tavus_conversation_create(pal_id?, face_id?, conversation_name?, meeting_url?)`
140
140
  - `tavus_conversation_end(conversation_id)`
141
141
  - `tavus_quickstart(system_prompt, pal_name, face_id)`
142
142
  - `tavus_resource_list(resource, limit)` for `guardrails`, `objectives`, `documents`, `voices`, `skills`, or `tools`
@@ -279,6 +279,20 @@ Prefer focused patches over full rebuilds:
279
279
 
280
280
  Common patch targets include `/system_prompt`, `/greeting`, `/context`, `/pal_name`, `/default_face_id`, `/objectives_id`, `/guardrail_ids`, `/guardrail_tags`, `/document_ids`, `/document_tags`, and nested layer paths under `/layers/llm`, `/layers/tts`, `/layers/stt`, `/layers/perception`, `/layers/conversational_flow`, `/layers/capabilities`, and `/layers/knowledge_base`.
281
281
 
282
+ For meeting participation, set `wake_phrase` and `sleep_phrase` under
283
+ `/layers/conversational_flow`. Save both phrases together; a sleep phrase
284
+ requires a wake phrase. Configure `/layers/conferencing` in a separate patch
285
+ with `username`, `allowlist`, and `whitelabel`. The API rejects a patch that
286
+ mixes conferencing with behavior settings. A default face must be selected
287
+ before claiming a conferencing identity. Read back `layers.conferencing.email`
288
+ for the invite address; do not construct it yourself. Before joining a meeting,
289
+ ask the creator for its link and confirm that the PAL is expected there.
290
+ Creating a conferencing identity does not join a call. Test waking and sleeping
291
+ in a real voice call before claiming the meeting behavior works.
292
+ To send the PAL to the supplied meeting link, call `tavus_conversation_create`
293
+ with `pal_id` and `meeting_url`. A successful response confirms dispatch, not
294
+ admission. Check the meeting participant list before saying the PAL joined.
295
+
282
296
  ## Creation Patterns
283
297
 
284
298
  Use `tavus_quickstart` or `uv run tavus quickstart` when the user wants a pal plus a conversation quickly. It uses the first stock face unless a face ID is provided.
@@ -47,6 +47,10 @@ tavus_pal_build_and_verify(
47
47
  )
48
48
  ```
49
49
 
50
+ The hosted connector accepts up to five supplied probes and retains all of
51
+ them. Generated probes are capped at three. The smoke test has a shared time
52
+ budget; a probe that cannot run is reported in the transcript with an error.
53
+
50
54
  ### Changing an existing PAL (hosted connector)
51
55
 
52
56
  Pass `pal_id` to run the same drafters on an existing PAL. Put the requested
@@ -1,4 +1,4 @@
1
1
  """Tavus CLI and MCP server package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.10.3" # x-release-please-version
4
+ __version__ = "0.10.4" # x-release-please-version
@@ -74,9 +74,18 @@ class ConversationalFlowLayerPatchModel(BaseModel):
74
74
  voice_isolation: str | None = None
75
75
  noise_cancellation: str | None = None
76
76
  wake_phrase: str | None = None
77
+ sleep_phrase: str | None = None
77
78
  idle_engagement: str | None = None
78
79
 
79
80
 
81
+ class ConferencingLayerPatchModel(BaseModel):
82
+ model_config = ConfigDict(extra="forbid")
83
+
84
+ username: str | None = None
85
+ allowlist: list[str] | None = None
86
+ whitelabel: bool | None = None
87
+
88
+
80
89
  class CapabilitiesLayerPatchModel(BaseModel):
81
90
  model_config = ConfigDict(extra="forbid")
82
91
 
@@ -106,6 +115,7 @@ class LayersPatchModel(BaseModel):
106
115
  transport: dict[str, Any] | None = None
107
116
  perception: PerceptionLayerPatchModel | None = None
108
117
  conversational_flow: ConversationalFlowLayerPatchModel | None = None
118
+ conferencing: ConferencingLayerPatchModel | None = None
109
119
  capabilities: CapabilitiesLayerPatchModel | None = None
110
120
  knowledge_base: KnowledgeBaseLayerPatchModel | None = None
111
121
 
@@ -427,7 +427,12 @@ async def tavus_patch_pal(pal_id: str, ops: list[dict[str, Any]]) -> Any:
427
427
 
428
428
  Tools are first-class now: prefer tavus_tool_create + tavus_pal_tools_attach
429
429
  over writing tools inline here. Inline layer tool paths are rejected by the
430
- patch validator."""
430
+ patch validator. Set wake_phrase and sleep_phrase under
431
+ /layers/conversational_flow. Patch /layers/conferencing separately from
432
+ behavior settings; it accepts username, allowlist, and whitelabel.
433
+ Configuring an identity does not join a call. Ask the creator for the
434
+ meeting link before joining.
435
+ """
431
436
  async with TavusClient.from_env(surface="mcp") as client:
432
437
  return await client.pals.patch(pal_id, ops)
433
438
 
@@ -853,13 +858,21 @@ async def tavus_conversation_create(
853
858
  pal_id: str | None = None,
854
859
  face_id: str | None = None,
855
860
  conversation_name: str | None = None,
861
+ meeting_url: str | None = None,
856
862
  ) -> Any:
863
+ """Create a conversation, or send a PAL to an existing meeting.
864
+
865
+ Ask the creator for the meeting link before setting meeting_url. The PAL
866
+ needs a conferencing identity and a default face. Creation confirms the
867
+ request was sent; verify admission in the meeting before reporting joined.
868
+ """
857
869
  # /v2/conversations is not part of the pal/face alias, so the body keeps the
858
870
  # underlying persona_id/replica_id wire fields (id values are identical).
859
871
  body = {
860
872
  "persona_id": pal_id,
861
873
  "replica_id": face_id,
862
874
  "conversation_name": conversation_name,
875
+ "meeting_url": meeting_url,
863
876
  }
864
877
  async with TavusClient.from_env(surface="mcp") as client:
865
878
  return await client.conversations.create({k: v for k, v in body.items() if v})
@@ -23,6 +23,27 @@ from tavus_mcp.server import (
23
23
  )
24
24
 
25
25
 
26
+ @pytest.mark.asyncio
27
+ @respx.mock
28
+ async def test_mcp_dispatches_pal_to_requested_meeting(clean_env: Path) -> None:
29
+ (clean_env / ".env").write_text(
30
+ "TAVUS_ENV=TEST\nTAVUS_API_KEY=test-key\n"
31
+ "TAVUS_PUBLIC_API_BASE_URL=https://api.example.test/v2\n"
32
+ )
33
+ route = respx.post("https://api.example.test/v2/conversations").respond(
34
+ 200, json={"conversation_id": "c-meeting", "status": "active"}
35
+ )
36
+ async with Client(mcp) as client:
37
+ await client.call_tool("tavus_conversation_create", {
38
+ "pal_id": "p-meeting",
39
+ "meeting_url": "https://meet.google.com/abc-defg-hij",
40
+ })
41
+ assert json.loads(route.calls.last.request.content) == {
42
+ "persona_id": "p-meeting",
43
+ "meeting_url": "https://meet.google.com/abc-defg-hij",
44
+ }
45
+
46
+
26
47
  @pytest.mark.asyncio
27
48
  async def test_builder_guidance_reaches_mcp_clients() -> None:
28
49
  async with Client(mcp) as client:
@@ -3,9 +3,33 @@ from __future__ import annotations
3
3
  import pytest
4
4
  from pydantic import ValidationError
5
5
 
6
+ from tavus_mcp.sdk.patch import validate_patch_operations
6
7
  from tavus_mcp.sdk.schemas.pal import PalCreate
7
8
 
8
9
 
10
+ def test_meeting_pal_accepts_activation_phrases_and_conferencing_settings() -> None:
11
+ layers = {
12
+ "conversational_flow": {"wake_phrase": "Hey Morgan", "sleep_phrase": "Goodbye Morgan"},
13
+ "conferencing": {
14
+ "username": "morgan-rehearsal",
15
+ "allowlist": ["host@example.com"],
16
+ "whitelabel": False,
17
+ },
18
+ }
19
+ pal = PalCreate.model_validate({"system_prompt": "Be a skeptical customer.", "layers": layers})
20
+ saved = pal.model_dump(exclude_none=True)["layers"]
21
+ assert saved["conversational_flow"] == layers["conversational_flow"]
22
+ assert saved["conferencing"] == layers["conferencing"]
23
+ for layer, fields in layers.items():
24
+ for field, value in fields.items():
25
+ validate_patch_operations(
26
+ [{"op": "add", "path": f"/layers/{layer}/{field}", "value": value}]
27
+ )
28
+ validate_patch_operations(
29
+ [{"op": "add", "path": "/layers/conferencing/allowlist/-", "value": "other@example.com"}]
30
+ )
31
+
32
+
9
33
  def test_full_pipeline_requires_system_prompt() -> None:
10
34
  with pytest.raises(ValidationError, match="system_prompt is required"):
11
35
  PalCreate.model_validate({"pal_name": "p"})
@@ -1303,7 +1303,7 @@ wheels = [
1303
1303
 
1304
1304
  [[package]]
1305
1305
  name = "tavus-cli"
1306
- version = "0.10.3"
1306
+ version = "0.10.4"
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.10.3",
3
+ "version": "0.10.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@tavus/tavus-mcp-worker",
9
- "version": "0.10.3",
9
+ "version": "0.10.4",
10
10
  "dependencies": {
11
11
  "@modelcontextprotocol/sdk": "^1.29.0",
12
12
  "agents": "^0.12.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tavus/tavus-mcp-worker",
3
- "version": "0.10.3",
3
+ "version": "0.10.4",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -385,6 +385,12 @@ const PATCHABLE_PATHS = [
385
385
  "/layers/capabilities/mcp_enabled",
386
386
  "/layers/capabilities/search_enabled",
387
387
  "/layers/capabilities/search_results_prompt_injection_prevention_enabled",
388
+ "/layers/conferencing",
389
+ "/layers/conferencing/allowlist",
390
+ "/layers/conferencing/allowlist/-",
391
+ "/layers/conferencing/allowlist/0",
392
+ "/layers/conferencing/username",
393
+ "/layers/conferencing/whitelabel",
388
394
  "/layers/conversational_flow",
389
395
  "/layers/conversational_flow/active_listening",
390
396
  "/layers/conversational_flow/idle_engagement",
@@ -395,6 +401,7 @@ const PATCHABLE_PATHS = [
395
401
  "/layers/conversational_flow/turn_taking_patience",
396
402
  "/layers/conversational_flow/voice_isolation",
397
403
  "/layers/conversational_flow/wake_phrase",
404
+ "/layers/conversational_flow/sleep_phrase",
398
405
  "/layers/knowledge_base",
399
406
  "/layers/knowledge_base/enable_rag_observability_app_messages",
400
407
  "/layers/knowledge_base/rag_n_chunks",
@@ -696,7 +703,7 @@ export function createTavusMcpServer(
696
703
 
697
704
  server.tool(
698
705
  "tavus_patch_pal",
699
- "Patch a PAL with validated JSON Patch operations for an exact field edit. To change what a PAL does or shows, such as adding an on-screen scorecard, use tavus_pal_build_and_verify with pal_id instead. Attach first-class tools through top-level tool_ids or tavus_pal_tools_attach; legacy layers.llm.tools writes are rejected.",
706
+ "Patch a PAL with validated JSON Patch operations for an exact field edit. To change what a PAL does or shows, such as adding an on-screen scorecard, use tavus_pal_build_and_verify with pal_id instead. Set wake_phrase and sleep_phrase under /layers/conversational_flow. Patch /layers/conferencing separately from behavior settings; it accepts username, allowlist, and whitelabel. Configuring an identity does not join a call. Ask the creator for the meeting link before joining. Attach first-class tools through top-level tool_ids or tavus_pal_tools_attach; legacy layers.llm.tools writes are rejected.",
700
707
  {
701
708
  pal_id: z.string().min(1),
702
709
  ops: z.array(JsonPatchOperationSchema).min(1),
@@ -1671,11 +1678,12 @@ export function createTavusMcpServer(
1671
1678
 
1672
1679
  server.tool(
1673
1680
  "tavus_conversation_create",
1674
- "Create a Tavus conversation for a pal and/or face.",
1681
+ "Create a Tavus conversation for a PAL and/or face, or send a PAL to an existing meeting. Ask the creator for the meeting link before setting meeting_url. The PAL needs a conferencing identity and a default face. Creation confirms the request was sent; verify admission in the meeting before reporting joined.",
1675
1682
  {
1676
1683
  pal_id: z.string().optional(),
1677
1684
  face_id: z.string().optional(),
1678
1685
  conversation_name: z.string().optional(),
1686
+ meeting_url: z.string().optional(),
1679
1687
  },
1680
1688
  {
1681
1689
  title: "Create conversation",
@@ -1686,7 +1694,7 @@ export function createTavusMcpServer(
1686
1694
  },
1687
1695
  // /v2/conversations is not part of the pal/face alias, so the body keeps the
1688
1696
  // underlying persona_id/replica_id wire fields (id values are identical).
1689
- async ({ pal_id, face_id, conversation_name }) =>
1697
+ async ({ pal_id, face_id, conversation_name, meeting_url }) =>
1690
1698
  toolResult(
1691
1699
  await client.create(
1692
1700
  "conversations",
@@ -1694,6 +1702,7 @@ export function createTavusMcpServer(
1694
1702
  persona_id: pal_id,
1695
1703
  replica_id: face_id,
1696
1704
  conversation_name,
1705
+ meeting_url,
1697
1706
  }),
1698
1707
  ),
1699
1708
  ),
@@ -3130,8 +3139,7 @@ async function runGuidedBuild(
3130
3139
 
3131
3140
  let probes = (options.probes ?? [])
3132
3141
  .map((probe) => probe.trim())
3133
- .filter(Boolean)
3134
- .slice(0, MAX_SMOKE_PROBES);
3142
+ .filter(Boolean);
3135
3143
  if (!probes.length) {
3136
3144
  const generated = await safeCall(() =>
3137
3145
  client.post("persona-builder/llm/generate-probes", { persona_spec: spec }),
@@ -0,0 +1 @@
1
+ export const VERSION = "0.10.4"; // x-release-please-version
@@ -72,6 +72,25 @@ function registeredTools(
72
72
  }
73
73
 
74
74
  describe("Cloudflare Tavus MCP helpers", () => {
75
+ it("dispatches a PAL to the requested meeting through the hosted tool", async () => {
76
+ const requests: Array<{ url: string; body: unknown }> = [];
77
+ vi.stubGlobal("fetch", vi.fn(async (input: string | URL | Request, init?: RequestInit) => {
78
+ requests.push({ url: String(input), body: JSON.parse(String(init?.body)) });
79
+ return Response.json({ conversation_id: "c-meeting", status: "active" });
80
+ }));
81
+ try {
82
+ const tool = registeredTools(createTavusMcpServer({ TAVUS_API_KEY: "secret" }))
83
+ .tavus_conversation_create;
84
+ await tool.handler({ pal_id: "p-meeting", meeting_url: "https://meet.google.com/abc-defg-hij" });
85
+ expect(requests).toEqual([{
86
+ url: "https://tavusapi.com/v2/conversations",
87
+ body: { persona_id: "p-meeting", meeting_url: "https://meet.google.com/abc-defg-hij" },
88
+ }]);
89
+ } finally {
90
+ vi.unstubAllGlobals();
91
+ }
92
+ });
93
+
75
94
  it("reads RQH builder history across MCP sessions and saves creator turns there", async () => {
76
95
  const history = [{ role: "assistant", content: "Would you like Memory?" }];
77
96
  vi.stubGlobal("fetch", vi.fn(async (input: string | URL | Request, init?: RequestInit) => {
@@ -591,7 +610,8 @@ describe("Cloudflare Tavus MCP helpers", () => {
591
610
  await expect(build({ pal_id: "p_live", prompt: request })).rejects.toThrow(/at least one brief/);
592
611
  expect(calls).toEqual([]);
593
612
 
594
- const pending = build({ pal_id: "p_live", prompt: request, briefs: { skills: request }, probes: ["Score me."] });
613
+ const probes = ["Start practice.", "My first answer.", "My second answer.", "Score me.", "Wrap up."];
614
+ const pending = build({ pal_id: "p_live", prompt: request, briefs: { skills: request }, probes });
595
615
  let settled = false;
596
616
  void pending.finally(() => {
597
617
  settled = true;
@@ -600,6 +620,9 @@ describe("Cloudflare Tavus MCP helpers", () => {
600
620
  await vi.advanceTimersByTimeAsync(500);
601
621
  }
602
622
  const result = JSON.parse((await pending).content[0].text);
623
+ expect(result.probes).toEqual(probes);
624
+ expect(result.smoke_transcript.filter((turn: { role: string }) => turn.role === "user")
625
+ .map((turn: { text: string }) => turn.text)).toEqual(probes);
603
626
 
604
627
  expect(calls.find((call) => call.path === "/builder")?.body).toEqual({
605
628
  name: "Leasing Coach",
@@ -648,6 +671,24 @@ describe("Cloudflare Tavus MCP helpers", () => {
648
671
  ).toThrow(/Unsupported pal patch path/);
649
672
  });
650
673
 
674
+ it("accepts meeting settings and rejects unsupported leaf paths", () => {
675
+ const ops = [
676
+ { op: "add" as const, path: "/layers/conversational_flow/wake_phrase", value: "Hey Morgan" },
677
+ { op: "add" as const, path: "/layers/conversational_flow/sleep_phrase", value: "Goodbye Morgan" },
678
+ { op: "add" as const, path: "/layers/conferencing", value: { username: "morgan-rehearsal" } },
679
+ { op: "replace" as const, path: "/layers/conferencing/username", value: "morgan-demo" },
680
+ { op: "replace" as const, path: "/layers/conferencing/allowlist", value: ["host@example.com"] },
681
+ { op: "add" as const, path: "/layers/conferencing/allowlist/-", value: "other@example.com" },
682
+ { op: "replace" as const, path: "/layers/conferencing/whitelabel", value: false },
683
+ ];
684
+ expect(validatePatchOperations(ops)).toEqual(ops);
685
+ for (const field of ["email", "aliased_from", "usernmae"]) {
686
+ expect(() => validatePatchOperations([
687
+ { op: "replace", path: `/layers/conferencing/${field}`, value: "invalid" },
688
+ ])).toThrow(/Unsupported pal patch path/);
689
+ }
690
+ });
691
+
651
692
  it("patches guardrails by id and tag, not by the removed grouped id", () => {
652
693
  expect(
653
694
  validatePatchOperations([
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.10.3"
3
- }
@@ -1 +0,0 @@
1
- export const VERSION = "0.10.3"; // x-release-please-version
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes