fast-agent-mcp 0.2.55__py3-none-any.whl → 0.2.56__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.55
3
+ Version: 0.2.56
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
@@ -211,7 +211,7 @@ Classifier: Programming Language :: Python :: 3
211
211
  Requires-Python: >=3.13
212
212
  Requires-Dist: a2a-sdk>=0.3.0
213
213
  Requires-Dist: aiohttp>=3.11.13
214
- Requires-Dist: anthropic>=0.59.0
214
+ Requires-Dist: anthropic>=0.63.0
215
215
  Requires-Dist: azure-identity>=1.14.0
216
216
  Requires-Dist: boto3>=1.35.0
217
217
  Requires-Dist: deprecated>=1.2.18
@@ -219,7 +219,7 @@ Requires-Dist: email-validator>=2.2.0
219
219
  Requires-Dist: fastapi>=0.115.6
220
220
  Requires-Dist: google-genai>=1.27.0
221
221
  Requires-Dist: mcp==1.12.4
222
- Requires-Dist: openai>=1.97.1
222
+ Requires-Dist: openai>=1.99.9
223
223
  Requires-Dist: opentelemetry-distro>=0.55b0
224
224
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.7.0
225
225
  Requires-Dist: opentelemetry-instrumentation-anthropic>=0.43.1; python_version >= '3.10' and python_version < '4.0'
@@ -234,20 +234,6 @@ Requires-Dist: pyyaml>=6.0.2
234
234
  Requires-Dist: rich>=14.1.0
235
235
  Requires-Dist: tensorzero>=2025.7.5
236
236
  Requires-Dist: typer>=0.15.1
237
- Provides-Extra: azure
238
- Requires-Dist: azure-identity>=1.14.0; extra == 'azure'
239
- Provides-Extra: dev
240
- Requires-Dist: anthropic>=0.42.0; extra == 'dev'
241
- Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
242
- Requires-Dist: pydantic>=2.10.4; extra == 'dev'
243
- Requires-Dist: pytest-asyncio>=0.21.1; extra == 'dev'
244
- Requires-Dist: pytest-cov; extra == 'dev'
245
- Requires-Dist: pytest>=7.4.0; extra == 'dev'
246
- Requires-Dist: pyyaml>=6.0.2; extra == 'dev'
247
- Requires-Dist: ruff>=0.8.4; extra == 'dev'
248
- Requires-Dist: tomli>=2.2.1; extra == 'dev'
249
- Provides-Extra: openai
250
- Requires-Dist: openai>=1.58.1; extra == 'openai'
251
237
  Description-Content-Type: text/markdown
252
238
 
253
239
  <p align="center">
@@ -10,7 +10,7 @@ mcp_agent/progress_display.py,sha256=GeJU9VUt6qKsFVymG688hCMVCsAygG9ifiiEb5IcbN4
10
10
  mcp_agent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  mcp_agent/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  mcp_agent/agents/agent.py,sha256=EAYlcP1qqI1D0_CS808I806z1048FBjZQxxpcCZPeIU,3154
13
- mcp_agent/agents/base_agent.py,sha256=4hyEdJJENxIDLCtYOAmRlmM7dRVE0JPEhOYktPTw1I0,34566
13
+ mcp_agent/agents/base_agent.py,sha256=BXakMe8VtDyWBtgoqcu-BXeMG54MB1o_gjcEAlhhYp8,34727
14
14
  mcp_agent/agents/workflow/__init__.py,sha256=HloteEW6kalvgR0XewpiFAqaQlMPlPJYg5p3K33IUzI,25
15
15
  mcp_agent/agents/workflow/chain_agent.py,sha256=eIlImirrSXkqBJmPuAJgOKis81Cl6lZEGM0-6IyaUV8,6105
16
16
  mcp_agent/agents/workflow/evaluator_optimizer.py,sha256=LT81m2B7fxgBZY0CorXFOZJbVhM5fnjDjfrcywO5UrM,12210
@@ -26,7 +26,7 @@ mcp_agent/cli/constants.py,sha256=KawdkaN289nVB02DKPB4IVUJ8-fohIUD0gLfOp0P7B8,55
26
26
  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
