universal-mcp 0.1.0__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 (31) hide show
  1. universal_mcp-0.1.0/.gitignore +17 -0
  2. universal_mcp-0.1.0/.python-version +1 -0
  3. universal_mcp-0.1.0/PKG-INFO +165 -0
  4. universal_mcp-0.1.0/README.md +148 -0
  5. universal_mcp-0.1.0/pyproject.toml +31 -0
  6. universal_mcp-0.1.0/src/universal_mcp/__init__.py +2 -0
  7. universal_mcp-0.1.0/src/universal_mcp/applications/__init__.py +31 -0
  8. universal_mcp-0.1.0/src/universal_mcp/applications/agentr.py +0 -0
  9. universal_mcp-0.1.0/src/universal_mcp/applications/application.py +101 -0
  10. universal_mcp-0.1.0/src/universal_mcp/applications/github/app.py +354 -0
  11. universal_mcp-0.1.0/src/universal_mcp/applications/google_calendar/app.py +487 -0
  12. universal_mcp-0.1.0/src/universal_mcp/applications/google_mail/app.py +565 -0
  13. universal_mcp-0.1.0/src/universal_mcp/applications/reddit/app.py +329 -0
  14. universal_mcp-0.1.0/src/universal_mcp/applications/resend/app.py +43 -0
  15. universal_mcp-0.1.0/src/universal_mcp/applications/tavily/app.py +57 -0
  16. universal_mcp-0.1.0/src/universal_mcp/applications/zenquotes/app.py +21 -0
  17. universal_mcp-0.1.0/src/universal_mcp/cli.py +111 -0
  18. universal_mcp-0.1.0/src/universal_mcp/config.py +15 -0
  19. universal_mcp-0.1.0/src/universal_mcp/exceptions.py +8 -0
  20. universal_mcp-0.1.0/src/universal_mcp/integrations/README.md +25 -0
  21. universal_mcp-0.1.0/src/universal_mcp/integrations/__init__.py +4 -0
  22. universal_mcp-0.1.0/src/universal_mcp/integrations/agentr.py +87 -0
  23. universal_mcp-0.1.0/src/universal_mcp/integrations/integration.py +141 -0
  24. universal_mcp-0.1.0/src/universal_mcp/py.typed +0 -0
  25. universal_mcp-0.1.0/src/universal_mcp/servers/__init__.py +3 -0
  26. universal_mcp-0.1.0/src/universal_mcp/servers/server.py +134 -0
  27. universal_mcp-0.1.0/src/universal_mcp/stores/__init__.py +3 -0
  28. universal_mcp-0.1.0/src/universal_mcp/stores/store.py +71 -0
  29. universal_mcp-0.1.0/src/universal_mcp/utils/bridge.py +0 -0
  30. universal_mcp-0.1.0/src/universal_mcp/utils/openapi.py +274 -0
  31. universal_mcp-0.1.0/uv.lock +510 -0
