universal-mcp-agents 0.1.18__py3-none-any.whl → 0.1.19rc1__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 universal-mcp-agents might be problematic. Click here for more details.

@@ -2,10 +2,11 @@ import json
2
2
  from typing import Any, Literal, cast
3
3
 
4
4
  from langchain.chat_models import init_chat_model
5
- from langchain_openai import AzureChatOpenAI
6
5
  from pydantic import BaseModel, Field
7
6
  from universal_mcp.applications.application import BaseApplication
8
7
 
8
+ from universal_mcp.agents.llm import load_chat_model
9
+
9
10
  MAX_RETRIES = 3
10
11
 
11
12
 
@@ -28,7 +29,7 @@ def _get_context_as_string(source: Any | list[Any] | dict[str, Any]) -> str:
28
29
  return "\n".join(f"<{k}>\n{str(v)}\n</{k}>" for k, v in source.items())
29
30
 
30
31
 
31
- class LLMApp(BaseApplication):
32
+ class LlmApp(BaseApplication):
32
33
  """
33
34
  An application for leveraging Large Language Models (LLMs) for advanced text processing tasks.
34
35
  """
@@ -40,22 +41,34 @@ class LLMApp(BaseApplication):
40
41
  def generate_text(
41
42
  self,
42
43
  task: str,
43
- context: Any | list[Any] | dict[str, Any],
44
+ context: str | list[str] | dict[str, str] = "",
44
45
  tone: str = "normal",
45
46
  output_format: Literal["markdown", "html", "plain"] = "markdown",
46
47
  length: Literal["very-short", "concise", "normal", "long"] = "concise",
47
48
  ) -> str:
48
49
  """
49
- Generates well-written text for a high-level task using the provided context.
50
-
51
- Use this function for creative writing, summarization, and other text generation tasks.
50
+ Given a high-level writing task and context, returns a well-written text
51
+ that achieves the task, given the context.
52
+
53
+ Example Call:
54
+ generate_text("Summarize this website with the goal of making it easy to understand.", web_content)
55
+ generate_text("Make a markdown table summarizing the key differences between doc_1 and doc_2.", {"doc_1": str(doc_1), "doc_2": str(doc_2)})
56
+ generate_text("Summarize all the provided documents.", [doc_1, doc_2, doc_3])
57
+
58
+ Important:
59
+ - Include specifics of the goal in the context verbatim.
60
+ - Be precise and direct in the task, and include as much context as possible.
61
+ - Include relevant high-level goals or intent in the task.
62
+ - You can provide multiple documents as input, and reference them in the task.
63
+ - You MUST provide the contents of any source documents to `generate_text`.
64
+ - NEVER use `generate_text` to produce JSON for a Pydantic model.
52
65
 
53
66
  Args:
54
67
  task: The main writing task or directive.
55
- context: A single string, list of strings, or dictionary mapping labels to content.
56
- tone: The desired tone of the output (e.g., "formal", "casual", "technical").
68
+ context: A single string, list of strings, or dict mapping labels to content.
69
+ tone: The desired tone of the output (e.g., "normal", "flirty", "formal", "casual", "crisp", "poetic", "technical", "internet-chat", "smartass", etc.).
57
70
  output_format: The desired output format ('markdown', 'html', 'plain').
58
- length: The desired length of the output ('very-short', 'concise', 'normal', 'long').
71
+ length: Desired length of the output ('very-short', 'concise', 'normal', 'long').
59
72
 
60
73
  Returns:
61
74
  The generated text as a string.
@@ -78,31 +91,63 @@ class LLMApp(BaseApplication):
78
91
 
79
92
  full_prompt = f"{prompt}\n\nContext:\n{context_str}\n\n"
80
93
 
81
- model = AzureChatOpenAI(model="gpt-4o", temperature=0.7)
94
+ model = load_chat_model("azure/gpt-5-mini")
82
95
  response = model.with_retry(stop_after_attempt=MAX_RETRIES).invoke(full_prompt)
83
96
  return str(response.content)
84
97
 
85
98
  def classify_data(
86
99
  self,
87
- task: str,
100
+ classification_task_and_requirements: str,
88
101
  context: Any | list[Any] | dict[str, Any],
89
102
  class_descriptions: dict[str, str],
90
103
  ) -> dict[str, Any]:
91
104
  """