- mcp_agent/cli/commands/go.py,sha256=SHFJlO3SeZzAWvx_Gz72zXKA8n7XfaZ49W6UNS5mbV4,14668
29
+ mcp_agent/cli/commands/go.py,sha256=RfNJQYmuDJicpYM7oT-jfv_9P7kBqCh_5Ezd4RtcYME,14712
30
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
@@ -36,7 +36,7 @@ mcp_agent/core/agent_app.py,sha256=SolGwejEmv9XtsTsmiMkNKPia7RN1VcHXm6JoEo4hvQ,1
36
36
  mcp_agent/core/agent_types.py,sha256=ClFN7ikstZ5suweeLFf5w9jcg3ygxVhMS7GRj9VJ8yQ,1749
37
37
  mcp_agent/core/direct_decorators.py,sha256=mOMLHf_qhWFqcOY0QE1UbHtXAarnetIKp7n0U8WvcyM,24061
38
38
  mcp_agent/core/direct_factory.py,sha256=0G1HbVECfdFJGn__lBYGha_qt7Xyp18ST18IOzO134E,20867
39
- mcp_agent/core/enhanced_prompt.py,sha256=ZIeJCeW7rcGMBZ2OdEQwqOmRT0wNSp0hO2-dZRSnnLE,36068
39
+ mcp_agent/core/enhanced_prompt.py,sha256=4uy_HRLL05DFzqYodN6EkzVLfux2iAbNOWib5d2YVaY,36097
40
40
  mcp_agent/core/error_handling.py,sha256=xoyS2kLe0eG0bj2eSJCJ2odIhGUve2SbDR7jP-A-uRw,624
41
41
  mcp_agent/core/exceptions.py,sha256=ENAD_qGG67foxy6vDkIvc-lgopIUQy6O7zvNPpPXaQg,2289
42
42
  mcp_agent/core/fastagent.py,sha256=HiKuxHsj0wq6_RV0wkJih8br39ciHNnnfVEsknhbiQA,25264
@@ -80,13 +80,13 @@ mcp_agent/llm/providers/anthropic_utils.py,sha256=vYDN5G5jKMhD2CQg8veJYab7tvvzYk
80
80
  mcp_agent/llm/providers/augmented_llm_aliyun.py,sha256=Th4qeyihOSfTrojPw8YsgzEyaDwhybk7hkXkFjH-1dY,1277
81
81
  mcp_agent/llm/providers/augmented_llm_anthropic.py,sha256=U8znA9HSCOx4FlhIjl-J29nbYc8Y-T6BXevtXuDafio,30352
82
82
  mcp_agent/llm/providers/augmented_llm_azure.py,sha256=Xoo6dFst6L9SaGKurqptwwTUzr-sYsolZ-AFb_79puc,6098
83
- mcp_agent/llm/providers/augmented_llm_bedrock.py,sha256=nfby1udL07zPTOLlN_tFxd1h0JRioo2oIW7v4iP4Bnk,82267
83
+ mcp_agent/llm/providers/augmented_llm_bedrock.py,sha256=lL_au5-QdVNFr7lxQQYk0HVQ3LKUieh2HHnBQsOWoro,82312
84
84
  mcp_agent/llm/providers/augmented_llm_deepseek.py,sha256=vphkYMFyukaejBw8SkCN-MqcG9qsfXJfWKZYYtspqPY,3877
85
85
  mcp_agent/llm/providers/augmented_llm_generic.py,sha256=5Uq8ZBhcFuQTt7koP_5ykolREh2iWu8zKhNbh3pM9lQ,1210
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
- mcp_agent/llm/providers/augmented_llm_groq.py,sha256=Nj4X7wL7nOz_JYC-3bFOWut-hleZxGqWHNe0U-0ga8Y,4419
89
- mcp_agent/llm/providers/augmented_llm_openai.py,sha256=d5WeCU6smP7a5egZOBpblF62mK5kOzK4tn2YeQoK34A,25401
88
+ mcp_agent/llm/providers/augmented_llm_groq.py,sha256=w-R1N2B7790v9tXxRCPt2SKnaB-DRdEtN_51fpdYb_I,5355
89
+ mcp_agent/llm/providers/augmented_llm_openai.py,sha256=v0iInSlPt939Dh2kGpGJ9_7qGpL7MhxQ7UNSc42dT6Q,25318
90
90
  mcp_agent/llm/providers/augmented_llm_openrouter.py,sha256=m3wS83fabBOmaZJH9gQ9sFw_2TB4xTb44WCOPB-2NJ4,2001
