fast-agent-mcp 0.1.13__py3-none-any.whl → 0.2.0__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.
Files changed (147) hide show
  1. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
  2. fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
  3. mcp_agent/__init__.py +75 -0
  4. mcp_agent/agents/agent.py +59 -371
  5. mcp_agent/agents/base_agent.py +522 -0
  6. mcp_agent/agents/workflow/__init__.py +1 -0
  7. mcp_agent/agents/workflow/chain_agent.py +173 -0
  8. mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
  9. mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
  10. mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +27 -11
  11. mcp_agent/agents/workflow/parallel_agent.py +182 -0
  12. mcp_agent/agents/workflow/router_agent.py +307 -0
  13. mcp_agent/app.py +3 -1
  14. mcp_agent/cli/commands/bootstrap.py +18 -7
  15. mcp_agent/cli/commands/setup.py +12 -4
  16. mcp_agent/cli/main.py +1 -1
  17. mcp_agent/cli/terminal.py +1 -1
  18. mcp_agent/config.py +24 -35
  19. mcp_agent/context.py +3 -1
  20. mcp_agent/context_dependent.py +3 -1
  21. mcp_agent/core/agent_types.py +10 -7
  22. mcp_agent/core/direct_agent_app.py +179 -0
  23. mcp_agent/core/direct_decorators.py +443 -0
  24. mcp_agent/core/direct_factory.py +476 -0
  25. mcp_agent/core/enhanced_prompt.py +15 -20
  26. mcp_agent/core/fastagent.py +151 -337
  27. mcp_agent/core/interactive_prompt.py +424 -0
  28. mcp_agent/core/mcp_content.py +19 -11
  29. mcp_agent/core/prompt.py +6 -2
  30. mcp_agent/core/validation.py +89 -16
  31. mcp_agent/executor/decorator_registry.py +6 -2
  32. mcp_agent/executor/temporal.py +35 -11
  33. mcp_agent/executor/workflow_signal.py +8 -2
  34. mcp_agent/human_input/handler.py +3 -1
  35. mcp_agent/llm/__init__.py +2 -0
  36. mcp_agent/{workflows/llm → llm}/augmented_llm.py +131 -256
  37. mcp_agent/{workflows/llm → llm}/augmented_llm_passthrough.py +35 -107
  38. mcp_agent/llm/augmented_llm_playback.py +83 -0
  39. mcp_agent/{workflows/llm → llm}/model_factory.py +26 -8
  40. mcp_agent/llm/providers/__init__.py +8 -0
  41. mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +5 -1
  42. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +37 -141
  43. mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
  44. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +112 -148
  45. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +78 -35
  46. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +73 -44
  47. mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +18 -4
  48. mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +3 -3
  49. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +3 -3
  50. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +3 -3
  51. mcp_agent/{workflows/llm → llm}/sampling_converter.py +0 -21
  52. mcp_agent/{workflows/llm → llm}/sampling_format_converter.py +16 -1
  53. mcp_agent/logging/logger.py +2 -2
  54. mcp_agent/mcp/gen_client.py +9 -3
  55. mcp_agent/mcp/interfaces.py +67 -45
  56. mcp_agent/mcp/logger_textio.py +97 -0
  57. mcp_agent/mcp/mcp_agent_client_session.py +12 -4
  58. mcp_agent/mcp/mcp_agent_server.py +3 -1
  59. mcp_agent/mcp/mcp_aggregator.py +124 -93
  60. mcp_agent/mcp/mcp_connection_manager.py +21 -7
  61. mcp_agent/mcp/prompt_message_multipart.py +59 -1
  62. mcp_agent/mcp/prompt_render.py +77 -0
  63. mcp_agent/mcp/prompt_serialization.py +20 -13
  64. mcp_agent/mcp/prompts/prompt_constants.py +18 -0
  65. mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
  66. mcp_agent/mcp/prompts/prompt_load.py +15 -5
  67. mcp_agent/mcp/prompts/prompt_server.py +154 -87
  68. mcp_agent/mcp/prompts/prompt_template.py +26 -35
  69. mcp_agent/mcp/resource_utils.py +3 -1
  70. mcp_agent/mcp/sampling.py +24 -15
  71. mcp_agent/mcp_server/agent_server.py +8 -5
  72. mcp_agent/mcp_server_registry.py +22 -9
  73. mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +1 -1
  74. mcp_agent/resources/examples/{data-analysis → in_dev}/slides.py +1 -1
  75. mcp_agent/resources/examples/internal/agent.py +4 -2
  76. mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
  77. mcp_agent/resources/examples/prompting/image_server.py +3 -1
  78. mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
  79. mcp_agent/ui/console_display.py +27 -7
  80. fast_agent_mcp-0.1.13.dist-info/RECORD +0 -164
  81. mcp_agent/core/agent_app.py +0 -570
  82. mcp_agent/core/agent_utils.py +0 -69
  83. mcp_agent/core/decorators.py +0 -448
  84. mcp_agent/core/factory.py +0 -422
  85. mcp_agent/core/proxies.py +0 -278
  86. mcp_agent/core/types.py +0 -22
  87. mcp_agent/eval/__init__.py +0 -0
  88. mcp_agent/mcp/stdio.py +0 -114
  89. mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
  90. mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
  91. mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
  92. mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
  93. mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
  94. mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
  95. mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
  96. mcp_agent/resources/examples/researcher/researcher-imp.py +0 -189
  97. mcp_agent/resources/examples/researcher/researcher.py +0 -39
  98. mcp_agent/resources/examples/workflows/chaining.py +0 -45
  99. mcp_agent/resources/examples/workflows/evaluator.py +0 -79
  100. mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
  101. mcp_agent/resources/examples/workflows/human_input.py +0 -26
  102. mcp_agent/resources/examples/workflows/orchestrator.py +0 -74
  103. mcp_agent/resources/examples/workflows/parallel.py +0 -79
  104. mcp_agent/resources/examples/workflows/router.py +0 -54
  105. mcp_agent/resources/examples/workflows/sse.py +0 -23
  106. mcp_agent/telemetry/__init__.py +0 -0
  107. mcp_agent/telemetry/usage_tracking.py +0 -19
  108. mcp_agent/workflows/__init__.py +0 -0
  109. mcp_agent/workflows/embedding/__init__.py +0 -0
  110. mcp_agent/workflows/embedding/embedding_base.py +0 -58
  111. mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
  112. mcp_agent/workflows/embedding/embedding_openai.py +0 -37
  113. mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
  114. mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -447
  115. mcp_agent/workflows/intent_classifier/__init__.py +0 -0
  116. mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -117
  117. mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -130
  118. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -41
  119. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -41
  120. mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -150
  121. mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
  122. mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -58
  123. mcp_agent/workflows/llm/__init__.py +0 -0
  124. mcp_agent/workflows/llm/augmented_llm_playback.py +0 -111
  125. mcp_agent/workflows/llm/providers/__init__.py +0 -8
  126. mcp_agent/workflows/orchestrator/__init__.py +0 -0
  127. mcp_agent/workflows/orchestrator/orchestrator.py +0 -535
  128. mcp_agent/workflows/parallel/__init__.py +0 -0
  129. mcp_agent/workflows/parallel/fan_in.py +0 -320
  130. mcp_agent/workflows/parallel/fan_out.py +0 -181
  131. mcp_agent/workflows/parallel/parallel_llm.py +0 -149
  132. mcp_agent/workflows/router/__init__.py +0 -0
  133. mcp_agent/workflows/router/router_base.py +0 -338
  134. mcp_agent/workflows/router/router_embedding.py +0 -226
  135. mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
  136. mcp_agent/workflows/router/router_embedding_openai.py +0 -59
  137. mcp_agent/workflows/router/router_llm.py +0 -304
  138. mcp_agent/workflows/swarm/__init__.py +0 -0
  139. mcp_agent/workflows/swarm/swarm.py +0 -292
  140. mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
  141. mcp_agent/workflows/swarm/swarm_openai.py +0 -41
  142. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
  143. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
  144. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
  145. /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
  146. /mcp_agent/{workflows/llm → llm}/memory.py +0 -0
  147. /mcp_agent/{workflows/llm → llm}/prompt_utils.py +0 -0
