fast-agent-mcp 0.2.20__py3-none-any.whl → 0.2.22__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.2.20
3
+ Version: 0.2.22
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
6
6
  License: Apache License
@@ -213,7 +213,7 @@ Requires-Dist: a2a-types>=0.1.0
213
213
  Requires-Dist: aiohttp>=3.11.13
214
214
  Requires-Dist: anthropic>=0.49.0
215
215
  Requires-Dist: fastapi>=0.115.6
216
- Requires-Dist: mcp==1.6.0
216
+ Requires-Dist: mcp>=1.8.0
217
217
  Requires-Dist: openai>=1.63.2
218
218
  Requires-Dist: opentelemetry-distro>=0.50b0
219
219
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.29.0
@@ -224,6 +224,7 @@ Requires-Dist: pydantic-settings>=2.7.0
224
224
  Requires-Dist: pydantic>=2.10.4
225
225
  Requires-Dist: pyyaml>=6.0.2
226
226
  Requires-Dist: rich>=13.9.4
227
+ Requires-Dist: tensorzero>=2025.4.7
227
228
  Requires-Dist: typer>=0.15.1
228
229
  Provides-Extra: dev
229
230
  Requires-Dist: anthropic>=0.42.0; extra == 'dev'
@@ -260,6 +261,7 @@ The simple declarative syntax lets you concentrate on composing your Prompts and
260
261
  `fast-agent` is multi-modal, supporting Images and PDFs for both Anthropic and OpenAI endpoints via Prompts, Resources and MCP Tool Call results. The inclusion of passthrough and playback LLMs enable rapid development and test of Python glue-code for your applications.
261
262
 
262
263
  > [!IMPORTANT]
264
+ >
263
265
  > `fast-agent` The fast-agent documentation repo is here: https://github.com/evalstate/fast-agent-docs. Please feel free to submit PRs for documentation, experience reports or other content you think others may find helpful. All help and feedback warmly received.
264
266
 
265
267
  ### Agent Application Development
