universal-mcp 0.1.15rc7__tar.gz → 0.1.17__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 (56) hide show
  1. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/.gitignore +2 -1
  2. universal_mcp-0.1.17/PKG-INFO +282 -0
  3. universal_mcp-0.1.17/README.md +242 -0
  4. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/pyproject.toml +2 -2
  5. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_api_generator.py +4 -12
  6. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_applications.py +2 -2
  7. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_zenquotes.py +1 -3
  8. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/applications/__init__.py +25 -27
  9. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/applications/application.py +19 -55
  10. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/cli.py +10 -29
  11. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/config.py +16 -48
  12. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/integrations/__init__.py +1 -3
  13. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/logger.py +31 -29
  14. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/servers/server.py +6 -18
  15. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/func_metadata.py +5 -19
  16. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/manager.py +5 -15
  17. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/tools.py +4 -11
  18. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/agentr.py +2 -6
  19. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/common.py +1 -1
  20. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/docstring_parser.py +4 -13
  21. universal_mcp-0.1.17/src/universal_mcp/utils/installation.py +193 -0
  22. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/api_generator.py +1 -3
  23. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/docgen.py +17 -54
  24. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/openapi.py +62 -110
  25. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/preprocessor.py +60 -190
  26. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/readme.py +3 -9
  27. universal_mcp-0.1.15rc7/PKG-INFO +0 -247
  28. universal_mcp-0.1.15rc7/README.md +0 -207
  29. universal_mcp-0.1.15rc7/src/universal_mcp/utils/installation.py +0 -310
  30. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/LICENSE +0 -0
  31. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/__init__.py +0 -0
  32. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/conftest.py +0 -0
  33. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_api_integration.py +0 -0
  34. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_localserver.py +0 -0
  35. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_stores.py +0 -0
  36. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/tests/test_tool.py +0 -0
  37. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/__init__.py +0 -0
  38. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/analytics.py +0 -0
  39. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/applications/README.md +0 -0
  40. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/exceptions.py +0 -0
  41. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/integrations/README.md +0 -0
  42. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/integrations/integration.py +0 -0
  43. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/py.typed +0 -0
  44. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/servers/README.md +0 -0
  45. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/servers/__init__.py +0 -0
  46. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/stores/README.md +0 -0
  47. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/stores/__init__.py +0 -0
  48. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/stores/store.py +0 -0
  49. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/README.md +0 -0
  50. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/__init__.py +0 -0
  51. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/tools/adapters.py +0 -0
  52. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/__init__.py +0 -0
  53. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/openapi/__inti__.py +0 -0
  54. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/singleton.py +0 -0
  55. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/templates/README.md.j2 +0 -0
  56. {universal_mcp-0.1.15rc7 → universal_mcp-0.1.17}/src/universal_mcp/utils/templates/api_client.py.j2 +0 -0
@@ -47,4 +47,5 @@ src/universal_mcp/applications/test_with_docs/
47
47
  src/universal_mcp/applications/test_without_docs/
48
48
 
49
49
  # Temporary files