@@ -0,0 +1,18 @@
1
+ """
2
+ Constants for the prompt system.
3
+
4
+ This module defines constants used throughout the prompt system, including
5
+ delimiters for parsing prompt files and serializing prompt messages.
6
+ """
7
+
8
+ # Standard delimiters used for prompt template parsing and serialization
9
+ USER_DELIMITER = "---USER"
10
+ ASSISTANT_DELIMITER = "---ASSISTANT"
11
+ RESOURCE_DELIMITER = "---RESOURCE"
12
+
13
+ # Default delimiter mapping used by PromptTemplate and PromptTemplateLoader
14
+ DEFAULT_DELIMITER_MAP = {
15
+ USER_DELIMITER: "user",
16
+ ASSISTANT_DELIMITER: "assistant",
17
+ RESOURCE_DELIMITER: "resource",
18
+ }
@@ -0,0 +1,327 @@
1
+ """
2
+ Helper functions for working with PromptMessage and PromptMessageMultipart objects.
3
+
4
+ These utilities simplify extracting content from nested message structures
5
+ without repetitive type checking.
6
+ """
7
+
8
+ from typing import List, Optional, Union, cast
9
+
10
+ from mcp.types import (
11
+ BlobResourceContents,
12
+ EmbeddedResource,
13
+ ImageContent,
14
+ PromptMessage,
15
+ TextContent,
16
+ TextResourceContents,
17
+ )
18
+
19
+ from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
20
+
21
+
22
+ def get_text(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
23
+ """
24
+ Extract text content from a content object if available.
25
+
26
+ Args:
27
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
28
+
29
+ Returns:
30
+ The text content as a string or None if not a text content
31
+ """
32
+ if isinstance(content, TextContent):
33
+ return content.text
34
+
35
+ if isinstance(content, EmbeddedResource):
36
+ if isinstance(content.resource, TextResourceContents):
37
+ return content.resource.text
38
+
39
+ return None
40
+
41
+
42
+ def get_image_data(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
43
+ """
44
+ Extract image data from a content object if available.
45
+
46
+ Args:
47
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
48
+
49
+ Returns:
50
+ The image data as a base64 string or None if not an image content
51
+ """
52
+ if isinstance(content, ImageContent):
53
+ return content.data
54
+
55
+ if isinstance(content, EmbeddedResource):
56
+ if isinstance(content.resource, BlobResourceContents):
57
+ # This assumes the blob might be an image, which isn't always true
58
+ # Consider checking the mimeType if needed
59
+ return content.resource.blob
60
+
61
+ return None
62
+
63
+
64
+ def get_resource_uri(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
65
+ """
66
+ Extract resource URI from an EmbeddedResource if available.
67
+
68
+ Args:
69
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
70
+
71
+ Returns:
72
+ The resource URI as a string or None if not an embedded resource
73
+ """
74
+ if isinstance(content, EmbeddedResource):
75
+ return str(content.resource.uri)
76
+
77
+ return None
78
+
79
+
80
+ def is_text_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
81
+ """
82
+ Check if the content is text content.
83
+
84
+ Args:
85
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
86
+
87
+ Returns:
88
+ True if the content is TextContent, False otherwise
89
+ """
90
+ return isinstance(content, TextContent)
91
+
92
+
93
+ def is_image_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
94
+ """
95
+ Check if the content is image content.
96
+
97
+ Args:
98
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
99
+
100
+ Returns:
101
+ True if the content is ImageContent, False otherwise
102
+ """
103
+ return isinstance(content, ImageContent)
104
+
105
+
106
+ def is_resource_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
107
+ """
108
+ Check if the content is an embedded resource.
109
+
110
+ Args:
111
+ content: A content object (TextContent, ImageContent, or EmbeddedResource)
112
+
113
+ Returns:
114
+ True if the content is EmbeddedResource, False otherwise
115
+ """
116
+ return isinstance(content, EmbeddedResource)
117
+
118
+
119
+ class MessageContent:
120
+ """
121
+ Helper class for working with message content in both PromptMessage and
122
+ PromptMessageMultipart objects.
123
+ """
124
+
125
+ @staticmethod
126
+ def get_all_text(message: Union[PromptMessage, PromptMessageMultipart]) -> List[str]:
127
+ """
128
+ Extract all text content from a message.
129
+
130
+ Args:
131
+ message: A PromptMessage or PromptMessageMultipart
132
+
133
+ Returns:
134
+ List of text strings from all text content parts
135
+ """
136
+ if isinstance(message, PromptMessage):
137
+ text = get_text(message.content)
138
+ return [text] if text is not None else []
139
+
140
+ result = []
141
+ for content in message.content:
142
+ text = get_text(content)
143
+ if text is not None:
144
+ result.append(text)
145
+
146
+ return result
147
+
148
+ @staticmethod
149
+ def join_text(
150
+ message: Union[PromptMessage, PromptMessageMultipart], separator: str = "\n\n"
151
+ ) -> str:
152
+ """
153
+ Join all text content in a message with a separator.
154
+
155
+ Args:
156
+ message: A PromptMessage or PromptMessageMultipart
157
+ separator: String to use as separator (default: newlines)
158
+
159
+ Returns:
160
+ Joined text string
161
+ """
162
+ return separator.join(MessageContent.get_all_text(message))
163
+
164
+ @staticmethod
165
+ def get_first_text(message: Union[PromptMessage, PromptMessageMultipart]) -> Optional[str]:
166
+ """
167
+ Get the first available text content from a message.
168
+
169
+ Args:
170
+ message: A PromptMessage or PromptMessageMultipart
171
+
172
+ Returns:
173
+ First text content or None if no text content exists
174
+ """
175
+ if isinstance(message, PromptMessage):
176
+ return get_text(message.content)
177
+
178
+ for content in message.content:
179
+ text = get_text(content)
180
+ if text is not None:
181
+ return text
182
+
183
+ return None
184
+
185
+ @staticmethod
186
+ def has_text_at_first_position(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
187
+ """
188
+ Check if a message has a TextContent at the first position.
189
+ This is a common case when dealing with messages that start with text.
190
+
191
+ Args:
192
+ message: A PromptMessage or PromptMessageMultipart
193
+
194
+ Returns:
195
+ True if the message has TextContent at first position, False otherwise
196
+ """
197
+ if isinstance(message, PromptMessage):
198
+ return isinstance(message.content, TextContent)
199
+
200
+ # For multipart messages, check if there's at least one item and the first is TextContent
201
+ return len(message.content) > 0 and isinstance(message.content[0], TextContent)
202
+
203
+ @staticmethod
204
+ def get_text_at_first_position(
205
+ message: Union[PromptMessage, PromptMessageMultipart],
206
+ ) -> Optional[str]:
207
+ """
208
+ Get the text from the first position of a message if it's TextContent.
209
+
210
+ Args:
211
+ message: A PromptMessage or PromptMessageMultipart
212
+
213
+ Returns:
214
+ The text content at the first position if it's TextContent,
215
+ None otherwise
216
+ """
217
+ if not MessageContent.has_text_at_first_position(message):
218
+ return None
219
+
220
+ if isinstance(message, PromptMessage):
221
+ return cast("TextContent", message.content).text
222
+
223
+ # Safe to cast since we've verified the first item is TextContent
224
+ return cast("TextContent", message.content[0]).text
225
+
226
+ @staticmethod
227
+ def get_all_images(message: Union[PromptMessage, PromptMessageMultipart]) -> List[str]:
228
+ """
229
+ Extract all image data from a message.
230
+
231
+ Args:
232
+ message: A PromptMessage or PromptMessageMultipart
233
+
234
+ Returns:
235
+ List of image data strings from all image content parts
236
+ """
237
+ if isinstance(message, PromptMessage):
238
+ img_data = get_image_data(message.content)
239
+ return [img_data] if img_data is not None else []
240
+
241
+ result = []
242
+ for content in message.content:
243
+ img_data = get_image_data(content)
244
+ if img_data is not None:
245
+ result.append(img_data)
246
+
247
+ return result
248
+
249
+ @staticmethod
250
+ def get_first_image(message: Union[PromptMessage, PromptMessageMultipart]) -> Optional[str]:
251
+ """
252
+ Get the first available image data from a message.
253
+
254
+ Args:
255
+ message: A PromptMessage or PromptMessageMultipart
256
+
257
+ Returns:
258
+ First image data or None if no image content exists
259
+ """
260
+ if isinstance(message, PromptMessage):
261
+ return get_image_data(message.content)
262
+
263
+ for content in message.content:
264
+ img_data = get_image_data(content)
265
+ if img_data is not None:
266
+ return img_data
267
+
268
+ return None
269
+
270
+ @staticmethod
271
+ def get_all_resources(
272
+ message: Union[PromptMessage, PromptMessageMultipart],
273
+ ) -> List[EmbeddedResource]:
274
+ """
275
+ Extract all embedded resources from a message.
276
+
277
+ Args:
278
+ message: A PromptMessage or PromptMessageMultipart
279
+
280
+ Returns:
281
+ List of EmbeddedResource objects
282
+ """
283
+ if isinstance(message, PromptMessage):
284
+ if isinstance(message.content, EmbeddedResource):
285
+ return [message.content]
286
+ return []
287
+
288
+ return [content for content in message.content if isinstance(content, EmbeddedResource)]
289
+
290
+ @staticmethod
291
+ def has_text(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
292
+ """
293
+ Check if the message has any text content.
294
+
295
+ Args:
296
+ message: A PromptMessage or PromptMessageMultipart
297
+
298
+ Returns:
299
+ True if the message has text content, False otherwise
300
+ """
301
+ return len(MessageContent.get_all_text(message)) > 0
302
+
303
+ @staticmethod
304
+ def has_images(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
305
+ """
306
+ Check if the message has any image content.
307
+
308
+ Args:
309
+ message: A PromptMessage or PromptMessageMultipart
310
+
311
+ Returns:
312
+ True if the message has image content, False otherwise
313
+ """
314
+ return len(MessageContent.get_all_images(message)) > 0
315
+
316
+ @staticmethod
317
+ def has_resources(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
318
+ """
319
+ Check if the message has any embedded resources.
320
+
321
+ Args:
322
+ message: A PromptMessage or PromptMessageMultipart
323
+
324
+ Returns:
325
+ True if the message has embedded resources, False otherwise
326
+ """
327
+ return len(MessageContent.get_all_resources(message)) > 0
@@ -31,7 +31,9 @@ def cast_message_role(role: str) -> MessageRole:
31
31
  return "user"
32
32
 
33
33
 
34
- def create_messages_with_resources(content_sections: List[PromptContent], prompt_files: List[Path]) -> List[PromptMessage]:
34
+ def create_messages_with_resources(
35
+ content_sections: List[PromptContent], prompt_files: List[Path]
36
+ ) -> List[PromptMessage]:
35
37
  """
36
38
  Create a list of messages from content sections, with resources properly handled.
37
39
 
@@ -60,10 +62,14 @@ def create_messages_with_resources(content_sections: List[PromptContent], prompt
60
62
  for resource_path in section.resources:
61
63
  try:
62
64
  # Load resource with information about its type
63
- resource_content, mime_type, is_binary = resource_utils.load_resource_content(resource_path, prompt_files)
65
+ resource_content, mime_type, is_binary = resource_utils.load_resource_content(
66
+ resource_path, prompt_files
67
+ )
64
68
 
65
69
  # Create and add the resource message
66
- resource_message = create_resource_message(resource_path, resource_content, mime_type, is_binary, role)
70
+ resource_message = create_resource_message(
71
+ resource_path, resource_content, mime_type, is_binary, role
72
+ )
67
73
  messages.append(resource_message)
68
74
  except Exception as e:
69
75
  logger.error(f"Error loading resource {resource_path}: {e}")
@@ -76,7 +82,9 @@ def create_content_message(text: str, role: MessageRole) -> PromptMessage:
76
82
  return PromptMessage(role=role, content=TextContent(type="text", text=text))
77
83
 
78
84
 
79
- def create_resource_message(resource_path: str, content: str, mime_type: str, is_binary: bool, role: MessageRole) -> Message:
85
+ def create_resource_message(
86
+ resource_path: str, content: str, mime_type: str, is_binary: bool, role: MessageRole
87
+ ) -> Message:
80
88
  """Create a resource message with the specified content and role"""
81
89
  message_class = UserMessage if role == "user" else AssistantMessage
82
90
 
@@ -86,7 +94,9 @@ def create_resource_message(resource_path: str, content: str, mime_type: str, is
86
94
  return message_class(content=image_content)
87
95
  else:
88
96
  # For other resources, create an EmbeddedResource
89
- embedded_resource = resource_utils.create_embedded_resource(resource_path, content, mime_type, is_binary)
97
+ embedded_resource = resource_utils.create_embedded_resource(
98
+ resource_path, content, mime_type, is_binary
99
+ )
90
100
  return message_class(content=embedded_resource)
91
101
 
92
102