universal-mcp 0.1.20rc1__tar.gz → 0.1.20rc2__tar.gz

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 (55) hide show
  1. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/PKG-INFO +1 -1
  2. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/pyproject.toml +1 -1
  3. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/adapters.py +1 -1
  4. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/openapi.py +19 -42
  5. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/.gitignore +0 -0
  6. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/LICENSE +0 -0
  7. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/README.md +0 -0
  8. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/__init__.py +0 -0
  9. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/conftest.py +0 -0
  10. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_api_generator.py +0 -0
  11. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_api_integration.py +0 -0
  12. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_applications.py +0 -0
  13. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_localserver.py +0 -0
  14. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_stores.py +0 -0
  15. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_tool.py +0 -0
  16. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_tool_manager.py +0 -0
  17. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/tests/test_zenquotes.py +0 -0
  18. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/__init__.py +0 -0
  19. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/analytics.py +0 -0
  20. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/applications/README.md +0 -0
  21. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/applications/__init__.py +0 -0
  22. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/applications/application.py +0 -0
  23. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/cli.py +0 -0
  24. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/config.py +0 -0
  25. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/exceptions.py +0 -0
  26. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/integrations/README.md +0 -0
  27. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/integrations/__init__.py +0 -0
  28. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/integrations/integration.py +0 -0
  29. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/logger.py +0 -0
  30. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/py.typed +0 -0
  31. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/servers/README.md +0 -0
  32. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/servers/__init__.py +0 -0
  33. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/servers/server.py +0 -0
  34. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/stores/README.md +0 -0
  35. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/stores/__init__.py +0 -0
  36. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/stores/store.py +0 -0
  37. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/README.md +0 -0
  38. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/__init__.py +0 -0
  39. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/func_metadata.py +0 -0
  40. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/manager.py +0 -0
  41. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/tools/tools.py +0 -0
  42. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/__init__.py +0 -0
  43. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/agentr.py +0 -0
  44. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/common.py +0 -0
  45. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/docstring_parser.py +0 -0
  46. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/installation.py +0 -0
  47. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/__inti__.py +0 -0
  48. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/api_generator.py +0 -0
  49. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/api_splitter.py +0 -0
  50. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/docgen.py +0 -0
  51. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/preprocessor.py +0 -0
  52. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/openapi/readme.py +0 -0
  53. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/singleton.py +0 -0
  54. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/templates/README.md.j2 +0 -0
  55. {universal_mcp-0.1.20rc1 → universal_mcp-0.1.20rc2}/src/universal_mcp/utils/templates/api_client.py.j2 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp
3
- Version: 0.1.20rc1
3
+ Version: 0.1.20rc2
4
4
  Summary: Universal MCP acts as a middle ware for your API applications. It can store your credentials, authorize, enable disable apps on the fly and much more.
5
5
  Author-email: Manoj Bajaj <manojbajaj95@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "universal-mcp"