92
- Classifies data into one of several categories based on a given task and context.
105
+ Classifies and compares data based on given requirements.
106
+
107
+ Use `classify_data` for tasks which need to classify data into one of many categories.
108
+ If making multiple binary classifications, call `classify_data` for each.
109
+
110
+ Guidance:
111
+ - Prefer to use classify_data operations to compare strings, rather than string ops.
112
+ - Prefer to include an "Unsure" category for classification tasks.
113
+ - The `class_descriptions` dict argument MUST be a map from possible class names to a precise description.
114
+ - Use precise and specific class names and concise descriptions.
115
+ - Pass ALL relevant context, preferably as a dict mapping labels to content.
116
+ - Returned dict maps each possible class name to a probability.
117
+
118
+ Example Usage:
119
+ classification_task_and_requirements = "Does the document contain an address?"
120
+ class_descriptions = {
121
+ "Is_Address": "Valid addresses usually have street names, city, and zip codes.",
122
+ "Not_Address": "Not valid addresses."
123
+ }
124
+ classification = classify_data(
125
+ classification_task_and_requirements,
126
+ {"address": extracted_address},
127
+ class_descriptions
128
+ )
129
+ if classification["probabilities"]["Is_Address"] > 0.5:
130
+ ...
93
131
 
94
132
  Args:
95
- task: The classification question and any specific rules or requirements.
96
- context: The data to be classified, provided as a string, list, or dictionary.
97
- class_descriptions: A dictionary mapping class names to their descriptions.
133
+ classification_task_and_requirements: The classification question and rules.
134
+ context: The data to classify (string, list, or dict).
135
+ class_descriptions: Mapping from class names to descriptions.
136
+
137
+ Tags:
138
+ important
98
139
 
99
140
  Returns:
100
- A dictionary containing the classification probabilities, the reasoning, and the top class.
141
+ dict: {
142
+ "probabilities": dict[str, float],
143
+ "reason": str,
144
+ "top_class": str,
145
+ }
101
146
  """
102
147
  context_str = _get_context_as_string(context)
103
148
 
104
149
  prompt = (
105
- f"{task}\n\n"
150
+ f"{classification_task_and_requirements}\n\n"
106
151
  f"This is a classification task.\nPossible classes and descriptions:\n"
107
152
  f"{json.dumps(class_descriptions, indent=2)}\n\n"
108
153
  f"Context:\n{context_str}\n\n"
@@ -125,25 +170,61 @@ class LLMApp(BaseApplication):
125
170
 
126
171
  def extract_data(
127
172
  self,
128
- task: str,
173
+ extraction_task: str,
129
174
  source: Any | list[Any] | dict[str, Any],
130
175
  output_schema: dict[str, Any],
131
176
  ) -> dict[str, Any]:
132
177
  """
133
- Extracts structured data from unstructured text based on a provided JSON schema.
178
+ Extracts structured data from unstructured data (documents, webpages, images, large bodies of text),
179
+ returning a dictionary matching the given output_schema.
180
+
181
+ You MUST anticipate Exception raised for unextractable data; skip this item if applicable.
182
+
183
+ Strongly prefer to:
184
+ - Be comprehensive, specific, and precise on the data you want to extract.
185
+ - Use optional fields everywhere.
186
+ - Extract multiple items from each source unless otherwise specified.
187
+ - The more specific your extraction task and output_schema are, the better the results.
134
188
 
135
189
  Args:
136
- task: A description of the data to be extracted.
137
- source: The unstructured data to extract from (e.g., document, webpage content).
138
- output_schema: A valid JSON schema with a 'title' and 'description'.
190
+ extraction_task: The directive describing what to extract.
191
+ source: The unstructured data to extract from.
192
+ output_schema: must be a valid JSON schema with top-level 'title' and 'description' keys.
139
193
 
140
194
  Returns:
141
195
  A dictionary containing the extracted data, matching the provided schema.