91
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
@@ -113,7 +113,7 @@ mcp_agent/mcp/hf_auth.py,sha256=7szw4rkwRyK3J-sUTcVZHdwoLIZqlYo8XolJnZdjOww,4571
113
113
  mcp_agent/mcp/interfaces.py,sha256=5y7zuXkpGCfsJfZOAEZAZtbFd5rAKjn7oG4JoblPHZ4,8070
114
114
  mcp_agent/mcp/logger_textio.py,sha256=vljC1BtNTCxBAda9ExqNB-FwVNUZIuJT3h1nWmCjMws,3172
115
115
  mcp_agent/mcp/mcp_agent_client_session.py,sha256=ssRgxMOzyCPyAr25AeRBz3Xr-08OBdmsJf8A-ofc3bY,9115
116
- mcp_agent/mcp/mcp_aggregator.py,sha256=6fZTgoiUfE7YHjLug1ZQ2VtKYj8HVe_diMwNN6npPGk,53343
116
+ mcp_agent/mcp/mcp_aggregator.py,sha256=KtZEDydOw577Tk-3eNiZkPmuHIT-mDPxpCfT43ZYbx4,53399
117
117
  mcp_agent/mcp/mcp_connection_manager.py,sha256=dJxjnv2IRzlFIxrbPFl39-pmGcZHgyeMXVlMfqpREhE,17974
118
118
  mcp_agent/mcp/mime_utils.py,sha256=difepNR_gpb4MpMLkBRAoyhDk-AjXUHTiqKvT_VwS1o,1805
119
119
  mcp_agent/mcp/prompt_message_multipart.py,sha256=-oSO0mnc5gkSgulE1gAntPEwAKF4asOjEeVyLjhYrEk,4336
@@ -185,8 +185,8 @@ mcp_agent/resources/examples/workflows/short_story.txt,sha256=X3y_1AyhLFN2AKzCKv
185
185
  mcp_agent/tools/tool_definition.py,sha256=L3Pxl-uLEXqlVoo-bYuFTFALeI-2pIU44YgFhsTKEtM,398
186
186
  mcp_agent/ui/console_display.py,sha256=XXrHr950wSBSedEKUaaGkXjOzuFpQYzUKKiyaZ58Mps,28280
187
187
  mcp_agent/ui/console_display_legacy.py,sha256=sm2v61-IPVafbF7uUaOyhO2tW_zgFWOjNS83IEWqGgI,14931
188
- fast_agent_mcp-0.2.55.dist-info/METADATA,sha256=wJSX8ZuwOm6h7kbWev3_cv1CQRDHT0C60xwlE9tXPqE,31048
189
- fast_agent_mcp-0.2.55.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
190
- fast_agent_mcp-0.2.55.dist-info/entry_points.txt,sha256=QaX5kLdI0VdMPRdPUF1nkG_WdLUTNjp_icW6e3EhNYU,232
191
- fast_agent_mcp-0.2.55.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
192
- fast_agent_mcp-0.2.55.dist-info/RECORD,,
188
+ fast_agent_mcp-0.2.56.dist-info/METADATA,sha256=6cyeWzS7xvOKhhLE9rdoRDxp9LOZ4I4yPVq9bHo9yv4,30459
189
+ fast_agent_mcp-0.2.56.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
190
+ fast_agent_mcp-0.2.56.dist-info/entry_points.txt,sha256=QaX5kLdI0VdMPRdPUF1nkG_WdLUTNjp_icW6e3EhNYU,232
191
+ fast_agent_mcp-0.2.56.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
192
+ fast_agent_mcp-0.2.56.dist-info/RECORD,,
@@ -364,12 +364,15 @@ class BaseAgent(MCPAggregator, AgentProtocol):
364
364
  if self.config.tools is not None:
365
365
  filtered_tools = []
366
366
  for tool in result.tools:
367
- # Extract server name from tool name (e.g., "mathematics-add" -> "mathematics")
368
- if "-" in tool.name:
369
- server_name = tool.name.split("-", 1)[0]
367
+ # Extract server name from tool name, handling server names with hyphens
368
+ server_name = None
369
+ for configured_server in self.config.tools.keys():
370
+ if tool.name.startswith(f"{configured_server}-"):
371
+ server_name = configured_server
372
+ break
370
373
 
371
- # Check if this server has tool filters
372
- if server_name in self.config.tools:
374
+ # Check if this server has tool filters
375
+ if server_name and server_name in self.config.tools:
373
376
  # Check if tool matches any pattern for this server
374
377
  for pattern in self.config.tools[server_name]:
375
378
  if self._matches_pattern(tool.name, pattern, server_name):
@@ -121,9 +121,9 @@ async def _run_agent(
121
121
  print(response)
122
122
  elif prompt_file:
123
123
  prompt = load_prompt_multipart(Path(prompt_file))
124
- response = await agent.generate(prompt)
125
- # Print the response text and exit
126
- print(response.last_text())
124
+ response = await agent.agent.generate(prompt)
125
+ print(f"\nLoaded {len(prompt)} messages from prompt file '{prompt_file}'")
126
+ await agent.interactive()
127
127
  else:
128
128
  await agent.interactive()
129
129
 
@@ -585,6 +585,7 @@ async def get_enhanced_input(
585
585
  ("Ctrl+Y", "Copy"),
586
586
  ("Ctrl+L", "Clear"),
587
587
  ("↑/↓", "History"),
588
+ ("EXIT", "Exit")
588
589
  ]
589
590
 
590
591
  newline = "Ctrl+&lt;Enter&gt;:Submit" if in_multiline_mode else "&lt;Enter&gt;:Submit"
@@ -86,6 +86,7 @@ class BedrockAugmentedLLM(AugmentedLLM[BedrockMessageParam, BedrockMessage]):
86
86
  r"^cohere\..*", # Cohere models
87
87
  r"^ai21\..*", # AI21 models
88
88
  r"^stability\..*", # Stability AI models
89
+ r"^openai\..*", # OpenAI models
89
90
  ]
90
91
 
91
92
  import re
@@ -49,35 +49,22 @@ class GroqAugmentedLLM(OpenAIAugmentedLLM):
49
49
  if "object" == json_mode:
50
50
  request_params.response_format = {"type": "json_object"}
51
51
 
52
- # Get the full schema and extract just the properties
53
- full_schema = model.model_json_schema()
54
- properties = full_schema.get("properties", {})
55
- required_fields = full_schema.get("required", [])
56
-
57
- # Create a cleaner format description
58
- format_description = "{\n"
59
- for field_name, field_info in properties.items():
60
- field_type = field_info.get("type", "string")
61
- description = field_info.get("description", "")
62
- format_description += f' "{field_name}": "{field_type}"'
63
- if description:
64
- format_description += f" // {description}"
65
- if field_name in required_fields:
66
- format_description += " // REQUIRED"
67
- format_description += "\n"
68
- format_description += "}"
69
-
70
- multipart_messages[-1].add_text(
71
- f"""YOU MUST RESPOND WITH A JSON OBJECT IN EXACTLY THIS FORMAT:
72
- {format_description}
73
-
74
- IMPORTANT RULES:
75
- - Respond ONLY with the JSON object, no other text
76
- - Do NOT include "properties" or "schema" wrappers
77
- - Do NOT use code fences or markdown
78
- - The response must be valid JSON that matches the format above
79
- - All required fields must be included"""
80
- )
52
+ # Create a cleaner format description from full schema
53
+ full_schema = model.model_json_schema()
54
+ format_description = self._schema_to_json_object(
55
+ full_schema, full_schema.get("$defs")
56
+ )
57
+
58
+ multipart_messages[-1].add_text(
59
+ f"""YOU MUST RESPOND WITH A JSON OBJECT IN EXACTLY THIS FORMAT:
60
+ {format_description}
61
+
62
+ IMPORTANT RULES:
63
+ - Respond ONLY with the JSON object, no other text
64
+ - Do NOT include "properties" or "schema" wrappers
65
+ - Do NOT use code fences or markdown
66
+ - The response must be valid JSON that matches the format above
67
+ - All required fields must be included""")
81
68
 
