universal-mcp 0.1.12__py3-none-any.whl → 0.1.13rc2__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 (109) hide show
  1. universal_mcp/applications/__init__.py +51 -7
  2. universal_mcp/cli.py +109 -17
  3. universal_mcp/integrations/__init__.py +1 -1
  4. universal_mcp/integrations/integration.py +79 -0
  5. universal_mcp/servers/README.md +79 -0
  6. universal_mcp/servers/server.py +17 -29
  7. universal_mcp/stores/README.md +74 -0
  8. universal_mcp/stores/store.py +0 -2
  9. universal_mcp/templates/README.md.j2 +93 -0
  10. universal_mcp/templates/api_client.py.j2 +27 -0
  11. universal_mcp/tools/README.md +86 -0
  12. universal_mcp/tools/tools.py +1 -1
  13. universal_mcp/utils/agentr.py +90 -0
  14. universal_mcp/utils/api_generator.py +166 -208
  15. universal_mcp/utils/openapi.py +221 -321
  16. universal_mcp/utils/singleton.py +23 -0
  17. {universal_mcp-0.1.12.dist-info → universal_mcp-0.1.13rc2.dist-info}/METADATA +16 -41
  18. universal_mcp-0.1.13rc2.dist-info/RECORD +38 -0
  19. universal_mcp/applications/ahrefs/README.md +0 -76
  20. universal_mcp/applications/ahrefs/__init__.py +0 -0
  21. universal_mcp/applications/ahrefs/app.py +0 -2291
  22. universal_mcp/applications/cal_com_v2/README.md +0 -175
  23. universal_mcp/applications/cal_com_v2/__init__.py +0 -0
  24. universal_mcp/applications/cal_com_v2/app.py +0 -5390
  25. universal_mcp/applications/calendly/README.md +0 -78
  26. universal_mcp/applications/calendly/__init__.py +0 -0
  27. universal_mcp/applications/calendly/app.py +0 -1195
  28. universal_mcp/applications/clickup/README.md +0 -160
  29. universal_mcp/applications/clickup/__init__.py +0 -0
  30. universal_mcp/applications/clickup/app.py +0 -5009
  31. universal_mcp/applications/coda/README.md +0 -133
  32. universal_mcp/applications/coda/__init__.py +0 -0
  33. universal_mcp/applications/coda/app.py +0 -3671
  34. universal_mcp/applications/e2b/README.md +0 -37
  35. universal_mcp/applications/e2b/app.py +0 -65
  36. universal_mcp/applications/elevenlabs/README.md +0 -84
  37. universal_mcp/applications/elevenlabs/__init__.py +0 -0
  38. universal_mcp/applications/elevenlabs/app.py +0 -1402
  39. universal_mcp/applications/falai/README.md +0 -42
  40. universal_mcp/applications/falai/__init__.py +0 -0
  41. universal_mcp/applications/falai/app.py +0 -332
  42. universal_mcp/applications/figma/README.md +0 -74
  43. universal_mcp/applications/figma/__init__.py +0 -0
  44. universal_mcp/applications/figma/app.py +0 -1261
  45. universal_mcp/applications/firecrawl/README.md +0 -45
  46. universal_mcp/applications/firecrawl/app.py +0 -268
  47. universal_mcp/applications/github/README.md +0 -47
  48. universal_mcp/applications/github/app.py +0 -429
  49. universal_mcp/applications/gong/README.md +0 -88
  50. universal_mcp/applications/gong/__init__.py +0 -0
  51. universal_mcp/applications/gong/app.py +0 -2297
  52. universal_mcp/applications/google_calendar/app.py +0 -442
  53. universal_mcp/applications/google_docs/README.md +0 -40
  54. universal_mcp/applications/google_docs/app.py +0 -88
  55. universal_mcp/applications/google_drive/README.md +0 -44
  56. universal_mcp/applications/google_drive/app.py +0 -286
  57. universal_mcp/applications/google_mail/README.md +0 -47
  58. universal_mcp/applications/google_mail/app.py +0 -664
  59. universal_mcp/applications/google_sheet/README.md +0 -42
  60. universal_mcp/applications/google_sheet/app.py +0 -150
  61. universal_mcp/applications/hashnode/app.py +0 -81
  62. universal_mcp/applications/hashnode/prompt.md +0 -23
  63. universal_mcp/applications/heygen/README.md +0 -69
  64. universal_mcp/applications/heygen/__init__.py +0 -0
  65. universal_mcp/applications/heygen/app.py +0 -956
  66. universal_mcp/applications/mailchimp/README.md +0 -306
  67. universal_mcp/applications/mailchimp/__init__.py +0 -0
  68. universal_mcp/applications/mailchimp/app.py +0 -10937
  69. universal_mcp/applications/markitdown/app.py +0 -44
  70. universal_mcp/applications/notion/README.md +0 -55
  71. universal_mcp/applications/notion/__init__.py +0 -0
  72. universal_mcp/applications/notion/app.py +0 -527
  73. universal_mcp/applications/perplexity/README.md +0 -37
  74. universal_mcp/applications/perplexity/app.py +0 -65
  75. universal_mcp/applications/reddit/README.md +0 -45
  76. universal_mcp/applications/reddit/app.py +0 -379
  77. universal_mcp/applications/replicate/README.md +0 -65
  78. universal_mcp/applications/replicate/__init__.py +0 -0
  79. universal_mcp/applications/replicate/app.py +0 -980
  80. universal_mcp/applications/resend/README.md +0 -38
  81. universal_mcp/applications/resend/app.py +0 -37
  82. universal_mcp/applications/retell_ai/README.md +0 -46
  83. universal_mcp/applications/retell_ai/__init__.py +0 -0
  84. universal_mcp/applications/retell_ai/app.py +0 -333
  85. universal_mcp/applications/rocketlane/README.md +0 -42
  86. universal_mcp/applications/rocketlane/__init__.py +0 -0
  87. universal_mcp/applications/rocketlane/app.py +0 -194
  88. universal_mcp/applications/serpapi/README.md +0 -37
  89. universal_mcp/applications/serpapi/app.py +0 -73
  90. universal_mcp/applications/spotify/README.md +0 -116
  91. universal_mcp/applications/spotify/__init__.py +0 -0
  92. universal_mcp/applications/spotify/app.py +0 -2526
  93. universal_mcp/applications/supabase/README.md +0 -112
  94. universal_mcp/applications/supabase/__init__.py +0 -0
  95. universal_mcp/applications/supabase/app.py +0 -2970
  96. universal_mcp/applications/tavily/README.md +0 -38
  97. universal_mcp/applications/tavily/app.py +0 -51
  98. universal_mcp/applications/wrike/README.md +0 -71
  99. universal_mcp/applications/wrike/__init__.py +0 -0
  100. universal_mcp/applications/wrike/app.py +0 -1372
  101. universal_mcp/applications/youtube/README.md +0 -82
  102. universal_mcp/applications/youtube/__init__.py +0 -0
  103. universal_mcp/applications/youtube/app.py +0 -1428
  104. universal_mcp/applications/zenquotes/README.md +0 -37
  105. universal_mcp/applications/zenquotes/app.py +0 -31
  106. universal_mcp/integrations/agentr.py +0 -112
  107. universal_mcp-0.1.12.dist-info/RECORD +0 -119
  108. {universal_mcp-0.1.12.dist-info → universal_mcp-0.1.13rc2.dist-info}/WHEEL +0 -0
  109. {universal_mcp-0.1.12.dist-info → universal_mcp-0.1.13rc2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,93 @@
1
+ # {{ name }} MCP Server
2
+
3
+ An MCP Server for the {{ name }} API.
4
+
5
+ ## 📋 Prerequisites
6
+
7
+ Before you begin, ensure you have met the following requirements:
8
+ * Python 3.11+ (Recommended)
9
+ * [uv](https://github.com/astral-sh/uv) installed globally (`pip install uv`)
10
+
11
+ ## 🛠️ Setup Instructions
12
+
13
+ Follow these steps to get the development environment up and running:
14
+
15
+ ### 1. Sync Project Dependencies
16
+ Navigate to the project root directory (where `pyproject.toml` is located).
17
+ ```bash
18
+ uv sync
19
+ ```
20
+ This command uses `uv` to install all dependencies listed in `pyproject.toml` into a virtual environment (`.venv`) located in the project root.
21
+
22
+ ### 2. Activate the Virtual Environment
23
+ Activating the virtual environment ensures that you are using the project's specific dependencies and Python interpreter.
24
+ - On **Linux/macOS**:
25
+ ```bash
26
+ source .venv/bin/activate
27
+ ```
28
+ - On **Windows**:
29
+ ```bash
30
+ .venv\\Scripts\\activate
31
+ ```
32
+
33
+ ### 3. Start the MCP Inspector
34
+ Use the MCP CLI to start the application in development mode.
35
+ ```bash
36
+ mcp dev src/{{ name.lower() }}/mcp.py
37
+ ```
38
+ The MCP inspector should now be running. Check the console output for the exact address and port.
39
+
40
+ ## 🔌 Supported Integrations
41
+
42
+ - AgentR
43
+ - API Key (Coming Soon)
44
+ - OAuth (Coming Soon)
45
+
46
+ ## 🛠️ Tool List
47
+
48
+ This is automatically generated from OpenAPI schema for the {{ name }} API.
49
+
50
+ {% if tools %}
51
+ | Tool | Description |
52
+ |------|-------------|
53
+ {%- for tool_name, tool_desc in tools %}
54
+ | `{{ tool_name }}` | {{ tool_desc }} |
55
+ {%- endfor %}
56
+ {% else %}
57
+ No tools with documentation were found in this API client.
58
+ {% endif %}
59
+
60
+ ## 📁 Project Structure
61
+
62
+ The generated project has a standard layout:
63
+ ```
64
+ .
65
+ ├── src/ # Source code directory
66
+ │ └── {{ name.lower() }}/
67
+ │ ├── __init__.py
68
+ │ └── mcp.py # Server is launched here
69
+ │ └── app.py # Application tools are defined here
70
+ ├── tests/ # Directory for project tests
71
+ ├── .env # Environment variables (for local development)
72
+ ├── pyproject.toml # Project dependencies managed by uv
73
+ ├── README.md # This file
74
+ ```
75
+
76
+ ## 📝 License
77
+
78
+ This project is licensed under the MIT License.
79
+
80
+ ---
81
+
82
+ _This project was generated using **MCP CLI** — Happy coding! 🚀_
83
+
84
+ ## Usage
85
+
86
+ - Login to AgentR
87
+ - Follow the quickstart guide to setup MCP Server for your client
88
+ - Visit Apps Store and enable the {{ name }} app
89
+ - Restart the MCP Server
90
+
91
+ ### Local Development
92
+
93
+ - Follow the README to test with the local MCP Server
@@ -0,0 +1,27 @@
1
+ from typing import Any, Annotated
2
+ from universal_mcp.applications import APIApplication
3
+ from universal_mcp.integrations import Integration
4
+
5
+ class {{ class_name }}(APIApplication):
6
+ def __init__(self, integration: Integration = None, **kwargs) -> None:
7
+ super().__init__(name='{{ class_name.lower() }}', integration=integration, **kwargs)
8
+ self.base_url = "{{ base_url }}"
9
+
10
+ {% for method in methods %}
11
+ def {{ method.name }}(self, {{ method.args_str }}) -> {{ method.return_type }}:
12
+ """
13
+ {{ method.description }}
14
+ {% if method.tags %}
15
+ Tags: {{ method.tags|join(', ') }}
16
+ {% endif %}
17
+ """
18
+
19
+ {{ method.implementation|indent(8) }}
20
+ {% endfor %}
21
+
22
+ def list_tools(self):
23
+ return [
24
+ {% for method in methods %}
25
+ self.{{ method.name }}{% if not loop.last %},{% endif %}
26
+ {%- endfor %}
27
+ ]
@@ -0,0 +1,86 @@
1
+ # Universal MCP Tools
2
+
3
+ This directory contains the core tooling infrastructure for Universal MCP, providing a flexible and extensible framework for defining, managing, and converting tools across different formats.
4
+
5
+ ## Components
6
+
7
+ ### `tools.py`
8
+ The main module containing the core tool management functionality:
9
+
10
+ - `Tool` class: Represents a tool with metadata, validation, and execution capabilities
11
+ - `ToolManager` class: Manages tool registration, lookup, and execution
12
+ - Conversion utilities for different tool formats (OpenAI, LangChain, MCP)
13
+
14
+ ### `adapters.py`
15
+ Contains adapters for converting tools between different formats:
16
+ - `convert_tool_to_mcp_tool`: Converts a tool to MCP format
17
+ - `convert_tool_to_langchain_tool`: Converts a tool to LangChain format
18
+
19
+ ### `func_metadata.py`
20
+ Provides function metadata and argument validation:
21
+ - `FuncMetadata` class: Handles function signature analysis and argument validation
22
+ - `ArgModelBase` class: Base model for function arguments
23
+ - Utilities for parsing and validating function signatures
24
+
25
+ ## Usage
26
+
27
+ ### Creating a Tool
28
+
29
+ ```python
30
+ from universal_mcp.tools import Tool
31
+
32
+ def my_tool(param1: str, param2: int) -> str:
33
+ """A simple tool that does something.
34
+
35
+ Args:
36
+ param1: Description of param1
37
+ param2: Description of param2
38
+
39
+ Returns:
40
+ Description of return value
41
+ """
42
+ return f"Result: {param1} {param2}"
43
+
44
+ tool = Tool.from_function(my_tool)
45
+ ```
46
+
47
+ ### Managing Tools
48
+
49
+ ```python
50
+ from universal_mcp.tools import ToolManager
51
+
52
+ manager = ToolManager()
53
+ manager.add_tool(my_tool)
54
+
55
+ # Get a tool by name
56
+ tool = manager.get_tool("my_tool")
57
+
58
+ # List all tools in a specific format
59
+ tools = manager.list_tools(format="openai") # or "langchain" or "mcp"
60
+ ```
61
+
62
+ ### Converting Tools
63
+
64
+ ```python
65
+ from universal_mcp.tools import convert_tool_to_langchain_tool
66
+
67
+ langchain_tool = convert_tool_to_langchain_tool(tool)
68
+ ```
69
+
70
+ ## Features
71
+
72
+ - Automatic docstring parsing for tool metadata
73
+ - Type validation using Pydantic
74
+ - Support for both sync and async tools
75
+ - JSON schema generation for tool parameters
76
+ - Error handling and analytics tracking
77
+ - Tag-based tool organization
78
+ - Multiple format support (OpenAI, LangChain, MCP)
79
+
80
+ ## Best Practices
81
+
82
+ 1. Always provide clear docstrings for your tools
83
+ 2. Use type hints for better validation
84
+ 3. Handle errors appropriately in your tool implementations
85
+ 4. Use tags to organize related tools
86
+ 5. Consider async implementations for I/O-bound operations
@@ -261,7 +261,7 @@ class ToolManager:
261
261
  available_tool_functions = app.list_tools()
262
262
  except TypeError as e:
263
263
  logger.error(
264
- f"Error calling list_tools for app '{app.name}'. Does its list_tools method accept arguments? It shouldn't. Error: {e}"
264
+ f"Error calling list_tools for app '{app.name}'. Error: {e}"
265
265
  )
266
266
  return
267
267
  except Exception as e:
@@ -0,0 +1,90 @@
1
+ from loguru import logger
2
+ import os
3
+ import httpx
4
+ from universal_mcp.config import AppConfig
5
+ from universal_mcp.utils.singleton import Singleton
6
+
7
+ class AgentrClient(metaclass=Singleton):
8
+ """Helper class for AgentR API operations.
9
+
10
+ This class provides utility methods for interacting with the AgentR API,
11
+ including authentication, authorization, and credential management.
12
+
13
+ Args:
14
+ api_key (str, optional): AgentR API key. If not provided, will look for AGENTR_API_KEY env var
15
+ base_url (str, optional): Base URL for AgentR API. Defaults to https://api.agentr.dev
16
+ """
17
+
18
+ def __init__(self, api_key: str = None, base_url: str = None):
19
+ self.api_key = api_key or os.getenv("AGENTR_API_KEY")
20
+ if not self.api_key:
21
+ logger.error(
22
+ "API key for AgentR is missing. Please visit https://agentr.dev to create an API key, then set it as AGENTR_API_KEY environment variable."
23
+ )
24
+ raise ValueError("AgentR API key required - get one at https://agentr.dev")
25
+ self.base_url = (base_url or os.getenv("AGENTR_BASE_URL", "https://api.agentr.dev")).rstrip("/")
26
+
27
+ def get_credentials(self, integration_name: str) -> dict:
28
+ """Get credentials for an integration from the AgentR API.
29
+
30
+ Args:
31
+ integration_name (str): Name of the integration to get credentials for
32
+
33
+ Returns:
34
+ dict: Credentials data from API response
35
+
36
+ Raises:
37
+ NotAuthorizedError: If credentials are not found (404 response)
38
+ HTTPError: For other API errors
39
+ """
40
+ response = httpx.get(
41
+ f"{self.base_url}/api/{integration_name}/credentials/",
42
+ headers={"accept": "application/json", "X-API-KEY": self.api_key},
43
+ )
44
+ if response.status_code == 404:
45
+ logger.warning(
46
+ f"No credentials found for {integration_name}. Requesting authorization..."
47
+ )
48
+ action = self.get_authorization_url(integration_name)
49
+ raise NotAuthorizedError(action)
50
+ response.raise_for_status()
51
+ return response.json()
52
+
53
+ def get_authorization_url(self, integration_name: str) -> str:
54
+ """Get authorization URL for an integration.
55
+
56
+ Args:
57
+ integration_name (str): Name of the integration to get authorization URL for
58
+
59
+ Returns:
60
+ str: Message containing authorization URL
61
+
62
+ Raises:
63
+ HTTPError: If API request fails
64
+ """
65
+ response = httpx.get(
66
+ f"{self.base_url}/api/{integration_name}/authorize/",
67
+ headers={"X-API-KEY": self.api_key},
68
+ )
69
+ response.raise_for_status()
70
+ url = response.json()
71
+ return f"Please ask the user to visit the following url to authorize the application: {url}. Render the url in proper markdown format with a clickable link."
72
+
73
+ def fetch_apps(self) -> list[dict]:
74
+ """Fetch available apps from AgentR API.
75
+
76
+ Returns:
77
+ List of application configurations
78
+
79
+ Raises:
80
+ httpx.HTTPError: If API request fails
81
+ """
82
+ response = httpx.get(
83
+ f"{self.base_url}/api/apps/",
84
+ headers={"X-API-KEY": self.api_key},
85
+ timeout=10,
86
+ )
87
+ response.raise_for_status()
88
+ data = response.json()
89
+ return [AppConfig.model_validate(app) for app in data]
90
+