196
+
197
+ Example:
198
+ news_articles_schema = {
199
+ "title": "NewsArticleList",
200
+ "description": "A list of news articles with headlines and URLs",
201
+ "type": "object",
202
+ "properties": {
203
+ "articles": {
204
+ "type": "array",
205
+ "items": {
206
+ "type": "object",
207
+ "properties": {
208
+ "headline": {
209
+ "type": "string"
210
+ },
211
+ "url": {
212
+ "type": "string"
213
+ }
214
+ },
215
+ "required": ["headline", "url"]
216
+ }
217
+ }
218
+ },
219
+ "required": ["articles"]
220
+ }
221
+
222
+ news_articles = extract_data("Extract headlines and their corresponding URLs.", content, news_articles_schema)
142
223
  """
143
224
  context_str = _get_context_as_string(source)
144
225
 
145
226
  prompt = (
146
- f"{task}\n\n"
227
+ f"{extraction_task}\n\n"
147
228
  f"Context:\n{context_str}\n\n"
148
229
  "Return ONLY a valid JSON object that conforms to the provided schema, with no extra text."
149
230
  )
@@ -156,3 +237,64 @@ class LLMApp(BaseApplication):
156
237
  .invoke(prompt)
157
238
  )
158
239
  return cast(dict[str, Any], response)
240
+
241
+ def call_llm(
242
+ self,
243
+ task_instructions: str,
244
+ context: Any | list[Any] | dict[str, Any],
245
+ output_schema: dict[str, Any],
246
+ ) -> dict[str, Any]:
247
+ """
248
+ Call a Large Language Model (LLM) with an instruction and contextual information,
249
+ returning a dictionary matching the given output_schema.
250
+ Can be used for tasks like creative writing, llm reasoning based content generation, etc.
251
+
252
+ You MUST anticipate Exceptions in reasoning based tasks which will lead to some empty fields
253
+ in the returned output; skip this item if applicable.
254
+
255
+ General Guidelines:
256
+ - Be comprehensive, specific, and precise on the task instructions.
257
+ - Include as much context as possible.
258
+ - You can provide multiple items in context, and reference them in the task.
259
+ - Include relevant high-level goals or intent in the task.
260
+ - In the output_schema, use required field wherever necessary.
261
+ - The more specific your task instructions and output_schema are, the better the results.
262
+
263
+ Guidelines for content generation tasks:
264
+ - Feel free to add instructions for tone, length, and format (markdown, html, plain-text, xml)
265
+ - Some examples of tone are: "normal", "flirty", "formal", "casual", "crisp", "poetic", "technical", "internet-chat", "smartass", etc.
266
+ - Prefer length to be concise by default. Other examples are: "very-short", "concise", "normal", "long", "2-3 lines", etc.
267
+ - In format prefer plain-text but you can also use markdown and html wherever useful.
268
+
269
+ Args:
270
+ task_instructions: The main directive for the LLM (e.g., "Summarize the article" or "Extract key entities").
271
+ context:
272
+ A dictionary containing named text elements that provide additional
273
+ information for the LLM. Keys are labels (e.g., 'article', 'transcript'),
274
+ values are strings of content.
275
+ output_schema: must be a valid JSON schema with top-level 'title' and 'description' keys.
276
+
277
+ Returns:
278
+ dict: Parsed JSON object matching the desired output_schema.
279
+
280
+ """
281
+ context_str = _get_context_as_string(context)
282
+
283
+ prompt = f"{task_instructions}\n\nContext:\n{context_str}\n\nReturn ONLY a valid JSON object, no extra text."
284
+
285
+ model = init_chat_model(model="claude-4-sonnet-20250514", temperature=0)
286
+
287
+ response = (
288
+ model.with_structured_output(schema=output_schema, method="json_mode")
289
+ .with_retry(stop_after_attempt=MAX_RETRIES)
290
+ .invoke(prompt)
291
+ )
292
+ return cast(dict[str, Any], response)
293
+
294
+ def list_tools(self):
295
+ return [
296
+ self.generate_text,
297
+ self.classify_data,
298
+ self.extract_data,
299
+ self.call_llm,
300
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp-agents
3
- Version: 0.1.18
3
+ Version: 0.1.19rc1
4
4
  Summary: Add your description here
5
5
  Project-URL: Homepage, https://github.com/universal-mcp/applications
6
6
  Project-URL: Repository, https://github.com/universal-mcp/applications
@@ -1,9 +1,10 @@
1
- universal_mcp/agents/__init__.py,sha256=5aE4zVgem6ehzfRrt5QqE6gLi7949vySZAn_uFuaU7Q,1252
1
+ universal_mcp/agents/__init__.py,sha256=rXWhqmhXdhUdId7QzuQHUpWUwfioPmj7ksu6RHZvCFI,1368
2
2
  universal_mcp/agents/base.py,sha256=GmagwWFJdPpp_yLeAfsrr4fu-zzxh7CgIlBJbTgFgWM,7072
3
3
  universal_mcp/agents/cli.py,sha256=AG9e4iSX3GazT537573YrYT1wSaZYOr42rrYQ7xP3YA,1016
4
4
  universal_mcp/agents/hil.py,sha256=_5PCK6q0goGm8qylJq44aSp2MadP-yCPvhOJYKqWLMo,3808
5
5
  universal_mcp/agents/llm.py,sha256=hVRwjZs3MHl5_3BWedmurs2Jt1oZDfFX0Zj9F8KH7fk,1787
6
6
  universal_mcp/agents/react.py,sha256=8XQvJ0HLVgc-K0qn9Ml48WGcgUGuIKtL67HatlT6Da0,3334
7
+ universal_mcp/agents/sandbox.py,sha256=Int2O8JNFPlB8c7gb86KRxlNbuV0zdz5_NCo_GMcCds,2876
7
8
  universal_mcp/agents/simple.py,sha256=NSATg5TWzsRNS7V3LFiDG28WSOCIwCdcC1g7NRwg2nM,2095
8
9
  universal_mcp/agents/utils.py,sha256=P6W9k6XAOBp6tdjC2VTP4tE0B2M4-b1EDmr-ylJ47Pw,7765
9
10
  universal_mcp/agents/bigtool/__init__.py,sha256=mZG8dsaCVyKlm82otxtiTA225GIFLUCUUYPEIPF24uw,2299
@@ -28,12 +29,12 @@ universal_mcp/agents/codeact/sandbox.py,sha256=NjN6ISj8psFtHf8V0w24ChJdUMUWkq7Or
28
29
  universal_mcp/agents/codeact/state.py,sha256=WTPfpxDlGRnlr5tZuXMg_KU7GS7TZbnrIKslOvZLbQI,565
29
30
  universal_mcp/agents/codeact/utils.py,sha256=JUbT_HYGS_D1BzmzoVpORIe7SGur1KgJguTZ_1tZ4JY,1918
30
31
  universal_mcp/agents/codeact0/__init__.py,sha256=ebKkpgg-0UnsvDtagEJ2tMer1VsfhmEE5KJcFzUk9fU,133
31
- universal_mcp/agents/codeact0/__main__.py,sha256=V2wLWW9ym3rtiSvPEs-N0Mki7G5dYHzV5dAsAoF-ygQ,1148
32
+ universal_mcp/agents/codeact0/__main__.py,sha256=xeqNuawP9M8JVAnkhLesalnpI_TakC49ATJaSCzCsYs,880
32
33
  universal_mcp/agents/codeact0/agent.py,sha256=9BInAQr3csES-XHSscmeJlYJ3-wQUHPvLOf-6wFILUU,6695
33
34
  universal_mcp/agents/codeact0/config.py,sha256=H-1woj_nhSDwf15F63WYn723y4qlRefXzGxuH81uYF0,2215
34
35
  universal_mcp/agents/codeact0/langgraph_agent.py,sha256=ehjMV_Z1118pCFWB_Sa5H7XnUp0udsbUHjfjXjhIQM8,435
35
- universal_mcp/agents/codeact0/llm_tool.py,sha256=fydA4BbSnhG3OLMR_VEtJxTPTmRK_mMvXGsUCO-5Mig,13829
36
- universal_mcp/agents/codeact0/playbook_agent.py,sha256=JIyn4RZxFDJnXW7-jM16RLM1ylbVU02M8RBJuj1oBUs,17811
36
+ universal_mcp/agents/codeact0/llm_tool.py,sha256=q-hiqkKtjVmpyNceFoRgo7hvKh4HtQf_I1VudRUEPR0,11075
37
+ universal_mcp/agents/codeact0/playbook_agent.py,sha256=Eq_us8j7plxgep1LuJ4I3u8qxjS95_2vGEaPR3g8A-o,17796
37
38
  universal_mcp/agents/codeact0/prompts.py,sha256=CF2X6zSK1lYQ9ef78cn0iN0oQN_tDe3T02Ecfn1o45U,8627
38
39
  universal_mcp/agents/codeact0/sandbox.py,sha256=zMgHrWnQYkSkJb2MzfXvT3euCc4hvqzBE_EbX2_iLxA,3142
39
40
  universal_mcp/agents/codeact0/state.py,sha256=Y-Rzn_S7--aXH18KPvyhqDqOOB-miu1lsAmLgmMlaAg,1259
@@ -42,9 +43,22 @@ universal_mcp/agents/codeact0/utils.py,sha256=jAZItSd3KGDkY9PquSWRIFCj9N26K9Kt0H
42
43
  universal_mcp/agents/shared/__main__.py,sha256=XxH5qGDpgFWfq7fwQfgKULXGiUgeTp_YKfcxftuVZq8,1452
43
44
  universal_mcp/agents/shared/prompts.py,sha256=yjP3zbbuKi87qCj21qwTTicz8TqtkKgnyGSeEjMu3ho,3761
44
45
  universal_mcp/agents/shared/tool_node.py,sha256=DC9F-Ri28Pam0u3sXWNODVgmj9PtAEUb5qP1qOoGgfs,9169
45
- universal_mcp/applications/llm/__init__.py,sha256=xnpxq4Wl_pevvwtSUtEwcty8_d61ywO1V2YnEXyCREY,46
46
- universal_mcp/applications/llm/app.py,sha256=iNLU6z2LRZc01GfSKvV0vNzT1LhKAjq_UrSJEmjthjw,6032
46
+ universal_mcp/agents/unified/README.md,sha256=lcZobDA7MVm7vOAefLr4EMlEmgmODhndOZhwrOQO8lg,3658
47
+ universal_mcp/agents/unified/__init__.py,sha256=Oi5nfloc1saGh0HuYZvw2h7NRRWKKVptBXg6PFK6lnw,60
48
+ universal_mcp/agents/unified/__main__.py,sha256=XzHdp_AEd7k2CaWmsUekk3r1eefjmZSKsPhyBBWQDHU,865
49
+ universal_mcp/agents/unified/agent.py,sha256=jQrEk_AcaWpbty5hlncI9cTOOw1W_U4KYQB7xiraoYA,13551
50
+ universal_mcp/agents/unified/langgraph_agent.py,sha256=7v76Uv_1UydCsQpDj99k1FtR1wm7e9yZihwCYdFebwY,403
51
+ universal_mcp/agents/unified/llm_tool.py,sha256=-pAz04OrbZ_dJ2ueysT1qZd02DrbLY4EbU0tiuF_UNU,798
52
+ universal_mcp/agents/unified/prompts.py,sha256=ojHoZUJ1tLc7CwOZPWRJvzdwC_H3hE6PgZ9GKfHqAhU,9521
53
+ universal_mcp/agents/unified/sandbox.py,sha256=zMgHrWnQYkSkJb2MzfXvT3euCc4hvqzBE_EbX2_iLxA,3142
54
+ universal_mcp/agents/unified/state.py,sha256=6gtl1TV4qnnvkhXgHntH13jlVL53S00dFtw_mPKTFw4,1380
55
+ universal_mcp/agents/unified/tools.py,sha256=7hcFJxR26w_VCOWL8Oec8Ezfn3Auyv3YgeRv9f8j9xo,7642
56
+ universal_mcp/agents/unified/utils.py,sha256=jAZItSd3KGDkY9PquSWRIFCj9N26K9Kt0HKQ_jwvvSQ,15944
57
+ universal_mcp/applications/filesystem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
+ universal_mcp/applications/filesystem/app.py,sha256=0TRjjm8YnslVRSmfkXI7qQOAlqWlD1eEn8Jm0xBeigs,5561
59
+ universal_mcp/applications/llm/__init__.py,sha256=_XGRxN3O1--ZS5joAsPf8IlI9Qa6negsJrwJ5VJXno0,46
60
+ universal_mcp/applications/llm/app.py,sha256=oqX3byvlFRmeRo4jJJxUBGy-iTDGm2fplMEKA2pcMtw,12743
47
61
  universal_mcp/applications/ui/app.py,sha256=c7OkZsO2fRtndgAzAQbKu-1xXRuRp9Kjgml57YD2NR4,9459
48
- universal_mcp_agents-0.1.18.dist-info/METADATA,sha256=_OEOGCno6HWgMENbxmi7zUeeMdyMcZyLVUELcBS72Rs,878
49
- universal_mcp_agents-0.1.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
- universal_mcp_agents-0.1.18.dist-info/RECORD,,
62
+ universal_mcp_agents-0.1.19rc1.dist-info/METADATA,sha256=6euKZt6O6J-GgvtqE57uQbZRrNtvL7Al2wGdOEBALvQ,881
63
+ universal_mcp_agents-0.1.19rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
64
+ universal_mcp_agents-0.1.19rc1.dist-info/RECORD,,