50
- tmp/
50
+ tmp/
51
+ examples
@@ -0,0 +1,282 @@
1
+ Metadata-Version: 2.4
2
+ Name: universal-mcp
3
+ Version: 0.1.17
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
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: cookiecutter>=2.6.0
10
+ Requires-Dist: gql[all]>=3.5.2
11
+ Requires-Dist: jinja2>=3.1.3
12
+ Requires-Dist: jsonref>=1.1.0
13
+ Requires-Dist: keyring>=25.6.0
14
+ Requires-Dist: langchain-mcp-adapters>=0.0.3
15
+ Requires-Dist: litellm>=1.30.7
16
+ Requires-Dist: loguru>=0.7.3
17
+ Requires-Dist: mcp>=1.7.1
18
+ Requires-Dist: posthog>=3.24.0
19
+ Requires-Dist: pydantic-settings>=2.8.1
20
+ Requires-Dist: pydantic>=2.11.1
21
+ Requires-Dist: pyyaml>=6.0.2
22
+ Requires-Dist: rich>=14.0.0
23
+ Requires-Dist: typer>=0.15.2
24
+ Provides-Extra: dev
25
+ Requires-Dist: litellm>=1.30.7; extra == 'dev'
26
+ Requires-Dist: pre-commit>=4.2.0; extra == 'dev'
27
+ Requires-Dist: pyright>=1.1.398; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.26.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8.3.5; extra == 'dev'
30
+ Requires-Dist: ruff>=0.11.4; extra == 'dev'
31
+ Provides-Extra: playground
32
+ Requires-Dist: langchain-openai>=0.3.12; extra == 'playground'
33
+ Requires-Dist: langgraph-checkpoint-sqlite>=2.0.6; extra == 'playground'
34
+ Requires-Dist: langgraph>=0.3.24; extra == 'playground'
35
+ Requires-Dist: litellm>=1.30.7; extra == 'playground'
36
+ Requires-Dist: python-dotenv>=1.0.1; extra == 'playground'
37
+ Requires-Dist: streamlit>=1.44.1; extra == 'playground'
38
+ Requires-Dist: watchdog>=6.0.0; extra == 'playground'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # Universal MCP
42
+
43
+ Universal MCP acts as a middleware layer for your API applications, enabling seamless integration with various services through the Model Control Protocol (MCP). It simplifies credential management, authorization, dynamic app enablement, and provides a robust framework for building and managing AI-powered tools.
44
+
45
+ ## 🌟 Features
46
+
47
+ - **MCP (Model Control Protocol) Integration**: Seamlessly works with MCP server architecture for standardized agent-tool communication.
48
+ - **Simplified API Integration**: Connect to services like GitHub, Google Calendar, Gmail, Reddit, Tavily, and more with minimal code. See [AgentR](https://agentr.dev) for a list of available applications.
49
+ - **Managed Authentication**: Built-in support for API keys and OAuth-based authentication flows, often managed via the AgentR platform.
50
+ - **Extensible Architecture**: Easily build and add new app integrations with minimal boilerplate using provided base classes and generation tools.
51
+ - **Credential Management**: Flexible and secure storage options for API credentials (memory, environment variables, system keyring).
52
+ - **Comprehensive Tool Management**: Robust tool registration, Pydantic-based validation, automatic docstring parsing, and execution capabilities. Supports conversion between MCP, LangChain, and OpenAI tool formats.
53
+ - **Multiple Server Types**: Configurations for local development, AgentR-connected dynamic app loading, and single-application servers.
54
+ - **Playground Environment**: Includes an interactive Streamlit-based playground for testing agents and tools.
55
+
56
+ ## 🔧 Installation
57
+
58
+ Install Universal MCP using pip:
59
+
60
+ ```bash
61
+ pip install universal-mcp
62
+ ```
63
+
64
+ ## 🚀 Quick Start
65
+
66
+ **Important Prerequisite: AgentR API Key (If Using AgentR Integration)**
67
+
68
+ If you plan to use integrations with `type: "agentr"` (for services like GitHub, Gmail, Notion via the AgentR platform), or if you run the MCP server itself with `type: "agentr"`, you first need an AgentR API key:
69
+
70
+ 1. Visit [https://agentr.dev](https://agentr.dev) to create an account and generate an API key from your dashboard.
71
+ 2. Set it as an environment variable _before_ running the MCP server:
72
+ ```bash
73
+ export AGENTR_API_KEY="your_api_key_here"
74
+ ```
75
+
76
+ **1. Create a Configuration File (e.g., `config.json`)**
77
+
78
+ This file defines the server settings, credential stores, and the applications to load with their respective integrations.
79
+
80
+ ```json
81
+ {
82
+ "name": "My Local MCP Server",
83
+ "description": "A server for testing applications locally",
84
+ "type": "local", // "local" or "agentr"
85
+ "transport": "sse", // "sse", "stdio", or "http"
86
+ "port": 8005, // Relevant for "sse" or "http"
87
+ "store": {
88
+ // Default store for integrations
89
+ "name": "my_mcp_store",
90
+ "type": "keyring" // "keyring", "environment", or "memory"
91
+ },
92
+ "apps": [
93
+ {
94
+ "name": "zenquotes", // App slug (e.g., from agentr.dev)
95
+ "integration": null // No authentication needed for this app
96
+ },
97
+ {
98
+ "name": "tavily",
99
+ "integration": {
100
+ "name": "TAVILY_API_KEY", // Unique name for this credential if type is "api_key"
101
+ "type": "api_key",
102
+ "store": {
103
+ // Override default store for this specific app
104
+ "type": "environment" // Looks for TAVILY_API_KEY env var
105
+ }
106
+ }
107
+ },
108
+ {
109
+ "name": "github",
110
+ "integration": {
111
+ "name": "github", // Matches the service name in AgentR
112
+ "type": "agentr" // Uses AgentR platform for auth/creds
113
+ }
114
+ }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ _Notes on `config.json`:_
120
+
121
+ - `type: "local"`: Runs applications defined directly in the config's `apps` list.
122
+ - `type: "agentr"`: Connects to the AgentR platform to dynamically load user-enabled apps (ignores the `apps` list in the config) and handle credentials. Requires `AGENTR_API_KEY` environment variable.
123
+ - `store`: Defines credential storage.
124
+ - `environment`: Looks for an environment variable named `<INTEGRATION_NAME_UPPERCASE>` (e.g., `TAVILY_API_KEY` for the example above).
125
+ - `keyring`: Uses the system's secure credential storage.
126
+ - `memory`: Transient storage, lost when the server stops.
127
+ - `integration`: Configures authentication for each app.
128
+ - `type: "agentr"`: Uses the AgentR platform for OAuth/credential management.
129
+ - `type: "api_key"`: Uses the specified `store` to retrieve the key.
130
+
131
+ **2. Run the Server via CLI**
132
+
133
+ Ensure any required environment variables (like `TAVILY_API_KEY` for the Tavily example, or `AGENTR_API_KEY` if using `"agentr"` type server/integrations) are set.
134
+
135
+ ```bash
136
+ universal_mcp run -c config.json
137
+ ```
138
+
139
+ The server will start, load the configured applications (or connect to AgentR if `type: "agentr"`), and listen for connections based on the `transport` type.
140
+
141
+ ## 🛠️ Using the Playground
142
+
143
+ The `playground` directory provides a runnable Streamlit application for interacting with agents that can use tools from an MCP server.
144
+
145
+ **Prerequisites:**
146
+
147
+ - **`local_config.json`**: This file must exist in the **project root directory** (the same directory as this `README.md`). It configures the _local_ MCP server that the playground's agent can connect to if you choose to run one. For an example, see the `local_config.json` structure in the [Playground README](playground/README.md).
148
+ - **Dependencies**: Install playground-specific dependencies. If you have the project cloned, you might install them via:
149
+ ```bash
150
+ pip install -e .[playground]
151
+ # or manually install fastapi, streamlit, uvicorn, langchain-openai, etc.
152
+ ```
153
+
154
+ **Running the Playground:**
155
+
156
+ The easiest way is to use the automated startup script from the **project root directory**:
157
+
158
+ ```bash
159
+ python playground
160
+ ```
161
+
162
+ This script will:
163
+
164
+ 1. Optionally start a local MCP server (based on your `local_config.json`) if you confirm.
165
+ 2. Launch the Streamlit application.
166
+
167
+ For more detailed setup, manual startup instructions, and an explanation of the `local_config.json` for the playground, please refer to the [Playground README](playground/README.md).
168
+
169
+ ## 🧩 Available Applications
170
+
171
+ Universal MCP can integrate with a wide variety of applications. For a list of publicly available applications and their slugs (e.g., "github", "google-calendar"), please visit [AgentR Applications](https://agentr.dev).
172
+ Applications are typically installed dynamically by Universal MCP from their respective repositories when first referenced by slug.
173
+
174
+ _Authentication Type Notes:_
175
+
176
+ - _OAuth (via AgentR)_: Usually requires configuring the app's integration with `type: "agentr"` in your `ServerConfig`. This leverages the AgentR platform for the OAuth flow and requires the `AGENTR_API_KEY` to be set.
177
+ - _API Key (via Integration)_: Requires configuring `type: "api_key"` for the app's integration in your `ServerConfig`, along with a `store` (like `environment` or `keyring`) to specify where the API key is located.
178
+
179
+ ## 🔐 Integration Types
180
+
181
+ Universal MCP supports different ways to handle authentication for applications:
182
+
183
+ ### 1. API Key Integration (`type: "api_key"`)
184
+
185
+ For services that authenticate via simple API keys.
186
+
187
+ ```json
188
+ // In your ServerConfig apps array:
189
+ {
190
+ "name": "tavily",
191
+ "integration": {
192
+ "name": "TAVILY_API_KEY", // Used by the store (e.g., as env var name)
193
+ "type": "api_key",
194
+ "store": {
195
+ "type": "environment" // Or "keyring", "memory"
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### 2. AgentR Integration (`type: "agentr"`)
202
+
203
+ Recommended for services integrated with the AgentR platform, which typically handles OAuth flows or centrally managed credentials. Requires the `AGENTR_API_KEY` environment variable to be set for the MCP server process.
204
+
205
+ ```json
206
+ // In your ServerConfig apps array:
207
+ {
208
+ "name": "github",
209
+ "integration": {
210
+ "name": "github", // Matches the service name configured in AgentR
211
+ "type": "agentr"
212
+ }
213
+ }
214
+ ```
215
+
216
+ When an action requiring authorization is called, the `AgentRIntegration` will prompt the user (via the MCP client) to visit a URL to complete the OAuth flow managed by AgentR. This is also the default integration type for apps if the main server config is `type: "agentr"`.
217
+
218
+ ### 3. Direct OAuth Integration (`type: "oauth"`)
219
+
220
+ While `AgentRIntegration` is generally preferred for OAuth, a direct `OAuthIntegration` class exists. However, it requires manual configuration of client IDs, secrets, and callback handling, which is more complex to set up outside the AgentR platform.
221
+
222
+ ## 🤖 CLI Usage
223
+
224
+ Universal MCP includes a powerful command-line interface:
225
+
226
+ ```bash
227
+ # Run the MCP server using a configuration file
228
+ universal_mcp run -c config.json
229
+
230
+ # Initialize a new MCP application project structure
231
+ universal_mcp init --app-name my-cool-app --o ./my-apps --integration-type api_key
232
+
233
+ # Generate API client code and application structure from an OpenAPI schema
234
+ universal_mcp generate -s <path_to_schema.json_or_yaml> -o <path/to/app_output_directory> --c CustomAppClassName
235
+ # Example: universal_mcp generate -s notion_api.yaml -o ./custom_apps/notion --c MyNotionApp
236
+
237
+ # Preprocess an OpenAPI schema using an LLM to fill/enhance descriptions
238
+ universal_mcp preprocess -s <path_to_input_schema.json_or_yaml> -o <path_to_processed_schema.json_or_yaml>
239
+
240
+ # Generate Google-style docstrings for functions in a Python file using an LLM
241
+ universal_mcp docgen <path/to/app_file.py>
242
+
243
+ # Generate a README.md for a generated application file
244
+ universal_mcp readme <path/to/app_file.py>
245
+
246
+ # Install MCP configuration for supported desktop apps (e.g., Claude, Cursor)
247
+ # Requires an AgentR API key for configuration.
248
+ universal_mcp install claude
249
+ universal_mcp install cursor
250
+
251
+ # Check installed version (standard typer command)
252
+ universal_mcp --version
253
+ ```
254
+
255
+ ## 📋 Requirements
256
+
257
+ - Python 3.10+
258
+ - Key Dependencies (installed automatically via pip, see `pyproject.toml` for full list):
259
+ - `mcp-server`
260
+ - `loguru`
261
+ - `typer`
262
+ - `httpx`
263
+ - `pydantic`
264
+ - `pyyaml`
265
+ - `keyring` (for `KeyringStore`)
266
+ - `litellm` (for `docgen` and `preprocess` commands)
267
+ - `uv` (used internally for dynamic package installation)
268
+
269
+ ## 📚 Documentation
270
+
271
+ For more detailed information about specific components:
272
+
273
+ - [Applications Framework](src/universal_mcp/applications/README.md)
274
+ - [Tool Management](src/universal_mcp/tools/README.md)
275
+ - [Server Implementations](src/universal_mcp/servers/README.md)
276
+ - [Credential Stores](src/universal_mcp/stores/README.md)
277
+ - [Integration & Authentication](src/universal_mcp/integrations/README.md)
278
+ - [Playground Usage](playground/README.md)
279
+
280
+ ## 📝 License
281
+
282
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,242 @@
1
+ # Universal MCP
2
+
3
+ Universal MCP acts as a middleware layer for your API applications, enabling seamless integration with various services through the Model Control Protocol (MCP). It simplifies credential management, authorization, dynamic app enablement, and provides a robust framework for building and managing AI-powered tools.
4
+
5
+ ## 🌟 Features
6
+
7
+ - **MCP (Model Control Protocol) Integration**: Seamlessly works with MCP server architecture for standardized agent-tool communication.
8
+ - **Simplified API Integration**: Connect to services like GitHub, Google Calendar, Gmail, Reddit, Tavily, and more with minimal code. See [AgentR](https://agentr.dev) for a list of available applications.
9
+ - **Managed Authentication**: Built-in support for API keys and OAuth-based authentication flows, often managed via the AgentR platform.
10
+ - **Extensible Architecture**: Easily build and add new app integrations with minimal boilerplate using provided base classes and generation tools.
11
+ - **Credential Management**: Flexible and secure storage options for API credentials (memory, environment variables, system keyring).
12
+ - **Comprehensive Tool Management**: Robust tool registration, Pydantic-based validation, automatic docstring parsing, and execution capabilities. Supports conversion between MCP, LangChain, and OpenAI tool formats.
13
+ - **Multiple Server Types**: Configurations for local development, AgentR-connected dynamic app loading, and single-application servers.
14
+ - **Playground Environment**: Includes an interactive Streamlit-based playground for testing agents and tools.
15
+
16
+ ## 🔧 Installation
17
+
18
+ Install Universal MCP using pip:
19
+
20
+ ```bash
21
+ pip install universal-mcp
22
+ ```
23
+
24
+ ## 🚀 Quick Start
25
+
26
+ **Important Prerequisite: AgentR API Key (If Using AgentR Integration)**
27
+
28
+ If you plan to use integrations with `type: "agentr"` (for services like GitHub, Gmail, Notion via the AgentR platform), or if you run the MCP server itself with `type: "agentr"`, you first need an AgentR API key:
29
+
30
+ 1. Visit [https://agentr.dev](https://agentr.dev) to create an account and generate an API key from your dashboard.
31
+ 2. Set it as an environment variable _before_ running the MCP server:
32
+ ```bash
33
+ export AGENTR_API_KEY="your_api_key_here"
34
+ ```
35
+
36
+ **1. Create a Configuration File (e.g., `config.json`)**
37
+
38
+ This file defines the server settings, credential stores, and the applications to load with their respective integrations.
39
+
40
+ ```json
41
+ {
42
+ "name": "My Local MCP Server",
43
+ "description": "A server for testing applications locally",
44
+ "type": "local", // "local" or "agentr"
45
+ "transport": "sse", // "sse", "stdio", or "http"
46
+ "port": 8005, // Relevant for "sse" or "http"
47
+ "store": {
48
+ // Default store for integrations
49
+ "name": "my_mcp_store",
50
+ "type": "keyring" // "keyring", "environment", or "memory"
51
+ },
52
+ "apps": [
53
+ {
54
+ "name": "zenquotes", // App slug (e.g., from agentr.dev)
55
+ "integration": null // No authentication needed for this app
56
+ },
57
+ {
58
+ "name": "tavily",
59
+ "integration": {
60
+ "name": "TAVILY_API_KEY", // Unique name for this credential if type is "api_key"
61
+ "type": "api_key",
62
+ "store": {
63
+ // Override default store for this specific app
64
+ "type": "environment" // Looks for TAVILY_API_KEY env var
65
+ }
66
+ }
67
+ },
68
+ {
69
+ "name": "github",
70
+ "integration": {
71
+ "name": "github", // Matches the service name in AgentR
72
+ "type": "agentr" // Uses AgentR platform for auth/creds
73
+ }
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ _Notes on `config.json`:_
80
+
81
+ - `type: "local"`: Runs applications defined directly in the config's `apps` list.
82
+ - `type: "agentr"`: Connects to the AgentR platform to dynamically load user-enabled apps (ignores the `apps` list in the config) and handle credentials. Requires `AGENTR_API_KEY` environment variable.
83
+ - `store`: Defines credential storage.
84
+ - `environment`: Looks for an environment variable named `<INTEGRATION_NAME_UPPERCASE>` (e.g., `TAVILY_API_KEY` for the example above).
85
+ - `keyring`: Uses the system's secure credential storage.
86
+ - `memory`: Transient storage, lost when the server stops.
87
+ - `integration`: Configures authentication for each app.
88
+ - `type: "agentr"`: Uses the AgentR platform for OAuth/credential management.
89
+ - `type: "api_key"`: Uses the specified `store` to retrieve the key.
90
+
91
+ **2. Run the Server via CLI**
92
+
93
+ Ensure any required environment variables (like `TAVILY_API_KEY` for the Tavily example, or `AGENTR_API_KEY` if using `"agentr"` type server/integrations) are set.
94
+
95
+ ```bash
96
+ universal_mcp run -c config.json
97
+ ```
98
+
99
+ The server will start, load the configured applications (or connect to AgentR if `type: "agentr"`), and listen for connections based on the `transport` type.
100
+
101
+ ## 🛠️ Using the Playground
102
+
103
+ The `playground` directory provides a runnable Streamlit application for interacting with agents that can use tools from an MCP server.
104
+
105
+ **Prerequisites:**
106
+
107
+ - **`local_config.json`**: This file must exist in the **project root directory** (the same directory as this `README.md`). It configures the _local_ MCP server that the playground's agent can connect to if you choose to run one. For an example, see the `local_config.json` structure in the [Playground README](playground/README.md).
108
+ - **Dependencies**: Install playground-specific dependencies. If you have the project cloned, you might install them via:
109
+ ```bash
110
+ pip install -e .[playground]
111
+ # or manually install fastapi, streamlit, uvicorn, langchain-openai, etc.
112
+ ```
113
+
114
+ **Running the Playground:**
115
+
116
+ The easiest way is to use the automated startup script from the **project root directory**:
117
+
118
+ ```bash
119
+ python playground
120
+ ```
121
+
122
+ This script will:
123
+
124
+ 1. Optionally start a local MCP server (based on your `local_config.json`) if you confirm.
125
+ 2. Launch the Streamlit application.
126
+
127
+ For more detailed setup, manual startup instructions, and an explanation of the `local_config.json` for the playground, please refer to the [Playground README](playground/README.md).
128
+
129
+ ## 🧩 Available Applications
130
+
131
+ Universal MCP can integrate with a wide variety of applications. For a list of publicly available applications and their slugs (e.g., "github", "google-calendar"), please visit [AgentR Applications](https://agentr.dev).
132
+ Applications are typically installed dynamically by Universal MCP from their respective repositories when first referenced by slug.
133
+
134
+ _Authentication Type Notes:_
135
+
136
+ - _OAuth (via AgentR)_: Usually requires configuring the app's integration with `type: "agentr"` in your `ServerConfig`. This leverages the AgentR platform for the OAuth flow and requires the `AGENTR_API_KEY` to be set.
137
+ - _API Key (via Integration)_: Requires configuring `type: "api_key"` for the app's integration in your `ServerConfig`, along with a `store` (like `environment` or `keyring`) to specify where the API key is located.
138
+
139
+ ## 🔐 Integration Types
140
+
141
+ Universal MCP supports different ways to handle authentication for applications:
142
+
143
+ ### 1. API Key Integration (`type: "api_key"`)
144
+
145
+ For services that authenticate via simple API keys.
146
+
147
+ ```json
148
+ // In your ServerConfig apps array:
149
+ {
150
+ "name": "tavily",
151
+ "integration": {
152
+ "name": "TAVILY_API_KEY", // Used by the store (e.g., as env var name)
153
+ "type": "api_key",
154
+ "store": {
155
+ "type": "environment" // Or "keyring", "memory"
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ ### 2. AgentR Integration (`type: "agentr"`)
162
+
163
+ Recommended for services integrated with the AgentR platform, which typically handles OAuth flows or centrally managed credentials. Requires the `AGENTR_API_KEY` environment variable to be set for the MCP server process.
164
+
165
+ ```json
166
+ // In your ServerConfig apps array:
167
+ {
168
+ "name": "github",
169
+ "integration": {
170
+ "name": "github", // Matches the service name configured in AgentR
171
+ "type": "agentr"
172
+ }
173
+ }
174
+ ```
175
+
176
+ When an action requiring authorization is called, the `AgentRIntegration` will prompt the user (via the MCP client) to visit a URL to complete the OAuth flow managed by AgentR. This is also the default integration type for apps if the main server config is `type: "agentr"`.
177
+
178
+ ### 3. Direct OAuth Integration (`type: "oauth"`)
179
+
180
+ While `AgentRIntegration` is generally preferred for OAuth, a direct `OAuthIntegration` class exists. However, it requires manual configuration of client IDs, secrets, and callback handling, which is more complex to set up outside the AgentR platform.
181
+
182
+ ## 🤖 CLI Usage
183
+
184
+ Universal MCP includes a powerful command-line interface:
185
+
186
+ ```bash
187
+ # Run the MCP server using a configuration file
188
+ universal_mcp run -c config.json
189
+
190
+ # Initialize a new MCP application project structure
191
+ universal_mcp init --app-name my-cool-app --o ./my-apps --integration-type api_key
192
+
193
+ # Generate API client code and application structure from an OpenAPI schema
194
+ universal_mcp generate -s <path_to_schema.json_or_yaml> -o <path/to/app_output_directory> --c CustomAppClassName
195
+ # Example: universal_mcp generate -s notion_api.yaml -o ./custom_apps/notion --c MyNotionApp
196
+
197
+ # Preprocess an OpenAPI schema using an LLM to fill/enhance descriptions
198
+ universal_mcp preprocess -s <path_to_input_schema.json_or_yaml> -o <path_to_processed_schema.json_or_yaml>
199
+
200
+ # Generate Google-style docstrings for functions in a Python file using an LLM
201
+ universal_mcp docgen <path/to/app_file.py>
202
+
203
+ # Generate a README.md for a generated application file
204
+ universal_mcp readme <path/to/app_file.py>
205
+
206
+ # Install MCP configuration for supported desktop apps (e.g., Claude, Cursor)
207
+ # Requires an AgentR API key for configuration.
208
+ universal_mcp install claude
209
+ universal_mcp install cursor
210
+
211
+ # Check installed version (standard typer command)
212
+ universal_mcp --version
213
+ ```
214
+
215
+ ## 📋 Requirements
216
+
217
+ - Python 3.10+
218
+ - Key Dependencies (installed automatically via pip, see `pyproject.toml` for full list):
219
+ - `mcp-server`
220
+ - `loguru`
221
+ - `typer`
222
+ - `httpx`
223
+ - `pydantic`
224
+ - `pyyaml`
225
+ - `keyring` (for `KeyringStore`)
226
+ - `litellm` (for `docgen` and `preprocess` commands)
227
+ - `uv` (used internally for dynamic package installation)
228
+
229
+ ## 📚 Documentation
230
+
231
+ For more detailed information about specific components:
232
+
233
+ - [Applications Framework](src/universal_mcp/applications/README.md)
234
+ - [Tool Management](src/universal_mcp/tools/README.md)
235
+ - [Server Implementations](src/universal_mcp/servers/README.md)
236
+ - [Credential Stores](src/universal_mcp/stores/README.md)
237
+ - [Integration & Authentication](src/universal_mcp/integrations/README.md)
238
+ - [Playground Usage](playground/README.md)
239
+
240
+ ## 📝 License
241
+
242
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "universal-mcp"
7
- version = "0.1.15-rc7"
7
+ version = "0.1.17"
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 = [
@@ -98,7 +98,7 @@ exclude = [
98
98
  "site-packages",
99
99
  "venv",
100
100
  ]
101
- line-length = 88
101
+ line-length = 120
102
102
  indent-width = 4
103
103
  target-version = "py312"
104
104
 
@@ -70,9 +70,7 @@ async def test_generate_api_with_output(sample_schema, temp_dir):
70
70
  """Test API generation with output file."""
71
71
  output_path = temp_dir / "test.py"
72
72
 
73
- app_file = generate_api_from_schema(
74
- schema_path=sample_schema, output_path=output_path
75
- )
73
+ app_file = generate_api_from_schema(schema_path=sample_schema, output_path=output_path)
76
74
 
77
75
  assert "app_file" != None
78
76
  assert "readme_file" != None
@@ -100,9 +98,7 @@ async def test_generate_api_invalid_schema(temp_dir):
100
98
  async def test_generate_api_nonexistent_schema():
101
99
  """Test API generation with nonexistent schema file."""
102
100
  with pytest.raises(FileNotFoundError):
103
- await generate_api_from_schema(
104
- schema_path=Path("nonexistent.json"), output_path=None
105
- )
101
+ await generate_api_from_schema(schema_path=Path("nonexistent.json"), output_path=None)
106
102
 
107
103
 
108
104
  @pytest.mark.asyncio
@@ -110,9 +106,7 @@ async def test_generate_api_without_docstrings(sample_schema, temp_dir):
110
106
  """Test API generation without docstring generation."""
111
107
  output_path = temp_dir / "test_without_docs.py"
112
108
 
113
- app_file = generate_api_from_schema(
114
- schema_path=sample_schema, output_path=output_path
115
- )
109
+ app_file = generate_api_from_schema(schema_path=sample_schema, output_path=output_path)
116
110
 
117
111
  assert app_file is not None
118
112
  assert app_file.exists()
@@ -169,9 +163,7 @@ async def test_generate_api_with_complex_schema(temp_dir):
169
163
  json.dump(schema, f)
170
164
 
171
165
  output_path = temp_dir / "complex.py"
172
- app_file = generate_api_from_schema(
173
- schema_path=schema_file, output_path=output_path
174
- )
166
+ app_file = generate_api_from_schema(schema_path=schema_file, output_path=output_path)
175
167
 
176
168
  assert app_file is not None
177
169
  assert app_file.exists()
@@ -9,7 +9,7 @@ ALL_APPS = [
9
9
  "airtable",
10
10
  "apollo",
11
11
  "asana",
12
- # "box",
12
+ "box",
13
13
  "braze",
14
14
  "cal-com-v2",
15
15
  "confluence",
@@ -34,7 +34,7 @@ ALL_APPS = [
34
34
  "google-sheet",
35
35
  "hashnode",
36
36
  "heygen",
37
- # "jira",
37
+ "jira",
38
38
  "klaviyo",
39
39
  "mailchimp",
40
40
  "markitdown",
@@ -13,9 +13,7 @@ async def test_zenquotes():
13
13
  )
14
14
  ]
15
15
 
16
- server_config = ServerConfig(
17
- name="Test Server", description="Test Server", apps=apps_list
18
- )
16
+ server_config = ServerConfig(name="Test Server", description="Test Server", apps=apps_list)
19
17
  server = LocalServer(server_config)
20
18
 
21
19
  # List available tools