7
- version = "0.1.20-rc1"
7
+ version = "0.1.20-rc2"
8
8
  description = "Universal MCP acts as a middle ware for your API applications. It can store your credentials, authorize, enable disable apps on the fly and much more."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -17,7 +17,7 @@ def convert_tool_to_mcp_tool(
17
17
  from mcp.server.fastmcp.server import MCPTool
18
18
 
19
19
  return MCPTool(
20
- name=tool.name,
20
+ name=tool.name[:63],
21
21
  description=tool.description or "",
22
22
  inputSchema=tool.parameters,
23
23
  )
@@ -643,43 +643,28 @@ def _generate_method_code(path, method, operation):
643
643
  param_details[param_obj.name] = param_obj
644
644
 
645
645
  # Fetch request body example
646
- request_body_example_str = None
646
+ example_data = None # Initialize example_data here for wider scope
647
+
647
648
  if has_body:
648
649
  try:
649
650
  json_content = operation["requestBody"]["content"]["application/json"]
650
- example_data = None
651
+ #From direct content definition
651
652
  if "example" in json_content:
652
653
  example_data = json_content["example"]
653
654
  elif "examples" in json_content and json_content["examples"]:
654
655
  first_example_key = list(json_content["examples"].keys())[0]
655
656
  example_data = json_content["examples"][first_example_key].get("value")
656
-
657
- if example_data is not None:
658
- try:
659
- example_json = json.dumps(example_data, indent=2)
660
- indented_example = textwrap.indent(example_json, " " * 8) # 8 spaces
661
- request_body_example_str = f"\n Example:\n ```json\n{indented_example}\n ```"
662
- except TypeError:
663
- request_body_example_str = f"\n Example: {example_data}"
657
+ #If not found directly, try from resolved body schema (for nested/referenced examples)
658
+ if example_data is None and body_schema_to_use and "example" in body_schema_to_use:
659
+ example_data = body_schema_to_use["example"]
664
660
  except KeyError:
665
- pass # No example found
666
-
667
- # Identify the last argument related to the request body
668
- last_body_arg_name = None
669
- # request_body_params contains the names as they appear in the signature
670
- if final_request_body_arg_names_for_signature: # Use the new list with final aliased names
671
- # Find which of these appears last in the combined args list
672
- body_args_in_signature = [
673
- a.split("=")[0] for a in args if a.split("=")[0] in final_request_body_arg_names_for_signature
674
- ]
675
- if body_args_in_signature:
676
- last_body_arg_name = body_args_in_signature[-1]
661
+ pass # No example found or application/json content not present
677
662
 
678
663
  if signature_arg_names:
679
664
  args_doc_lines.append("Args:")
680
665
  for arg_signature_str in args:
681
666
  arg_name = arg_signature_str.split("=")[0]
682
- example_str = None # Initialize example_str here
667
+ example_str = None # Initialize example_str here for each argument
683
668
  detail = param_details.get(arg_name)
684
669
  if detail:
685
670
  desc = detail.description or "No description provided."
@@ -692,26 +677,22 @@ def _generate_method_code(path, method, operation):
692
677
  if detail.example and not detail.is_file: # Don't show schema example for file inputs
693
678
  example_str = repr(detail.example)
694
679
  arg_line += f" Example: {example_str}."
695
-
696
- # Append the full body example after the last body-related argument
697
- if arg_name == last_body_arg_name and request_body_example_str:
698
- # Remove the simple Example: if it exists before adding the detailed one
699
- if example_str and (
700
- f" Example: {example_str}." in arg_line or f" Example: {example_str} ." in arg_line
701
- ):
702
- arg_line = arg_line.replace(
703
- f" Example: {example_str}.", ""
704
- ) # Remove with or without trailing period
705
- arg_line += request_body_example_str # Append the formatted JSON example
680
+ # Fallback for body parameters if no direct example was found
681
+ elif not example_str and detail.where == "body" and example_data and isinstance(example_data, dict) and detail.identifier in example_data:
682
+ current_body_param_example = example_data[detail.identifier]
683
+ if current_body_param_example is not None: # Ensure the extracted part is not None
684
+ try:
685
+ arg_line += f" Example: {repr(current_body_param_example)}."
686
+ except Exception: # Fallback if repr fails
687
+ arg_line += " Example: [Could not represent example]."
706
688
 
707
689
  args_doc_lines.append(arg_line)
708
- elif arg_name == final_empty_body_param_name and has_empty_body: # Use potentially suffixed name
690
+
691
+ elif arg_name == final_empty_body_param_name and has_empty_body:
709
692
  args_doc_lines.append(
710
693
  f" {arg_name} (dict | None): Optional dictionary for an empty JSON request body (e.g., {{}})."
711
694
  )
712
- if ( arg_name == last_body_arg_name and request_body_example_str ):
713
- args_doc_lines[-1] += request_body_example_str
714
- elif arg_name == raw_body_param_name: # Docstring for raw body parameter
695
+ elif arg_name == raw_body_param_name:
715
696
  raw_body_type_hint = "bytes"
716
697
  raw_body_desc = "Raw binary content for the request body."
717
698
  if selected_content_type and "text" in selected_content_type:
@@ -720,13 +701,9 @@ def _generate_method_code(path, method, operation):
720
701
  elif selected_content_type and selected_content_type.startswith("image/"):
721
702
  raw_body_type_hint = "bytes (image data)"
722
703
  raw_body_desc = f"Raw image content ({selected_content_type}) for the request body."
723
-
724
704
  args_doc_lines.append(
725
705
  f" {arg_name} ({raw_body_type_hint} | None): {raw_body_desc}"
726
706
  )
727
- # Example for raw body is harder to give generically, but if present in spec, could be added.
728
- if ( arg_name == last_body_arg_name and request_body_example_str ):
729
- args_doc_lines[-1] += request_body_example_str
730
707
 
731
708
  if args_doc_lines:
732
709
  docstring_parts.append("\n".join(args_doc_lines))