fast-agent-mcp 0.2.50__py3-none-any.whl → 0.2.51__py3-none-any.whl

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.

Potentially problematic release.


This version of fast-agent-mcp might be problematic. Click here for more details.

Files changed (31) hide show
  1. {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/METADATA +1 -1
  2. {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/RECORD +29 -12
  3. mcp_agent/cli/commands/quickstart.py +107 -0
  4. mcp_agent/llm/model_database.py +5 -1
  5. mcp_agent/llm/model_factory.py +5 -3
  6. mcp_agent/llm/providers/augmented_llm_openai.py +6 -1
  7. mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py +127 -0
  8. mcp_agent/llm/providers/google_converter.py +4 -0
  9. mcp_agent/resources/examples/tensorzero/.env.sample +2 -0
  10. mcp_agent/resources/examples/tensorzero/Makefile +31 -0
  11. mcp_agent/resources/examples/tensorzero/README.md +55 -0
  12. mcp_agent/resources/examples/tensorzero/agent.py +35 -0
  13. mcp_agent/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
  14. mcp_agent/resources/examples/tensorzero/demo_images/crab.png +0 -0
  15. mcp_agent/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
  16. mcp_agent/resources/examples/tensorzero/docker-compose.yml +105 -0
  17. mcp_agent/resources/examples/tensorzero/fastagent.config.yaml +19 -0
  18. mcp_agent/resources/examples/tensorzero/image_demo.py +67 -0
  19. mcp_agent/resources/examples/tensorzero/mcp_server/Dockerfile +25 -0
  20. mcp_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh +35 -0
  21. mcp_agent/resources/examples/tensorzero/mcp_server/mcp_server.py +31 -0
  22. mcp_agent/resources/examples/tensorzero/mcp_server/pyproject.toml +11 -0
  23. mcp_agent/resources/examples/tensorzero/simple_agent.py +25 -0
  24. mcp_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json +29 -0
  25. mcp_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +11 -0
  26. mcp_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +35 -0
  27. mcp_agent/llm/providers/augmented_llm_tensorzero.py +0 -441
  28. mcp_agent/llm/providers/multipart_converter_tensorzero.py +0 -201
  29. {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/WHEEL +0 -0
  30. {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/entry_points.txt +0 -0
  31. {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.2.50
3
+ Version: 0.2.51
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>
6
6
  License: Apache License
@@ -27,7 +27,7 @@ mcp_agent/cli/main.py,sha256=Oo13X7LB0Cf7JrkilQXz8Eqi_48cE0Rr2qqDUOQifEQ,3175
27
27
  mcp_agent/cli/terminal.py,sha256=GRwD-RGW7saIz2IOWZn5vD6JjiArscELBThm1GTFkuI,1065
28
28
  mcp_agent/cli/commands/check_config.py,sha256=15YK0mtDQbVopnMm3HBjOeY2-00FUHj6tt8RvaemKmI,21081
29
29
  mcp_agent/cli/commands/go.py,sha256=SHFJlO3SeZzAWvx_Gz72zXKA8n7XfaZ49W6UNS5mbV4,14668
30
- mcp_agent/cli/commands/quickstart.py,sha256=lcozUGP9RRO8xZaayJg4pQNeY5zDQs-eg-ABm0A15cI,16471
30
+ mcp_agent/cli/commands/quickstart.py,sha256=hwIr1F9zGRSQGf7kwvmirMIK7Qke2s6W95inZ-a2SMQ,21171
31
31
  mcp_agent/cli/commands/server_helpers.py,sha256=x5tD_qhf1W4D2li09sfOyfRWCOCa6lmpumYAPsEfIQs,3649
32
32
  mcp_agent/cli/commands/setup.py,sha256=eOEd4TL-b0DaDeSJMGOfNOsTEItoZ67W88eTP4aP-bo,6482
33
33
  mcp_agent/cli/commands/url_parser.py,sha256=5VdtcHRHzi67YignStVbz7u-rcvNNErw9oJLAUFOtEY,5855
@@ -67,8 +67,8 @@ mcp_agent/llm/augmented_llm_playback.py,sha256=rLzgai496e2RlxqQp_Bp0U-Y1FF1SGsWl
67
67
  mcp_agent/llm/augmented_llm_silent.py,sha256=IUnK_1Byy4D9TG0Pj46LFeNezgSTQ8d6MQIHWAImBwE,1846
68
68
  mcp_agent/llm/augmented_llm_slow.py,sha256=DDSD8bL2flmQrVHZm-UDs7sR8aHRWkDOcOW-mX_GPok,2067
69
69
  mcp_agent/llm/memory.py,sha256=pTOaTDV3EA3X68yKwEtUAu7s0xGIQQ_cKBhfYUnfR0w,8614
70
- mcp_agent/llm/model_database.py,sha256=7G_rAXRE2RFrly_2PRr5uji7fT0XqaWj_RwhpZVx1LU,10690
71
- mcp_agent/llm/model_factory.py,sha256=WyuQm0hETOxECA9pjCm-Oo5Oh28186nsSWmjSntw2SE,11784
70
+ mcp_agent/llm/model_database.py,sha256=ehNiw_d5y4f1t_ySJSigxN1NxikXEXFXbkO5E0gLX9M,10943
71
+ mcp_agent/llm/model_factory.py,sha256=dIVs0RBhVy31-8nAjXdnWSIUJmW5UKnQym_oeQNuNiU,11906
72
72
  mcp_agent/llm/prompt_utils.py,sha256=yWQHykoK13QRF7evHUKxVF0SpVLN-Bsft0Yixzvn0g0,4825
73
73
  mcp_agent/llm/provider_key_manager.py,sha256=LSWIgcXlrUS4sfBvQBCya82qC6NcXQPYLtDHwHNOXR4,3394
74
74
  mcp_agent/llm/provider_types.py,sha256=LfuVuFjcM_lMED0lkrNfKK8s8Fs1vbxugQsrcBE2CIY,1119
@@ -86,14 +86,13 @@ mcp_agent/llm/providers/augmented_llm_generic.py,sha256=5Uq8ZBhcFuQTt7koP_5ykolR
86
86
  mcp_agent/llm/providers/augmented_llm_google_native.py,sha256=c6zczfs-Iw70j3OYELHJ4S7CRwAddkeXinex_yLMhmU,22194
87
87
  mcp_agent/llm/providers/augmented_llm_google_oai.py,sha256=g_g46h-YuxqbRZiO_dVo5zO2OkX1yx7nb6xDaQbOvWs,1137
88
88
  mcp_agent/llm/providers/augmented_llm_groq.py,sha256=5pqWgOoEJpvL230rJekBNlmBzUegbgwYitArlXgAmY0,4424
89
- mcp_agent/llm/providers/augmented_llm_openai.py,sha256=veVi4NcIP5S7xiV5fZLCSRFSiQbU48xQye0z-xx7X8I,25183
89
+ mcp_agent/llm/providers/augmented_llm_openai.py,sha256=ncFlItw4DKKWFQ1czePye2Hpo_qzL22Yanc3aaOUuHA,25343
90
90
  mcp_agent/llm/providers/augmented_llm_openrouter.py,sha256=m3wS83fabBOmaZJH9gQ9sFw_2TB4xTb44WCOPB-2NJ4,2001
91
- mcp_agent/llm/providers/augmented_llm_tensorzero.py,sha256=wxNffqdM1Psvfyya6Pmo__BZjyrek55_8iTRoH4TboI,20577
91
+ mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py,sha256=D53Fry2AfBLOB5z9hM19U6_HMJeVNTpiBCAJb11ulNg,5503
92
92
  mcp_agent/llm/providers/augmented_llm_xai.py,sha256=MhlX91IUNynQ_NDknx4EQJLwg-NbR8lcHS1P4JuLOnA,1433
93
- mcp_agent/llm/providers/google_converter.py,sha256=xCUVw4W7lqBvJMgSKKdzW4Y00zmHBgCR6pOoWLYQQfw,16699
93
+ mcp_agent/llm/providers/google_converter.py,sha256=YmSfkkZR2YzR5DZduGaOW0v7BtjjindCIiuS8zOJ1VA,16941
94
94
  mcp_agent/llm/providers/multipart_converter_anthropic.py,sha256=QsgIwWJ14SNZsun3fKDQaUx5AYdk8X6UYeBgYlZgZN0,16607
95
95
  mcp_agent/llm/providers/multipart_converter_openai.py,sha256=8vBwX7PB62mV6pe4VvAj9YxzX1Dp1RJMZK1NWOMnioY,17998
96
- mcp_agent/llm/providers/multipart_converter_tensorzero.py,sha256=Tr3DgogthxqTw04ajblwE8aB3Ft42X7aSXsMlm5FP4k,8619
97
96
  mcp_agent/llm/providers/openai_multipart.py,sha256=qKBn7d3jSabnJmVgWweVzqh8q9mBqr09fsPmP92niAQ,6899
98
97
  mcp_agent/llm/providers/openai_utils.py,sha256=T4bTCL9f7DsoS_zoKgQKv_FUv_4n98vgbvaUpdWZJr8,1875
99
98
  mcp_agent/llm/providers/sampling_converter_anthropic.py,sha256=35WzBWkPklnuMlu5S6XsQIq0YL58NOy8Ja6A_l4m6eM,1612
@@ -155,6 +154,24 @@ mcp_agent/resources/examples/researcher/fastagent.config.yaml,sha256=TbVMHQCKcyt
155
154
  mcp_agent/resources/examples/researcher/researcher-eval.py,sha256=CR9m4lyoXijS1whvsBDuk6IA-RmNc6iOYbtloETkITY,1833
156
155
  mcp_agent/resources/examples/researcher/researcher-imp.py,sha256=oJxSVnLbZfIn71QbQR1E6j_m_UBrOOGP4SVljXErHLQ,7879
157
156
  mcp_agent/resources/examples/researcher/researcher.py,sha256=SZfExi-FfwYETzGt2O3caS3L5E6EemV3IUrJHyzZqHI,1333
157
+ mcp_agent/resources/examples/tensorzero/.env.sample,sha256=khV_apbP4XprpNuIaeVicnHaVHEkwIdWGyZCvW1OLDc,35
158
+ mcp_agent/resources/examples/tensorzero/Makefile,sha256=BOvcJvPBAJN2MDh8brLsy2leHGwuT_bBjPzakOsUSCU,427
159
+ mcp_agent/resources/examples/tensorzero/README.md,sha256=xsA1qWjg2mI240jlbeFYWjYm_pQLsGeQiPiSlEtayeQ,2126
160
+ mcp_agent/resources/examples/tensorzero/agent.py,sha256=8x_W-_LHbwC_onXWZfDIbVQe2PX6qEZ5JRjwIWGOEr4,1272
161
+ mcp_agent/resources/examples/tensorzero/docker-compose.yml,sha256=YgmWgoHHDDTGeqRlU8Z21mLdEqo48IoKZsnlXaDZkrc,2851
162
+ mcp_agent/resources/examples/tensorzero/fastagent.config.yaml,sha256=3uJJ9p-0evDG48zr2QneektO4fe_h4uRPh1dyWfe7-k,355
163
+ mcp_agent/resources/examples/tensorzero/image_demo.py,sha256=BVdCMg1o8r9A9cgKEPmEO84CBeBOxz9zNF9yBxyYCp4,2122
164
+ mcp_agent/resources/examples/tensorzero/simple_agent.py,sha256=BjbD6k9C5zNJl_vAzKKIVSyghYuOsF-LOzqxMTnEOJ4,858
165
+ mcp_agent/resources/examples/tensorzero/demo_images/clam.jpg,sha256=K1NWrhz5QMfgjZfDMMIVctWwbwTyJSsPHLDaUMbcn18,22231
166
+ mcp_agent/resources/examples/tensorzero/demo_images/crab.png,sha256=W7R3bSKKDmZCjxJEmFk0pBXVhXXhfPGM1gIiVuv_eu4,58413
167
+ mcp_agent/resources/examples/tensorzero/demo_images/shrimp.png,sha256=2r3c6yHE25MpVRDTTwxjAGs1ShJ2UI-qxJqbxa-9ew4,7806
168
+ mcp_agent/resources/examples/tensorzero/mcp_server/Dockerfile,sha256=pujKW5xDY5q0PvIYsn8Wsh9Tz2F3sVuKTJc3o8lgt4M,681
169
+ mcp_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh,sha256=yLUXZKd4mF2k_ZFAd6125ZstLmrtksePpfgCNdewSyU,1123
170
+ mcp_agent/resources/examples/tensorzero/mcp_server/mcp_server.py,sha256=8Wr6VzNFihri3mv9wLo37i5Ly1VWL4s4jSnfiRG7Ez0,933
171
+ mcp_agent/resources/examples/tensorzero/mcp_server/pyproject.toml,sha256=3AppZ_HbIEmRGg_phGuEOq-Q63CY_IIsrIBr658ka9U,228
172
+ mcp_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json,sha256=q81vtb8eyX1gU0qOhT_BFNo7nI2Lg2o-D_Bvp8watEI,626
173
+ mcp_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja,sha256=_Ekz9YuE76pkmwtcMNJeDlih2U5vPRgFB5wFojAVde8,501
174
+ mcp_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml,sha256=wYDKzHyX0A2x42d1vF5a72ot304iTP8_i5Y1rzAcCEA,890
158
175
  mcp_agent/resources/examples/workflows/chaining.py,sha256=tY0kA0U8s2rceAO4ogZFtpQEkiUWcrYnYDgHu_-4G50,889
159
176
  mcp_agent/resources/examples/workflows/evaluator.py,sha256=XJXrk5r1hrJzfZAMtQ7WIggy6qPttMJG1yqxYELO7C4,3101
160
177
  mcp_agent/resources/examples/workflows/fastagent.config.yaml,sha256=qaxk-p7Pl7JepdL3a7BTl0CIp4LHCXies7pFdVWS9xk,783
@@ -168,8 +185,8 @@ mcp_agent/resources/examples/workflows/short_story.txt,sha256=X3y_1AyhLFN2AKzCKv
168
185
  mcp_agent/tools/tool_definition.py,sha256=L3Pxl-uLEXqlVoo-bYuFTFALeI-2pIU44YgFhsTKEtM,398
169
186
  mcp_agent/ui/console_display.py,sha256=XXrHr950wSBSedEKUaaGkXjOzuFpQYzUKKiyaZ58Mps,28280
170
187
  mcp_agent/ui/console_display_legacy.py,sha256=sm2v61-IPVafbF7uUaOyhO2tW_zgFWOjNS83IEWqGgI,14931
171
- fast_agent_mcp-0.2.50.dist-info/METADATA,sha256=jNGAWFccNjB_-7zrb8G6ambu93q8jtpvKxiA4Jp3rkQ,31048
172
- fast_agent_mcp-0.2.50.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
173
- fast_agent_mcp-0.2.50.dist-info/entry_points.txt,sha256=QaX5kLdI0VdMPRdPUF1nkG_WdLUTNjp_icW6e3EhNYU,232
174
- fast_agent_mcp-0.2.50.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
175
- fast_agent_mcp-0.2.50.dist-info/RECORD,,
188
+ fast_agent_mcp-0.2.51.dist-info/METADATA,sha256=6gg7Cc2qW7R5rVOUtSyhlrbBtZyTEOisFsdU00tohUk,31048
189
+ fast_agent_mcp-0.2.51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
190
+ fast_agent_mcp-0.2.51.dist-info/entry_points.txt,sha256=QaX5kLdI0VdMPRdPUF1nkG_WdLUTNjp_icW6e3EhNYU,232
191
+ fast_agent_mcp-0.2.51.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
192
+ fast_agent_mcp-0.2.51.dist-info/RECORD,,
@@ -76,6 +76,25 @@ EXAMPLE_TYPES = {
76
76
  ],
77
77
  "create_subdir": True,
78
78
  },
79
+ "tensorzero": {
80
+ "description": "A complete example showcasing the TensorZero integration.\n"
81
+ "Includes the T0 Gateway, an MCP server, an interactive agent, and \n"
82
+ "multi-modal functionality.",
83
+ "files": [
84
+ ".env.sample",
85
+ "Makefile",
86
+ "README.md",
87
+ "agent.py",
88
+ "docker-compose.yml",
89
+ "fastagent.config.yaml",
90
+ "image_demo.py",
91
+ "simple_agent.py",
92
+ "mcp_server/",
93
+ "demo_images/",
94
+ "tensorzero_config/"
95
+ ],
96
+ "create_subdir": True,
97
+ },
79
98
  }
80
99
 
81
100
 
@@ -225,6 +244,27 @@ def copy_example_files(example_type: str, target_dir: Path, force: bool = False)
225
244
  return created
226
245
 
227
246
 
247
+ def copy_project_template(source_dir: Path, dest_dir: Path, console: Console, force: bool = False):
248
+ """
249
+ Recursively copies a project template directory.
250
+ This is a helper to handle project-based quickstarts like TensorZero.
251
+ """
252
+ if dest_dir.exists():
253
+ if force:
254
+ console.print(f"[yellow]--force specified. Removing existing directory: {dest_dir}[/yellow]")
255
+ shutil.rmtree(dest_dir)
256
+ else:
257
+ console.print(f"[bold yellow]Directory '{dest_dir.name}' already exists.[/bold yellow] Use --force to overwrite.")
258
+ return False
259
+
260
+ try:
261
+ shutil.copytree(source_dir, dest_dir)
262
+ return True
263
+ except Exception as e:
264
+ console.print(f"[red]Error copying project template: {e}[/red]")
265
+ return False
266
+
267
+
228
268
  def show_overview() -> None:
229
269
  """Display an overview of available examples in a nicely formatted table."""
230
270
  console.print("\n[bold cyan]fast-agent quickstarts[/bold cyan]")
@@ -397,6 +437,73 @@ def _show_completion_message(example_type: str, created: list[str]) -> None:
397
437
  console.print("\n[yellow]No files were created.[/yellow]")
398
438
 
399
439
 
440
+ @app.command(name="tensorzero", help="Create the TensorZero integration example project.")
441
+ def tensorzero(
442
+ directory: Path = typer.Argument(
443
+ Path("."),
444
+ help="Directory where the 'tensorzero' project folder will be created.",
445
+ ),
446
+ force: bool = typer.Option(False, "--force", "-f", help="Force overwrite if project directory exists"),
447
+ ):
448
+ """Create the TensorZero project example."""
449
+ console.print("[bold green]Setting up the TensorZero quickstart example...[/bold green]")
450
+
451
+ dest_project_dir = directory.resolve() / "tensorzero"
452
+
453
+ # --- Find Source Directory ---
454
+ from importlib.resources import files
455
+ try:
456
+ # This path MUST match the "to" path from hatch_build.py
457
+ source_dir = files("mcp_agent").joinpath("resources").joinpath("examples").joinpath("tensorzero")
458
+ if not source_dir.is_dir():
459
+ raise FileNotFoundError # Fallback to dev mode if resource isn't a dir
460
+ except (ImportError, ModuleNotFoundError, FileNotFoundError):
461
+ console.print("[yellow]Package resources not found. Falling back to development mode.[/yellow]")
462
+ # This path is relative to the project root in a development environment
463
+ source_dir = Path(__file__).parent.parent.parent.parent / "examples" / "tensorzero"
464
+
465
+ if not source_dir.exists() or not source_dir.is_dir():
466
+ console.print(f"[red]Error: Source project directory not found at '{source_dir}'[/red]")
467
+ raise typer.Exit(1)
468
+
469
+ console.print(f"Source directory: [dim]{source_dir}[/dim]")
470
+ console.print(f"Destination: [dim]{dest_project_dir}[/dim]")
471
+
472
+ # --- Copy Project and Show Message ---
473
+ if copy_project_template(source_dir, dest_project_dir, console, force):
474
+ console.print(
475
+ f"\n[bold green]✅ Success![/bold green] Your TensorZero project has been created in: [cyan]{dest_project_dir}[/cyan]"
476
+ )
477
+ console.print("\n[bold yellow]Next Steps:[/bold yellow]")
478
+ console.print("\n1. [bold]Navigate to your new project directory:[/bold]")
479
+ console.print(f" [cyan]cd {dest_project_dir.relative_to(Path.cwd())}[/cyan]")
480
+
481
+ console.print("\n2. [bold]Set up your API keys:[/bold]")
482
+ console.print(" [cyan]cp .env.sample .env[/cyan]")
483
+ console.print(
484
+ " [dim]Then, open the new '.env' file and add your OpenAI or Anthropic API key.[/dim]"
485
+ )
486
+
487
+ console.print("\n3. [bold]Start the required services (TensorZero Gateway & MCP Server):[/bold]")
488
+ console.print(" [cyan]docker compose up --build -d[/cyan]")
489
+ console.print(
490
+ " [dim](This builds and starts the necessary containers in the background)[/dim]"
491
+ )
492
+
493
+ console.print("\n4. [bold]Run the interactive agent:[/bold]")
494
+ console.print(" [cyan]make agent[/cyan] (or `uv run agent.py`)")
495
+ console.print("\nEnjoy exploring the TensorZero integration with fast-agent! ✨")
496
+
497
+
498
+ @app.command(name="t0", help="Alias for the TensorZero quickstart.", hidden=True)
499
+ def t0_alias(
500
+ directory: Path = typer.Argument(Path("."), help="Directory for the 'tensorzero' project folder."),
501
+ force: bool = typer.Option(False, "--force", "-f", help="Force overwrite"),
502
+ ):
503
+ """Alias for the `tensorzero` command."""
504
+ tensorzero(directory, force)
505
+
506
+
400
507
  @app.callback(invoke_without_command=True)
401
508
  def main(ctx: typer.Context) -> None:
402
509
  """Quickstart applications for fast-agent."""
@@ -120,7 +120,9 @@ class ModelDatabase:
120
120
  OPENAI_O3_MINI_SERIES = ModelParameters(
121
121
  context_window=200000, max_output_tokens=100000, tokenizes=TEXT_ONLY
122
122
  )
123
-
123
+ OPENAI_GPT_OSS_SERIES = ModelParameters(
124
+ context_window=131072, max_output_tokens=32766, tokenizes=TEXT_ONLY, json_mode="object"
125
+ )
124
126
  # TODO update to 32000
125
127
  ANTHROPIC_OPUS_4_VERSIONED = ModelParameters(
126
128
  context_window=200000, max_output_tokens=32000, tokenizes=ANTHROPIC_MULTIMODAL
@@ -236,6 +238,8 @@ class ModelDatabase:
236
238
  "moonshotai/kimi-k2-instruct": KIMI_MOONSHOT,
237
239
  "qwen/qwen3-32b": QWEN3_REASONER,
238
240
  "deepseek-r1-distill-llama-70b": DEEPSEEK_DISTILL,
241
+ "openai/gpt-oss-120b": OPENAI_GPT_OSS_SERIES,
242
+ "openai/gpt-oss-20b": OPENAI_GPT_OSS_SERIES,
239
243
  }
240
244
 
241
245
  @classmethod
@@ -22,7 +22,7 @@ from mcp_agent.llm.providers.augmented_llm_google_oai import GoogleOaiAugmentedL
22
22
  from mcp_agent.llm.providers.augmented_llm_groq import GroqAugmentedLLM
23
23
  from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
24
24
  from mcp_agent.llm.providers.augmented_llm_openrouter import OpenRouterAugmentedLLM
25
- from mcp_agent.llm.providers.augmented_llm_tensorzero import TensorZeroAugmentedLLM
25
+ from mcp_agent.llm.providers.augmented_llm_tensorzero_openai import TensorZeroOpenAIAugmentedLLM
26
26
  from mcp_agent.llm.providers.augmented_llm_xai import XAIAugmentedLLM
27
27
  from mcp_agent.mcp.interfaces import AugmentedLLMProtocol
28
28
 
@@ -39,7 +39,7 @@ LLMClass = Union[
39
39
  Type[SlowLLM],
40
40
  Type[DeepSeekAugmentedLLM],
41
41
  Type[OpenRouterAugmentedLLM],
42
- Type[TensorZeroAugmentedLLM],
42
+ Type[TensorZeroOpenAIAugmentedLLM],
43
43
  Type[GoogleNativeAugmentedLLM],
44
44
  Type[GenericAugmentedLLM],
45
45
  Type[AzureOpenAIAugmentedLLM],
@@ -144,6 +144,8 @@ class ModelFactory:
144
144
  "gemini25": "gemini-2.5-flash-preview-05-20",
145
145
  "gemini25pro": "gemini-2.5-pro-preview-05-06",
146
146
  "kimi": "groq.moonshotai/kimi-k2-instruct",
147
+ "gpt-oss": "groq.openai/gpt-oss-120b",
148
+ "gpt-oss-20b": "groq.openai/gpt-oss-20b",
147
149
  }
148
150
 
149
151
  # Mapping of providers to their LLM classes
@@ -157,7 +159,7 @@ class ModelFactory:
157
159
  Provider.GOOGLE: GoogleNativeAugmentedLLM,
158
160
  Provider.XAI: XAIAugmentedLLM,
159
161
  Provider.OPENROUTER: OpenRouterAugmentedLLM,
160
- Provider.TENSORZERO: TensorZeroAugmentedLLM,
162
+ Provider.TENSORZERO: TensorZeroOpenAIAugmentedLLM,
161
163
  Provider.AZURE: AzureOpenAIAugmentedLLM,
162
164
  Provider.ALIYUN: AliyunAugmentedLLM,
163
165
  Provider.BEDROCK: BedrockAugmentedLLM,
@@ -391,8 +391,13 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
391
391
  # Convert to dict and remove None values
392
392
  message_dict = message.model_dump()
393
393
  message_dict = {k: v for k, v in message_dict.items() if v is not None}
394
- if model_name == "deepseek-r1-distill-llama-70b":
394
+ if model_name in (
395
+ "deepseek-r1-distill-llama-70b",
396
+ "openai/gpt-oss-120b",
397
+ "openai/gpt-oss-20b",
398
+ ):
395
399
  message_dict.pop("reasoning", None)
400
+ message_dict.pop("channel", None)
396
401
 
397
402
  messages.append(message_dict)
398
403
 
@@ -0,0 +1,127 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from openai.types.chat import ChatCompletionMessageParam, ChatCompletionSystemMessageParam
4
+
5
+ from mcp_agent.core.request_params import RequestParams
6
+ from mcp_agent.llm.provider_types import Provider
7
+ from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
8
+
9
+
10
+ class TensorZeroOpenAIAugmentedLLM(OpenAIAugmentedLLM):
11
+ """
12
+ An LLM augmentation that interacts with TensorZero's OpenAI-compatible inference endpoint.
13
+ This class extends the base OpenAIAugmentedLLM to handle TensorZero-specific
14
+ features, such as system template variables and custom parameters.
15
+ """
16
+
17
+ def __init__(self, *args, **kwargs) -> None:
18
+ """
19
+ Initializes the TensorZeroOpenAIAugmentedLLM.
20
+
21
+ Args:
22
+ *args: Variable length argument list.
23
+ **kwargs: Arbitrary keyword arguments.
24
+ """
25
+ self._t0_episode_id = kwargs.pop("episode_id", None)
26
+ self._t0_function_name = kwargs.get("model", "")
27
+
28
+ super().__init__(*args, provider=Provider.TENSORZERO, **kwargs)
29
+ self.logger.info("TensorZeroOpenAIAugmentedLLM initialized.")
30
+
31
+ def _initialize_default_params(self, kwargs: dict) -> RequestParams:
32
+ """
33
+ Initializes TensorZero-specific default parameters. Ensures the model name
34
+ is correctly prefixed for the TensorZero API.
35
+ """
36
+ model = kwargs.get("model", "")
37
+ if not model.startswith("tensorzero::"):
38
+ model = f"tensorzero::function_name::{model}"
39
+
40
+ self.logger.debug(f"Initializing with TensorZero model: {model}")
41
+
42
+ return RequestParams(
43
+ model=model,
44
+ systemPrompt=self.instruction,
45
+ parallel_tool_calls=True,
46
+ max_iterations=10,
47
+ use_history=True,
48
+ )
49
+
50
+ def _base_url(self) -> str:
51
+ """
52
+ Constructs the TensorZero OpenAI-compatible endpoint URL.
53
+ """
54
+ default_url = "http://localhost:3000/openai/v1"
55
+ if self.context and self.context.config and hasattr(self.context.config, "tensorzero"):
56
+ base_url = getattr(self.context.config.tensorzero, "base_url", default_url)
57
+ # Ensure the path is correctly appended
58
+ if not base_url.endswith('/openai/v1'):
59
+ base_url = f"{base_url.rstrip('/')}/openai/v1"
60
+ self.logger.debug(f"Using TensorZero base URL from config: {base_url}")
61
+ return base_url
62
+ self.logger.debug(f"Using default TensorZero base URL: {default_url}")
63
+ return default_url
64
+
65
+ def _prepare_api_request(
66
+ self,
67
+ messages: List[ChatCompletionMessageParam],
68
+ tools: Optional[List[Any]],
69
+ request_params: RequestParams
70
+ ) -> Dict[str, Any]:
71
+ """
72
+ Prepares the API request for the TensorZero OpenAI-compatible endpoint.
73
+ This method injects system template variables and other TensorZero-specific
74
+ parameters into the request. It also handles multimodal inputs.
75
+ """
76
+ self.logger.debug("Preparing API request for TensorZero OpenAI endpoint.")
77
+
78
+ # Start with the base arguments from the parent class
79
+ arguments = super()._prepare_api_request(messages, tools, request_params)
80
+
81
+ # Handle system template variables
82
+ if request_params.template_vars:
83
+ self.logger.debug(f"Injecting template variables: {request_params.template_vars}")
84
+ system_message_found = False
85
+ for i, msg in enumerate(messages):
86
+ if msg.get("role") == "system":
87
+ # If content is a string, convert it to the TensorZero format
88
+ if isinstance(msg.get("content"), str):
89
+ messages[i] = ChatCompletionSystemMessageParam(
90
+ role="system",
91
+ content=[request_params.template_vars]
92
+ )
93
+ elif isinstance(msg.get("content"), list):
94
+ # If content is already a list, merge the template vars
95
+ msg["content"][0].update(request_params.template_vars)
96
+ system_message_found = True
97
+ break
98
+
99
+ if not system_message_found:
100
+ # If no system message exists, create one
101
+ messages.insert(0, ChatCompletionSystemMessageParam(
102
+ role="system",
103
+ content=[request_params.template_vars]
104
+ ))
105
+
106
+ # Add TensorZero-specific extra body parameters
107
+ extra_body = arguments.get("extra_body", {})
108
+
109
+ if self._t0_episode_id:
110
+ extra_body["tensorzero::episode_id"] = str(self._t0_episode_id)
111
+ self.logger.debug(f"Added tensorzero::episode_id: {self._t0_episode_id}")
112
+
113
+ # Merge metadata arguments
114
+ if request_params.metadata and isinstance(request_params.metadata, dict):
115
+ t0_args = request_params.metadata.get("tensorzero_arguments")
116
+ if t0_args:
117
+ self.logger.debug(f"Merging tensorzero_arguments from metadata: {t0_args}")
118
+ for msg in messages:
119
+ if msg.get("role") == "system" and isinstance(msg.get("content"), list):
120
+ msg["content"][0].update(t0_args)
121
+ break
122
+
123
+ if extra_body:
124
+ arguments["extra_body"] = extra_body
125
+
126
+ self.logger.debug(f"Final API request arguments: {arguments}")
127
+ return arguments
@@ -336,6 +336,10 @@ class GoogleConverter:
336
336
  """
337
337
  Converts a single google.genai types.Content to a fast-agent PromptMessageMultipart.
338
338
  """
339
+ # Official fix for GitHub issue #207: Handle None content or content.parts
340
+ if content is None or not hasattr(content, "parts") or content.parts is None:
341
+ return PromptMessageMultipart(role="assistant", content=[])
342
+
339
343
  if content.role == "model" and any(part.function_call for part in content.parts):
340
344
  return PromptMessageMultipart(role="assistant", content=[])
341
345
 
@@ -0,0 +1,2 @@
1
+ OPENAI_API_KEY=
2
+ ANTHROPIC_API_KEY=
@@ -0,0 +1,31 @@
1
+ .PHONY: all
2
+
3
+ build:
4
+ docker compose build
5
+
6
+ up:
7
+ docker compose up -d
8
+
9
+ logs:
10
+ docker compose logs -f
11
+
12
+ tensorzero-logs:
13
+ docker compose logs -f gateway
14
+
15
+ mcp-logs:
16
+ docker compose logs -f mcp-server
17
+
18
+ minio-logs:
19
+ docker compose logs -f minio
20
+
21
+ stop:
22
+ docker compose stop
23
+
24
+ agent:
25
+ uv run agent.py --model=tensorzero.test_chat
26
+
27
+ simple-agent:
28
+ uv run simple_agent.py --model=tensorzero.simple_chat
29
+
30
+ image-test:
31
+ uv run image_demo.py
@@ -0,0 +1,55 @@
1
+ # About the tensorzero / fast-agent integration
2
+
3
+ [TensorZero](https://www.tensorzero.com/) is an open source project designed to help LLM application developers rapidly improve their inference calls. Its core features include:
4
+
5
+ - A uniform inference interface to all leading LLM platforms.
6
+ - The ability to dynamic route to different platforms and program failovers.
7
+ - Automated parameter tuning and training
8
+ - Advance templating features for your system prompts
9
+ - Organization of LLM inference data into a Clickhouse DB allowing for sophisticated downstream analytics
10
+ - A bunch of other good stuff is always in development
11
+
12
+ `tensorzero` is powerful heavy, so we provide here a quickstart example that combines the basic components of `fast-agent`, an MCP server, `tensorzero`, and other supporting services into a cohesive whole.
13
+
14
+ ## Quickstart guide
15
+
16
+ - Build and activate the `uv` `fast-agent` environment
17
+ - Ensure that ports `3000`, `4000`, `8000`, `9000`, and `9001` are unallocated before running this demo.
18
+ - Run `cp .env.sample .env` and then drop in at least one of `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`. Make sure the accounts are funded.
19
+ - `make up`
20
+ - `make agent`
21
+
22
+ The demo test's our implementation's ability to:
23
+
24
+ - Implement the T0 model gateway as an inference backend
25
+ - Implement T0's dynamic templating feature
26
+ - Have in-conversation memory
27
+ - Describe and execute tool calls
28
+ - Remember previous tool calls
29
+
30
+ A version of a conversation to test all of this could be:
31
+
32
+ ```
33
+ Hi.
34
+
35
+ Tell me a poem.
36
+
37
+ Do you have any tools that you can use?
38
+
39
+ Please demonstrate the use of that tool on your last response.
40
+
41
+ Please summarize the conversation so far.
42
+
43
+ What tool calls have you executed in this session, and what were their results?
44
+ ```
45
+
46
+ ## Multimodal support
47
+
48
+ Run `make image-test` to test the gateway's ability to handle base64-encoded image data
49
+
50
+ ## Development notes:
51
+
52
+ - `make stop` will stop the MCP server and the tensorzero server
53
+ - `make tenzorzero-logs` will tail the tensorzero server logs
54
+ - `make mcp-logs` will tail the MCP server logs
55
+ - Generic `make logs` dumps all log output from all services to terminal
@@ -0,0 +1,35 @@
1
+ import asyncio
2
+
3
+ from mcp_agent.core.fastagent import FastAgent
4
+ from mcp_agent.core.request_params import RequestParams
5
+
6
+ # Explicitly provide the path to the config file in the current directory
7
+ CONFIG_FILE = "fastagent.config.yaml"
8
+ fast = FastAgent("fast-agent example", config_path=CONFIG_FILE, ignore_unknown_args=True)
9
+
10
+ # Define T0 system variables here
11
+ my_t0_system_vars = {
12
+ "TEST_VARIABLE_1": "Roses are red",
13
+ "TEST_VARIABLE_2": "Violets are blue",
14
+ "TEST_VARIABLE_3": "Sugar is sweet",
15
+ "TEST_VARIABLE_4": "Vibe code responsibly 👍",
16
+ }
17
+
18
+
19
+ @fast.agent(
20
+ name="default",
21
+ instruction="""
22
+ You are an agent dedicated to helping developers understand the relationship between TensoZero and fast-agent. If the user makes a request
23
+ that requires you to invoke the test tools, please do so. When you use the tool, describe your rationale for doing so.
24
+ """,
25
+ servers=["tester"],
26
+ request_params=RequestParams(template_vars=my_t0_system_vars),
27
+ )
28
+ async def main():
29
+ async with fast.run() as agent_app: # Get the AgentApp wrapper
30
+ print("\nStarting interactive session with template_vars set via decorator...")
31
+ await agent_app.interactive()
32
+
33
+
34
+ if __name__ == "__main__":
35
+ asyncio.run(main()) # type: ignore