@@ -0,0 +1,17 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Environment variables
13
+ .env
14
+ .env.local
15
+
16
+
17
+ dump/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: universal-mcp
3
+ Version: 0.1.0
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
+ Author-email: Manoj Bajaj <manojbajaj95@gmail.com>
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: loguru>=0.7.3
8
+ Requires-Dist: mcp>=1.5.0
9
+ Requires-Dist: pydantic-settings>=2.8.1
10
+ Requires-Dist: pydantic>=2.11.1
11
+ Requires-Dist: pyyaml>=6.0.2
12
+ Requires-Dist: typer>=0.15.2
13
+ Provides-Extra: test
14
+ Requires-Dist: pytest-asyncio>=0.26.0; extra == 'test'
15
+ Requires-Dist: pytest>=8.3.5; extra == 'test'
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Universal MCP
19
+
20
+ 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.
21
+
22
+
23
+ ## 🌟 Features
24
+
25
+ - **MCP (Model Context Protocol) Integration**: Seamlessly works with MCP server architecture
26
+ - **Simplified API Integration**: Connect to services like GitHub, Google Calendar, Gmail, Reddit, Tavily, and more with minimal code
27
+ - **Managed Authentication**: Built-in support for API keys and OAuth-based authentication flows
28
+ - **Extensible Architecture**: Easily build and add new app integrations with minimal boilerplate
29
+ - **Credential Management**: Flexible storage options for API credentials with memory and environment-based implementations
30
+
31
+ ## 🔧 Installation
32
+
33
+ Install AgentR using pip:
34
+
35
+ ```bash
36
+ pip install universal-mcp
37
+ ```
38
+
39
+ ## 🚀 Quick Start
40
+
41
+ ### 1. Get an API Key
42
+ Before using AgentR with services that require authorization (like GitHub, Gmail, etc.), you'll need an AgentR API key:
43
+
44
+ Visit https://agentr.dev to create an account
45
+ Generate an API key from your dashboard
46
+ Set it as an environment variable or include it directly in your code:
47
+
48
+ ```bash
49
+ export AGENTR_API_KEY="your_api_key_here"
50
+ ```
51
+
52
+ ### 2. Create a basic server
53
+
54
+ ```bash
55
+ from agentr.server import TestServer
56
+
57
+ # Define your applications list
58
+ apps_list = [
59
+ {
60
+ "name": "tavily",
61
+ "integration": {
62
+ "name": "tavily_api_key",
63
+ "type": "api_key",
64
+ "store": {
65
+ "type": "environment",
66
+ }
67
+ },
68
+ },
69
+ {
70
+ "name": "zenquotes",
71
+ "integration": None
72
+ },
73
+ {
74
+ "name": "github",
75
+ "integration": {
76
+ "name": "github",
77
+ "type": "agentr",
78
+ }
79
+ }
80
+ ]
81
+
82
+ # Create a server with these applications
83
+ server = TestServer(name="My Agent Server", description="A server for my agent apps", apps_list=apps_list)
84
+
85
+ # Run the server
86
+ if __name__ == "__main__":
87
+ server.run()
88
+ ```
89
+
90
+ ## 🧩 Available Applications
91
+ AgentR comes with several pre-built applications:
92
+
93
+ | Application | Description | Authentication Type |
94
+ |-------------|-------------|---------------------|
95
+ | GitHub | Star repositories and more | OAuth (AgentR) |
96
+ | Google Calendar | Retrieve calendar events | OAuth (AgentR) |
97
+ | Gmail | Send emails | OAuth (AgentR) |
98
+ | Reddit | Access Reddit data | OAuth (AgentR) |
99
+ | Resend | Send emails via Resend API | API Key |
100
+ | Tavily | Web search capabilities | API Key |
101
+ | ZenQuotes | Get inspirational quotes | None |
102
+
103
+ > **Note**: More applications are coming soon! Stay tuned for updates to our application catalog.
104
+
105
+ ## 🔐 Integration Types
106
+ AgentR supports two primary integration types:
107
+
108
+ ### 1. API Key Integration
109
+ For services that authenticate via API keys:
110
+ ```python
111
+ {
112
+ "name": "service_name",
113
+ "integration": {
114
+ "name": "service_api_key",
115
+ "type": "api_key",
116
+ "store": {
117
+ "type": "environment", # or "memory"
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### 2. OAuth Integration (via AgentR)
124
+ For services requiring OAuth flow:
125
+ ```python
126
+ {
127
+ "name": "service_name",
128
+ "integration": {
129
+ "name": "service_name",
130
+ "type": "agentr"
131
+ }
132
+ }
133
+ ```
134
+ When using OAuth integrations, users will be directed to authenticate with the service provider through a secure flow managed by AgentR.
135
+
136
+ ## 🤖 CLI Usage
137
+ AgentR includes a command-line interface for common operations:
138
+
139
+ ```bash
140
+ # Get version information
141
+ agentr version
142
+
143
+ # Generate API client from OpenAPI schema
144
+ agentr generate --schema path/to/openapi.yaml
145
+
146
+ # Run the test server
147
+ agentr run
148
+
149
+ # Install AgentR for specific applications
150
+ agentr install claude
151
+ ```
152
+
153
+ ## 📋 Requirements
154
+
155
+ - Python 3.11+
156
+ - Dependencies (automatically installed):
157
+ - loguru >= 0.7.3
158
+ - mcp >= 1.5.0
159
+ - pyyaml >= 6.0.2
160
+ - typer >= 0.15.2
161
+
162
+
163
+ ## 📝 License
164
+
165
+ This project is licensed under the MIT License.
@@ -0,0 +1,148 @@
1
+ # Universal MCP
2
+
3
+ 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.
4
+
5
+
6
+ ## 🌟 Features
7
+
8
+ - **MCP (Model Context Protocol) Integration**: Seamlessly works with MCP server architecture
9
+ - **Simplified API Integration**: Connect to services like GitHub, Google Calendar, Gmail, Reddit, Tavily, and more with minimal code
10
+ - **Managed Authentication**: Built-in support for API keys and OAuth-based authentication flows
11
+ - **Extensible Architecture**: Easily build and add new app integrations with minimal boilerplate
12
+ - **Credential Management**: Flexible storage options for API credentials with memory and environment-based implementations
13
+
14
+ ## 🔧 Installation
15
+
16
+ Install AgentR using pip:
17
+
18
+ ```bash
19
+ pip install universal-mcp
20
+ ```
21
+
22
+ ## 🚀 Quick Start
23
+
24
+ ### 1. Get an API Key
25
+ Before using AgentR with services that require authorization (like GitHub, Gmail, etc.), you'll need an AgentR API key:
26
+
27
+ Visit https://agentr.dev to create an account
28
+ Generate an API key from your dashboard
29
+ Set it as an environment variable or include it directly in your code:
30
+
31
+ ```bash
32
+ export AGENTR_API_KEY="your_api_key_here"
33
+ ```
34
+
35
+ ### 2. Create a basic server
36
+
37
+ ```bash
38
+ from agentr.server import TestServer
39
+
40
+ # Define your applications list
41
+ apps_list = [
42
+ {
43
+ "name": "tavily",
44
+ "integration": {
45
+ "name": "tavily_api_key",
46
+ "type": "api_key",
47
+ "store": {
48
+ "type": "environment",
49
+ }
50
+ },
51
+ },
52
+ {
53
+ "name": "zenquotes",
54
+ "integration": None
55
+ },
56
+ {
57
+ "name": "github",
58
+ "integration": {
59
+ "name": "github",
60
+ "type": "agentr",
61
+ }
62
+ }
63
+ ]
64
+
65
+ # Create a server with these applications
66
+ server = TestServer(name="My Agent Server", description="A server for my agent apps", apps_list=apps_list)
67
+
68
+ # Run the server
69
+ if __name__ == "__main__":
70
+ server.run()
71
+ ```
72
+
73
+ ## 🧩 Available Applications
74
+ AgentR comes with several pre-built applications:
75
+
76
+ | Application | Description | Authentication Type |
77
+ |-------------|-------------|---------------------|
78
+ | GitHub | Star repositories and more | OAuth (AgentR) |
79
+ | Google Calendar | Retrieve calendar events | OAuth (AgentR) |
80
+ | Gmail | Send emails | OAuth (AgentR) |
81
+ | Reddit | Access Reddit data | OAuth (AgentR) |
82
+ | Resend | Send emails via Resend API | API Key |
83
+ | Tavily | Web search capabilities | API Key |
84
+ | ZenQuotes | Get inspirational quotes | None |
85
+
86
+ > **Note**: More applications are coming soon! Stay tuned for updates to our application catalog.
87
+
88
+ ## 🔐 Integration Types
89
+ AgentR supports two primary integration types:
90
+
91
+ ### 1. API Key Integration
92
+ For services that authenticate via API keys:
93
+ ```python
94
+ {
95
+ "name": "service_name",
96
+ "integration": {
97
+ "name": "service_api_key",
98
+ "type": "api_key",
99
+ "store": {
100
+ "type": "environment", # or "memory"
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### 2. OAuth Integration (via AgentR)
107
+ For services requiring OAuth flow:
108
+ ```python
109
+ {
110
+ "name": "service_name",
111
+ "integration": {
112
+ "name": "service_name",
113
+ "type": "agentr"
114
+ }
115
+ }
116
+ ```
117
+ When using OAuth integrations, users will be directed to authenticate with the service provider through a secure flow managed by AgentR.
118
+
119
+ ## 🤖 CLI Usage
120
+ AgentR includes a command-line interface for common operations:
121
+
122
+ ```bash
123
+ # Get version information
124
+ agentr version
125
+
126
+ # Generate API client from OpenAPI schema
127
+ agentr generate --schema path/to/openapi.yaml
128
+
129
+ # Run the test server
130
+ agentr run
131
+
132
+ # Install AgentR for specific applications
133
+ agentr install claude
134
+ ```
135
+
136
+ ## 📋 Requirements
137
+
138
+ - Python 3.11+
139
+ - Dependencies (automatically installed):
140
+ - loguru >= 0.7.3
141
+ - mcp >= 1.5.0
142
+ - pyyaml >= 6.0.2
143
+ - typer >= 0.15.2
144
+
145
+
146
+ ## 📝 License
147
+
148
+ This project is licensed under the MIT License.
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "universal-mcp"
3
+ version = "0.1.0"
4
+ 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."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Manoj Bajaj", email = "manojbajaj95@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.11"
10
+ dependencies = [
11
+ "pydantic>=2.11.1",
12
+ "pydantic-settings>=2.8.1",
13
+ "loguru>=0.7.3",
14
+ "mcp>=1.5.0",
15
+ "pyyaml>=6.0.2",
16
+ "typer>=0.15.2",
17
+ ]
18
+
19
+ [project.optional-dependencies]
20
+ test = [
21
+ "pytest>=8.3.5",
22
+ "pytest-asyncio>=0.26.0",
23
+ ]
24
+
25
+ [project.scripts]
26
+ universal_mcp = "universal_mcp.cli:app"
27
+
28
+ [build-system]
29
+ requires = ["hatchling"]
30
+ build-backend = "hatchling.build"
31
+
@@ -0,0 +1,2 @@
1
+ def hello() -> str:
2
+ return "Hello from universal-mcp!"
@@ -0,0 +1,31 @@
1
+ from universal_mcp.applications.zenquotes.app import ZenQuoteApp
2
+ from universal_mcp.applications.tavily.app import TavilyApp
3
+ from universal_mcp.applications.github.app import GithubApp
4
+ from universal_mcp.applications.google_calendar.app import GoogleCalendarApp
5
+ from universal_mcp.applications.google_mail.app import GmailApp
6
+ from universal_mcp.applications.resend.app import ResendApp
7
+ from universal_mcp.applications.reddit.app import RedditApp
8
+ from universal_mcp.applications.application import Application, APIApplication
9
+
10
+ def app_from_name(name: str):
11
+ name = name.lower().strip()
12
+ name = name.replace(" ", "-")
13
+ if name == "zenquotes":
14
+ return ZenQuoteApp
15
+ elif name == "tavily":
16
+ return TavilyApp
17
+ elif name == "github":
18
+ return GithubApp
19
+ elif name == "google-calendar":
20
+ return GoogleCalendarApp
21
+ elif name == "google-mail":
22
+ return GmailApp
23
+ elif name == "resend":
24
+ return ResendApp
25
+ elif name == "reddit":
26
+ return RedditApp
27
+ else:
28
+ raise ValueError(f"App {name} not found")
29
+
30
+
31
+ __all__ = ["app_from_name", "Application", "APIApplication"]
@@ -0,0 +1,101 @@
1
+ from abc import ABC
2
+ from loguru import logger
3
+ from universal_mcp.exceptions import NotAuthorizedError
4
+ from universal_mcp.integrations import Integration
5
+ import httpx
6
+
7
+ class Application(ABC):
8
+ """
9
+ Application is collection of tools that can be used by an agent.
10
+ """
11
+ def __init__(self, name: str, **kwargs):
12
+ self.name = name
13
+ self.tools = []
14
+
15
+ def list_tools(self):
16
+ return self.tools
17
+
18
+ class APIApplication(Application):
19
+ """
20
+ APIApplication is an application that uses an API to interact with the world.
21
+ """
22
+ def __init__(self, name: str, integration: Integration = None, **kwargs):
23
+ super().__init__(name, **kwargs)
24
+ self.integration = integration
25
+
26
+ def _get_headers(self):
27
+ return {}
28
+
29
+ def _get(self, url, params=None):
30
+ try:
31
+ headers = self._get_headers()
32
+ response = httpx.get(url, headers=headers, params=params)
33
+ response.raise_for_status()
34
+ return response
35
+ except NotAuthorizedError as e:
36
+ logger.warning(f"Authorization needed: {e.message}")
37
+ raise e
38
+ except Exception as e:
39
+ logger.error(f"Error getting {url}: {e}")
40
+ raise e
41
+
42
+
43
+ def _post(self, url, data, params=None):
44
+ try:
45
+ headers = self._get_headers()
46
+ response = httpx.post(url, headers=headers, json=data, params=params)
47
+ response.raise_for_status()
48
+ return response
49
+ except NotAuthorizedError as e:
50
+ logger.warning(f"Authorization needed: {e.message}")
51
+ raise e
52
+ except httpx.HTTPStatusError as e:
53
+ if e.response.status_code == 429:
54
+ return e.response.text or "Rate limit exceeded. Please try again later."
55
+ else:
56
+ raise e
57
+ except Exception as e:
58
+ logger.error(f"Error posting {url}: {e}")
59
+ raise e
60
+
61
+ def _put(self, url, data, params=None):
62
+ try:
63
+ headers = self._get_headers()
64
+ response = httpx.put(url, headers=headers, json=data, params=params)
65
+ response.raise_for_status()
66
+ return response
67
+ except NotAuthorizedError as e:
68
+ logger.warning(f"Authorization needed: {e.message}")
69
+ raise e
70
+ except Exception as e:
71
+ logger.error(f"Error posting {url}: {e}")
72
+ raise e
73
+
74
+ def _delete(self, url, params=None):
75
+ try:
76
+ headers = self._get_headers()
77
+ response = httpx.delete(url, headers=headers, params=params)
78
+ response.raise_for_status()
79
+ return response
80
+ except NotAuthorizedError as e:
81
+ logger.warning(f"Authorization needed: {e.message}")
82
+ raise e
83
+ except Exception as e:
84
+ logger.error(f"Error posting {url}: {e}")
85
+ raise e
86
+
87
+ def _patch(self, url, data, params=None):
88
+ try:
89
+ headers = self._get_headers()
90
+ response = httpx.patch(url, headers=headers, json=data, params=params)
91
+ response.raise_for_status()
92
+ return response
93
+ except NotAuthorizedError as e:
94
+ logger.warning(f"Authorization needed: {e.message}")
95
+ raise e
96
+ except Exception as e:
97
+ logger.error(f"Error patching {url}: {e}")
98
+ raise e
99
+
100
+ def validate(self):
101
+ pass