82
69
  result: PromptMessageMultipart = await self._apply_prompt_provider_specific(
83
70
  multipart_messages, request_params
@@ -101,3 +88,45 @@ class GroqAugmentedLLM(OpenAIAugmentedLLM):
101
88
  base_url = self.context.config.groq.base_url
102
89
 
103
90
  return base_url if base_url else GROQ_BASE_URL
91
+
92
+ def _schema_to_json_object(
93
+ self, schema: dict, defs: dict | None = None, visited: set | None = None
94
+ ) -> str:
95
+ visited = visited or set()
96
+
97
+ if id(schema) in visited:
98
+ return '"<recursive>"'
99
+ visited.add(id(schema))
100
+
101
+ if "$ref" in schema:
102
+ ref = schema.get("$ref", "")
103
+ if ref.startswith("#/$defs/"):
104
+ target = ref.split("/")[-1]
105
+ if defs and target in defs:
106
+ return self._schema_to_json_object(defs[target], defs, visited)
107
+ return f'"<ref:{ref}>"'
108
+
109
+ schema_type = schema.get("type")
110
+ description = schema.get("description", "")
111
+ required = schema.get("required", [])
112
+
113
+ if schema_type == "object":
114
+ props = schema.get("properties", {})
115
+ result = "{\n"
116
+ for prop_name, prop_schema in props.items():
117
+ is_required = prop_name in required
118
+ prop_str = self._schema_to_json_object(prop_schema, defs, visited)
119
+ if is_required:
120
+ prop_str += " // REQUIRED"
121
+ result += f' "{prop_name}": {prop_str},\n'
122
+ result += "}"
123
+ return result
124
+ elif schema_type == "array":
125
+ items = schema.get("items", {})
126
+ items_str = self._schema_to_json_object(items, defs, visited)
127
+ return f"[{items_str}]"
128
+ elif schema_type:
129
+ comment = f" // {description}" if description else ""
130
+ return f'"{schema_type}"' + comment
131
+
132
+ return '"<unknown>"'
@@ -171,7 +171,6 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
171
171
  async def _process_stream_manual(self, stream, model: str):
172
172
  """Manual stream processing for providers like Ollama that may not work with ChatCompletionStreamState."""
173
173
  from openai.types.chat import ChatCompletionMessageToolCall
174
- from openai.types.chat.chat_completion_message_tool_call import Function
175
174
 
176
175
  # Track estimated output tokens by counting text chunks
177
176
  estimated_tokens = 0
@@ -249,10 +248,10 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
249
248
  ChatCompletionMessageToolCall(
250
249
  id=tool_call_data["id"],
251
250
  type=tool_call_data["type"],
252
- function=Function(
253
- name=tool_call_data["function"]["name"],
254
- arguments=tool_call_data["function"]["arguments"],
255
- ),
251
+ function={
252
+ "name": tool_call_data["function"]["name"],
253
+ "arguments": tool_call_data["function"]["arguments"],
254
+ },
256
255
  )
257
256
  )
258
257
 
@@ -572,14 +572,13 @@ class MCPAggregator(ContextDependent):
572
572
 
573
573
  # Next, attempt to interpret as a namespaced name
574
574
  if is_namespaced_name(name):
575
- parts = name.split(SEP, 1)
576
- server_name, local_name = parts[0], parts[1]
575
+ # Try to match against known server names, handling server names with hyphens
576
+ for server_name in self.server_names:
577
+ if name.startswith(f"{server_name}{SEP}"):
578
+ local_name = name[len(server_name) + len(SEP):]
579
+ return server_name, local_name
577
580
 
578
- # Validate that the parsed server actually exists
579
- if server_name in self.server_names:
580
- return server_name, local_name
581
-
582
- # If the server name doesn't exist, it might be a tool with a hyphen in its name
581
+ # If no server name matched, it might be a tool with a hyphen in its name
583
582
  # Fall through to the next checks
584
583
 
585
584
  # For tools, search all servers for the tool by exact name match