@@ -277,12 +279,12 @@ Simple model selection makes testing Model <-> MCP Server interaction painless.
277
279
  Start by installing the [uv package manager](https://docs.astral.sh/uv/) for Python. Then:
278
280
 
279
281
  ```bash
280
- uv pip install fast-agent-mcp # install fast-agent!
282
+ uv pip install fast-agent-mcp # install fast-agent!
281
283
 
282
- fast-agent setup # create an example agent and config files
283
- uv run agent.py # run your first agent
284
- uv run agent.py --model=o3-mini.low # specify a model
285
- fast-agent quickstart workflow # create "building effective agents" examples
284
+ uv run fast-agent setup # create an example agent and config files
285
+ uv run agent.py # run your first agent
286
+ uv run agent.py --model=o3-mini.low # specify a model
287
+ uv run fast-agent quickstart workflow # create "building effective agents" examples
286
288
  ```
287
289
 
288
290
  Other quickstart examples include a Researcher Agent (with Evaluator-Optimizer workflow) and Data Analysis Agent (similar to the ChatGPT experience), demonstrating MCP Roots support.
@@ -1,10 +1,10 @@
1
1
  mcp_agent/__init__.py,sha256=18T0AG0W9sJhTY38O9GFFOzliDhxx9p87CvRyti9zbw,1620
2
2
  mcp_agent/app.py,sha256=WRsiUdwy_9IAnaGRDwuLm7pzgQpt2wgsg10vBOpfcwM,5539
3
- mcp_agent/config.py,sha256=_b5JeS2nWHScSUUTu6wYxXzdfKefoqII305ecKcw7Gs,12248
3
+ mcp_agent/config.py,sha256=ZC4SiIVbxVn7-hUfv3RFj6fNrXxvci6gmUNCGM7vzs8,12624
4
4
  mcp_agent/console.py,sha256=Gjf2QLFumwG1Lav__c07X_kZxxEUSkzV-1_-YbAwcwo,813
5
5
  mcp_agent/context.py,sha256=Kb3s_0MolHx7AeTs1NVcY3ly-xFBd35o8LT7Srpx9is,7334
6
6
  mcp_agent/context_dependent.py,sha256=QXfhw3RaQCKfscEEBRGuZ3sdMWqkgShz2jJ1ivGGX1I,1455
7
- mcp_agent/event_progress.py,sha256=3dqk5Pn1tAG_m_wn4IPNwLWLyzm7CyKIidqHN-4l-JY,2736
7
+ mcp_agent/event_progress.py,sha256=b1VKlQQF2AgPMb6XHjlJAVoPdx8GuxRTUk2g-4lBNm0,2749
8
8
  mcp_agent/mcp_server_registry.py,sha256=jUmCdfcpTitXm1-3TxpWsdRWY_8phdKNYgXwB16ZSVU,10100
9
9
  mcp_agent/progress_display.py,sha256=GeJU9VUt6qKsFVymG688hCMVCsAygG9ifiiEb5IcbN4,361
10
10
  mcp_agent/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -23,7 +23,7 @@ mcp_agent/cli/__main__.py,sha256=AVZ7tQFhU_sDOGuUGJq8ujgKtcxsYJBJwHbVaaiRDlI,166
23
23
  mcp_agent/cli/main.py,sha256=XjrgXMBaPKkVqAFo8T9LJz6Tp1-ivrKDOuNYWke99YA,3090
24
24
  mcp_agent/cli/terminal.py,sha256=GRwD-RGW7saIz2IOWZn5vD6JjiArscELBThm1GTFkuI,1065
25
25
  mcp_agent/cli/commands/check_config.py,sha256=9Ryxo_fLInm3YKdYv46yLrAJgnQtMisGreu6Kkriw2g,16677
26
- mcp_agent/cli/commands/go.py,sha256=DJpmq4n-p5r8BXH10UqBOexmLND-zSODl5f-w4noR5Q,4304
26
+ mcp_agent/cli/commands/go.py,sha256=2UY8TSDwhh_-p-WYXrZz3pEv3-2eTdBl5Lxy3JyJV0E,6057
27
27
  mcp_agent/cli/commands/quickstart.py,sha256=SM3CHMzDgvTxIpKjFuX9BrS_N1vRoXNBDaO90aWx1Rk,14586
28
28
  mcp_agent/cli/commands/setup.py,sha256=eOEd4TL-b0DaDeSJMGOfNOsTEItoZ67W88eTP4aP-bo,6482
29
29
  mcp_agent/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -38,7 +38,7 @@ mcp_agent/core/fastagent.py,sha256=WEEGz2WBAddDGNeWJwqwFIPLiQnLjaNxZLoMR0peyyU,2
38
38
  mcp_agent/core/interactive_prompt.py,sha256=w3VyRzW4hzn0xhWZRwo_qRRAD5WVSrJYe8QDe1XZ55Y,24252
39
39
  mcp_agent/core/mcp_content.py,sha256=2D7KHY9mG_vxoDwFLKvsPQV9VRIzHItM7V-jcEnACh8,8878
40
40
  mcp_agent/core/prompt.py,sha256=qnintOUGEoDPYLI9bu9G2OlgVMCe5ZPUZilgMzydXhc,7919
41
- mcp_agent/core/request_params.py,sha256=loYf13DN7e-DsdYRd37jWkJWJGwVBL-iFkcANP1J60Q,1366
41
+ mcp_agent/core/request_params.py,sha256=vRfAz9T6Ir-0oeJ4qEdO62LDOzoLwBuuXcBcdh6WPZ8,1576
42
42
  mcp_agent/core/validation.py,sha256=RIBKFlh0GJg4rTcFQXoXp8A0sK1HpsCigKcYSK3gFaY,12090
43
43
  mcp_agent/executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
44
  mcp_agent/executor/executor.py,sha256=E44p6d-o3OMRoP_dNs_cDnyti91LQ3P9eNU88mSi1kc,9462
@@ -48,26 +48,28 @@ mcp_agent/human_input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
48
48
  mcp_agent/human_input/handler.py,sha256=s712Z5ssTCwjL9-VKoIdP5CtgMh43YvepynYisiWTTA,3144
49
49
  mcp_agent/human_input/types.py,sha256=RtWBOVzy8vnYoQrc36jRLn8z8N3C4pDPMBN5vF6qM5Y,1476
50
50
  mcp_agent/llm/__init__.py,sha256=d8zgwG-bRFuwiMNMYkywg_qytk4P8lawyld_meuUmHI,68
51
- mcp_agent/llm/augmented_llm.py,sha256=ASe604OhrMZ9dVoGEUEpUQaY6fFamz4gL8ttzWP_9m0,24212
51
+ mcp_agent/llm/augmented_llm.py,sha256=CqtSGo_QrHE73tz_DHMd0wdt2F41gwuUu5Bue51FNm4,24199
52
52
  mcp_agent/llm/augmented_llm_passthrough.py,sha256=zHcctNpwg4EFJvD1x9Eg443SVX-uyzFphLikwF_yVE0,6288
53
53
  mcp_agent/llm/augmented_llm_playback.py,sha256=6L_RWIK__R67oZK7u3Xt3hWy1T2LnHXIO-efqgP3tPw,4177
54
54
  mcp_agent/llm/memory.py,sha256=HQ_c1QemOUjrkY6Z2omE6BG5fXga7y4jN7KCMOuGjPs,3345
55
- mcp_agent/llm/model_factory.py,sha256=QK3RrEhpvafKRlTFYR8Z9oNJRGjO7J9wIx5TGcDu6As,7649
55
+ mcp_agent/llm/model_factory.py,sha256=h3NJSa0yPa9iiLojEqBhIm9wgEBB46ZBibe44MnskHM,8089
56
56
  mcp_agent/llm/prompt_utils.py,sha256=yWQHykoK13QRF7evHUKxVF0SpVLN-Bsft0Yixzvn0g0,4825
57
57
  mcp_agent/llm/provider_key_manager.py,sha256=-K_FuibN6hdSnweT32lB8mKTfCARnbja6zYYs0ErTKg,2802
58
- mcp_agent/llm/provider_types.py,sha256=3IRRt9UbIHZHVJq1KF1XYfzsQtF9gj_gBNtU3hukIaY,308
58
+ mcp_agent/llm/provider_types.py,sha256=oWwXTlyr6hIzU_QLJ5T-UwxZGo5e4Pjwtahz2cr1PHg,364
59
59
  mcp_agent/llm/sampling_converter.py,sha256=C7wPBlmT0eD90XWabC22zkxsrVHKCrjwIwg6cG628cI,2926
60
60
  mcp_agent/llm/sampling_format_converter.py,sha256=xGz4odHpOcP7--eFaJaFtUR8eR9jxZS7MnLH6J7n0EU,1263
61
61
  mcp_agent/llm/providers/__init__.py,sha256=heVxtmuqFJOnjjxHz4bWSqTAxXoN1E8twC_gQ_yJpHk,265
62
62
  mcp_agent/llm/providers/anthropic_utils.py,sha256=vYDN5G5jKMhD2CQg8veJYab7tvvzYkDMq8M1g_hUAQg,3275
63
- mcp_agent/llm/providers/augmented_llm_anthropic.py,sha256=RQ4r5Q84VJ_dyuNo23b-EMzvq6RrpspzIQWtfVUfw6M,15468
63
+ mcp_agent/llm/providers/augmented_llm_anthropic.py,sha256=gK_IvllVBNJUUrSfpgFpdhM-d4liCt0MLq7d2lXS7RI,15510
64
64
  mcp_agent/llm/providers/augmented_llm_deepseek.py,sha256=NiZK5nv91ZS2VgVFXpbsFNFYLsLcppcbo_RstlRMd7I,1145
65
65
  mcp_agent/llm/providers/augmented_llm_generic.py,sha256=5Uq8ZBhcFuQTt7koP_5ykolREh2iWu8zKhNbh3pM9lQ,1210
66
66
  mcp_agent/llm/providers/augmented_llm_google.py,sha256=N0a2fphVtkvNYxKQpEX6J4tlO1C_mRw4sw3LBXnrOeI,1130
67
- mcp_agent/llm/providers/augmented_llm_openai.py,sha256=TumZs1y678IvyvYIehf8xSDqYWqC44dWrIbqFGtz03g,14085
67
+ mcp_agent/llm/providers/augmented_llm_openai.py,sha256=0C7BOB7i3xo0HsMCTagRSQ8Hsywb-31mot26OfohzCU,14478
68
68
  mcp_agent/llm/providers/augmented_llm_openrouter.py,sha256=V_TlVKm92GHBxYIo6gpvH_6cAaIdppS25Tz6x5T7LW0,2341
69
+ mcp_agent/llm/providers/augmented_llm_tensorzero.py,sha256=Mol_Wzj_ZtccW-LMw0oFwWUt1m1yfofloay9QYNP23c,20729
69
70
  mcp_agent/llm/providers/multipart_converter_anthropic.py,sha256=t5lHYGfFUacJldnrVtMNW-8gEMoto8Y7hJkDrnyZR-Y,16650
70
71
  mcp_agent/llm/providers/multipart_converter_openai.py,sha256=XPIulWntNpZWNGWrc240StPzok2RqrDAV7OigDwQ1uU,15850
72
+ mcp_agent/llm/providers/multipart_converter_tensorzero.py,sha256=BFTdyVk42HZskDAuTHicfDTUJq89d1fz8C9nAOuHxlE,8646
71
73
  mcp_agent/llm/providers/openai_multipart.py,sha256=qKBn7d3jSabnJmVgWweVzqh8q9mBqr09fsPmP92niAQ,6899
72
74
  mcp_agent/llm/providers/openai_utils.py,sha256=T4bTCL9f7DsoS_zoKgQKv_FUv_4n98vgbvaUpdWZJr8,1875
73
75
  mcp_agent/llm/providers/sampling_converter_anthropic.py,sha256=35WzBWkPklnuMlu5S6XsQIq0YL58NOy8Ja6A_l4m6eM,1612
@@ -83,9 +85,9 @@ mcp_agent/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
85
  mcp_agent/mcp/gen_client.py,sha256=fAVwFVCgSamw4PwoWOV4wrK9TABx1S_zZv8BctRyF2k,3030
84
86
  mcp_agent/mcp/interfaces.py,sha256=PAou8znAl2HgtvfCpLQOZFbKra9F72OcVRfBJbboNX8,6965
85
87
  mcp_agent/mcp/logger_textio.py,sha256=vljC1BtNTCxBAda9ExqNB-FwVNUZIuJT3h1nWmCjMws,3172
86
- mcp_agent/mcp/mcp_agent_client_session.py,sha256=RMYNltc2pDIzxwEJSS5589RbvPO0KWV4Y3jSyAmhKf0,4181
87
- mcp_agent/mcp/mcp_aggregator.py,sha256=c3UDWsTgHMcpHPx1p-vVru4y3eVO1jBQyLzwEMH2RHU,40237
88
- mcp_agent/mcp/mcp_connection_manager.py,sha256=L5Dk4cyarN_v2rfktkrfZJR4xUuD3yN_hUyQnKHBWgM,14044
88
+ mcp_agent/mcp/mcp_agent_client_session.py,sha256=Ng7epBXq8BEA_3m1GX5LqwafgNUAMSzBugwN6N0VUWQ,4364
89
+ mcp_agent/mcp/mcp_aggregator.py,sha256=lVSt0yp0CnaYjcHCWmluwBeFgl8JXHYEZk0MzXgrQzA,40110
90
+ mcp_agent/mcp/mcp_connection_manager.py,sha256=6jtjclh4YNJZsNwYnSWmQ6cPzapAwsRUxir1c_gVNfM,16051
89
91
  mcp_agent/mcp/mime_utils.py,sha256=difepNR_gpb4MpMLkBRAoyhDk-AjXUHTiqKvT_VwS1o,1805
90
92
  mcp_agent/mcp/prompt_message_multipart.py,sha256=BDwRdNwyWHb2q2bccDb2iR2VlORqVvkvoG3xYzcMpCE,4403
91
93
  mcp_agent/mcp/prompt_render.py,sha256=k3v4BZDThGE2gGiOYVQtA6x8WTEdOuXIEnRafANhN1U,2996
@@ -99,7 +101,7 @@ mcp_agent/mcp/prompts/__main__.py,sha256=gr1Tdz9fcK0EXjEuZg_BOnKUmvhYq5AH2lFZicV
99
101
  mcp_agent/mcp/prompts/prompt_constants.py,sha256=Q9W0t3rOXl2LHIG9wcghApUV2QZ1iICuo7SwVwHUf3c,566
100
102
  mcp_agent/mcp/prompts/prompt_helpers.py,sha256=Joqo2t09pTKDP-Wge3G-ozPEHikzjaqwV6GVk8hNR50,7534
101
103
  mcp_agent/mcp/prompts/prompt_load.py,sha256=Zo0FogqWFEG5FtF1d9ZH-RWsCSSMsi5FIEQHpJD8N7M,5404
102
- mcp_agent/mcp/prompts/prompt_server.py,sha256=SiUR2xYfd3vEpghnYRdzz2rFEMtAbCKx2xzUXgvz1g8,18501
104
+ mcp_agent/mcp/prompts/prompt_server.py,sha256=DbuDcYCMbsbqwBeebpNGInAQ4-DP1Jjp49y8uZ-0XlY,18872
103
105
  mcp_agent/mcp/prompts/prompt_template.py,sha256=EejiqGkau8OizORNyKTUwUjrPof5V-hH1H_MBQoQfXw,15732
104
106
  mcp_agent/mcp_server/__init__.py,sha256=zBU51ITHIEPScd9nRafnhEddsWqXRPAAvHhkrbRI2_4,155
105
107
  mcp_agent/mcp_server/agent_server.py,sha256=s-nI0uTNWx4nYDDM_5GmuY5x6ZeFkymfNoCSuwuBRd8,19891
@@ -143,8 +145,8 @@ mcp_agent/resources/examples/workflows/parallel.py,sha256=DQ5vY5-h8Qa5QHcYjsWXhZ
143
145
  mcp_agent/resources/examples/workflows/router.py,sha256=E4x_-c3l4YW9w1i4ARcDtkdeqIdbWEGfsMzwLYpdbVc,1677
144
146
  mcp_agent/resources/examples/workflows/short_story.txt,sha256=X3y_1AyhLFN2AKzCKvucJtDgAFIJfnlbsbGZO5bBWu0,1187
145
147
  mcp_agent/ui/console_display.py,sha256=TVGDtJ37hc6UG0ei9g7ZPZZfFNeS1MYozt-Mx8HsPCk,9752
146
- fast_agent_mcp-0.2.20.dist-info/METADATA,sha256=RlU6MHHAJoP4xuuA8QsIspMEZfGdSKDo76so374wzA4,30142
147
- fast_agent_mcp-0.2.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
148
- fast_agent_mcp-0.2.20.dist-info/entry_points.txt,sha256=bRniFM5zk3Kix5z7scX0gf9VnmGQ2Cz_Q1Gh7Ir4W00,186
149
- fast_agent_mcp-0.2.20.dist-info/licenses/LICENSE,sha256=cN3FxDURL9XuzE5mhK9L2paZo82LTfjwCYVT7e3j0e4,10939
150
- fast_agent_mcp-0.2.20.dist-info/RECORD,,
148
+ fast_agent_mcp-0.2.22.dist-info/METADATA,sha256=HbiOG6NhC3IEfEyBsUDQnihh2LbU4CEZEe19X4Y7VTQ,30194
149
+ fast_agent_mcp-0.2.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
150
+ fast_agent_mcp-0.2.22.dist-info/entry_points.txt,sha256=bRniFM5zk3Kix5z7scX0gf9VnmGQ2Cz_Q1Gh7Ir4W00,186
151
+ fast_agent_mcp-0.2.22.dist-info/licenses/LICENSE,sha256=cN3FxDURL9XuzE5mhK9L2paZo82LTfjwCYVT7e3j0e4,10939
152
+ fast_agent_mcp-0.2.22.dist-info/RECORD,,
@@ -18,8 +18,13 @@ async def _run_agent(
18
18
  config_path: Optional[str] = None,
19
19
  server_list: Optional[List[str]] = None,
20
20
  model: Optional[str] = None,
21
+ message: Optional[str] = None,
22
+ prompt_file: Optional[str] = None
21
23
  ) -> None:
22
24
  """Async implementation to run an interactive agent."""
25
+ from pathlib import Path
26
+
27
+ from mcp_agent.mcp.prompts.prompt_load import load_prompt_multipart
23
28
 
24
29
  # Create the FastAgent instance with CLI arg parsing enabled
25
30
  # It will automatically parse args like --model, --quiet, etc.
@@ -27,6 +32,7 @@ async def _run_agent(
27
32
  "name": name,
28
33
  "config_path": config_path,
29
34
  "ignore_unknown_args": True,
35
+ "parse_cli_args": False, # Don't parse CLI args, we're handling it ourselves
30
36
  }
31
37
 
32
38
  fast = FastAgent(**fast_kwargs)
@@ -38,10 +44,26 @@ async def _run_agent(
38
44
  if model:
39
45
  agent_kwargs["model"] = model
40
46
 
41
- @fast.agent(**agent_kwargs)
42
- async def cli_agent():
43
- async with fast.run() as agent:
44
- await agent.interactive()
47
+ # Handle prompt file and message options
48
+ if message or prompt_file:
49
+ @fast.agent(**agent_kwargs)
50
+ async def cli_agent():
51
+ async with fast.run() as agent:
52
+ if message:
53
+ response = await agent.send(message)
54
+ # Print the response and exit
55
+ print(response)
56
+ elif prompt_file:
57
+ prompt = load_prompt_multipart(Path(prompt_file))
58
+ response = await agent.generate(prompt)
59
+ # Print the response text and exit
60
+ print(response.last_text())
61
+ else:
62
+ # Standard interactive mode
63
+ @fast.agent(**agent_kwargs)
64
+ async def cli_agent():
65
+ async with fast.run() as agent:
66
+ await agent.interactive()
45
67
 
46
68
  # Run the agent
47
69
  await cli_agent()
@@ -51,7 +73,9 @@ def run_async_agent(
51
73
  instruction: str,
52
74
  config_path: Optional[str] = None,
53
75
  servers: Optional[str] = None,
54
- model: Optional[str] = None
76
+ model: Optional[str] = None,
77
+ message: Optional[str] = None,
78
+ prompt_file: Optional[str] = None
55
79
  ):
56
80
  """Run the async agent function with proper loop handling."""
57
81
  server_list = servers.split(',') if servers else None
@@ -75,7 +99,9 @@ def run_async_agent(
75
99
  instruction=instruction,
76
100
  config_path=config_path,
77
101
  server_list=server_list,
78
- model=model
102
+ model=model,
103
+ message=message,
104
+ prompt_file=prompt_file
79
105
  ))
80
106
  finally:
81
107
  try:
@@ -108,26 +134,38 @@ def go(
108
134
  model: Optional[str] = typer.Option(
109
135
  None, "--model", help="Override the default model (e.g., haiku, sonnet, gpt-4)"
110
136
  ),
137
+ message: Optional[str] = typer.Option(
138
+ None, "--message", "-m", help="Message to send to the agent (skips interactive mode)"
139
+ ),
140
+ prompt_file: Optional[str] = typer.Option(
141
+ None, "--prompt-file", "-p", help="Path to a prompt file to use (either text or JSON)"
142
+ ),
111
143
  ) -> None:
112
144
  """
113
145
  Run an interactive agent directly from the command line.
114
146
 
115
- Example:
147
+ Examples:
116
148
  fast-agent go --model=haiku --instruction="You are a coding assistant" --servers=fetch,filesystem
149
+ fast-agent go --message="What is the weather today?" --model=haiku
150
+ fast-agent go --prompt-file=my-prompt.txt --model=haiku
117
151
 
118
152
  This will start an interactive session with the agent, using the specified model
119
153
  and instruction. It will use the default configuration from fastagent.config.yaml
120
154
  unless --config-path is specified.
121
155
 
122
156
  Common options:
123
- --model: Override the default model (e.g., --model=haiku)
124
- --quiet: Disable progress display and logging
125
- --servers: Comma-separated list of server names to enable from config
157
+ --model Override the default model (e.g., --model=haiku)
158
+ --quiet Disable progress display and logging
159
+ --servers Comma-separated list of server names to enable from config
160
+ --message, -m Send a single message and exit
161
+ --prompt-file, -p Use a prompt file instead of interactive mode
126
162
  """
127
163
  run_async_agent(
128
164
  name=name,
129
165
  instruction=instruction,
130
166
  config_path=config_path,
131
167
  servers=servers,
132
- model=model
168
+ model=model,
169
+ message=message,
170
+ prompt_file=prompt_file
133
171
  )
mcp_agent/config.py CHANGED
@@ -198,6 +198,16 @@ class OpenTelemetrySettings(BaseModel):
198
198
  """Sample rate for tracing (1.0 = sample everything)"""
199
199
 
200
200
 
201
+ class TensorZeroSettings(BaseModel):
202
+ """
203
+ Settings for using TensorZero via its OpenAI-compatible API.
204
+ """
205
+
206
+ base_url: Optional[str] = None
207
+ api_key: Optional[str] = None
208
+ model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
209
+
210
+
201
211
  class LoggerSettings(BaseModel):
202
212
  """
203
213
  Logger settings for the fast-agent application.
@@ -287,6 +297,9 @@ class Settings(BaseSettings):
287
297
  generic: GenericSettings | None = None
288
298
  """Settings for using Generic models in the fast-agent application"""
289
299
 
300
+ tensorzero: Optional[TensorZeroSettings] = None
301
+ """Settings for using TensorZero inference gateway"""
302
+
290
303
  logger: LoggerSettings | None = LoggerSettings()
291
304
  """Logger settings for the fast-agent application"""
292
305
 
@@ -2,7 +2,7 @@
2
2
  Request parameters definitions for LLM interactions.
3
3
  """
4
4
 
5
- from typing import Any, List
5
+ from typing import Any, Dict, List
6
6
 
7
7
  from mcp import SamplingMessage
8
8
  from mcp.types import CreateMessageRequestParams
@@ -48,3 +48,8 @@ class RequestParams(CreateMessageRequestParams):
48
48
  """
49
49
  Override response format for structured calls. Prefer sending pydantic model - only use in exceptional circumstances
50
50
  """
51
+
52
+ template_vars: Dict[str, Any] = Field(default_factory=dict)
53
+ """
54
+ Optional dictionary of template variables for dynamic templates. Currently only works for TensorZero inference backend
55
+ """
@@ -88,7 +88,7 @@ def convert_log_event(event: Event) -> Optional[ProgressEvent]:
88
88
 
89
89
  return ProgressEvent(
90
90
  action=ProgressAction(progress_action),
91
- target=target,
91
+ target=target or "unknown",
92
92
  details=details,
93
93
  agent_name=event_data.get("agent_name"),
94
94
  )
@@ -76,20 +76,14 @@ def deep_merge(dict1: Dict[Any, Any], dict2: Dict[Any, Any]) -> Dict[Any, Any]:
76
76
  Dict: The updated `dict1`.
77
77
  """
78
78
  for key in dict2:
79
- if (
80
- key in dict1
81
- and isinstance(dict1[key], dict)
82
- and isinstance(dict2[key], dict)
83
- ):
79
+ if key in dict1 and isinstance(dict1[key], dict) and isinstance(dict2[key], dict):
84
80
  deep_merge(dict1[key], dict2[key])
85
81
  else:
86
82
  dict1[key] = dict2[key]
87
83
  return dict1
88
84
 
89
85
 
90
- class AugmentedLLM(
91
- ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT, MessageT]
92
- ):
86
+ class AugmentedLLM(ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT, MessageT]):
93
87
  # Common parameter names used across providers
94
88
  PARAM_MESSAGES = "messages"
95
89
  PARAM_MODEL = "model"
@@ -100,7 +94,7 @@ class AugmentedLLM(
100
94
  PARAM_METADATA = "metadata"
101
95
  PARAM_USE_HISTORY = "use_history"
102
96
  PARAM_MAX_ITERATIONS = "max_iterations"
103
-
97
+ PARAM_TEMPLATE_VARS = "template_vars"
104
98
  # Base set of fields that should always be excluded
105
99
  BASE_EXCLUDE_FIELDS = {PARAM_METADATA}
106
100
 
@@ -15,6 +15,7 @@ from mcp_agent.llm.providers.augmented_llm_generic import GenericAugmentedLLM
15
15
  from mcp_agent.llm.providers.augmented_llm_google import GoogleAugmentedLLM
16
16
  from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
17
17
  from mcp_agent.llm.providers.augmented_llm_openrouter import OpenRouterAugmentedLLM
18
+ from mcp_agent.llm.providers.augmented_llm_tensorzero import TensorZeroAugmentedLLM
18
19
  from mcp_agent.mcp.interfaces import AugmentedLLMProtocol
19
20
 
20
21
  # from mcp_agent.workflows.llm.augmented_llm_deepseek import DeekSeekAugmentedLLM
@@ -28,6 +29,7 @@ LLMClass = Union[
28
29
  Type[PlaybackLLM],
29
30
  Type[DeepSeekAugmentedLLM],
30
31
  Type[OpenRouterAugmentedLLM],
32
+ Type[TensorZeroAugmentedLLM],
31
33
  ]
32
34
 
33
35
 
@@ -110,6 +112,7 @@ class ModelFactory:
110
112
  Provider.GENERIC: GenericAugmentedLLM,
111
113
  Provider.GOOGLE: GoogleAugmentedLLM, # type: ignore
112
114
  Provider.OPENROUTER: OpenRouterAugmentedLLM,
115
+ Provider.TENSORZERO: TensorZeroAugmentedLLM,
113
116
  }
114
117
 
115
118
  # Mapping of special model names to their specific LLM classes
@@ -142,6 +145,11 @@ class ModelFactory:
142
145
  provider = Provider(potential_provider)
143
146
  model_parts = model_parts[1:]
144
147
 
148
+ if provider == Provider.TENSORZERO and not model_parts:
149
+ raise ModelConfigError(
150
+ f"TensorZero provider requires a function name after the provider "
151
+ f"(e.g., tensorzero.my-function), got: {model_string}"
152
+ )
145
153
  # Join remaining parts as model name
146
154
  model_name = ".".join(model_parts)
147
155
 
@@ -15,3 +15,4 @@ class Provider(Enum):
15
15
  DEEPSEEK = "deepseek"
16
16
  GENERIC = "generic"
17
17
  OPENROUTER = "openrouter"
18
+ TENSORZERO = "tensorzero" # For TensorZero Gateway
@@ -62,6 +62,7 @@ class AnthropicAugmentedLLM(AugmentedLLM[MessageParam, Message]):
62
62
  AugmentedLLM.PARAM_USE_HISTORY,
63
63
  AugmentedLLM.PARAM_MAX_ITERATIONS,
64
64
  AugmentedLLM.PARAM_PARALLEL_TOOL_CALLS,
65
+ AugmentedLLM.PARAM_TEMPLATE_VARS,
65
66
  }
66
67
 
67
68
  def __init__(self, *args, **kwargs) -> None:
@@ -56,6 +56,7 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
56
56
  AugmentedLLM.PARAM_PARALLEL_TOOL_CALLS,
57
57
  AugmentedLLM.PARAM_USE_HISTORY,
58
58
  AugmentedLLM.PARAM_MAX_ITERATIONS,
59
+ AugmentedLLM.PARAM_TEMPLATE_VARS,
59
60
  }
60
61
 
61
62
  def __init__(self, provider: Provider = Provider.OPENAI, *args, **kwargs) -> None:
@@ -143,7 +144,7 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
143
144
  function={
144
145
  "name": tool.name,
145
146
  "description": tool.description if tool.description else "",
146
- "parameters": tool.inputSchema,
147
+ "parameters": self.adjust_schema(tool.inputSchema),
147
148
  },
148
149
  )
149
150
  for tool in response.tools
@@ -350,3 +351,15 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
350
351
  base_args, request_params, self.OPENAI_EXCLUDE_FIELDS.union(self.BASE_EXCLUDE_FIELDS)
351
352
  )
352
353
  return arguments
354
+
355
+ def adjust_schema(self, inputSchema: Dict) -> Dict:
356
+ # return inputSchema
357
+ if not Provider.OPENAI == self.provider:
358
+ return inputSchema
359
+
360
+ if "properties" in inputSchema:
361
+ return inputSchema
362
+
363
+ result = inputSchema.copy()
364
+ result["properties"] = {}
365
+ return result