universal-mcp 0.1.23rc2__py3-none-any.whl → 0.1.24rc2__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 (48) hide show
  1. universal_mcp/analytics.py +43 -11
  2. universal_mcp/applications/application.py +186 -132
  3. universal_mcp/applications/sample_tool_app.py +80 -0
  4. universal_mcp/cli.py +5 -229
  5. universal_mcp/client/agents/__init__.py +4 -0
  6. universal_mcp/client/agents/base.py +38 -0
  7. universal_mcp/client/agents/llm.py +115 -0
  8. universal_mcp/client/agents/react.py +67 -0
  9. universal_mcp/client/cli.py +181 -0
  10. universal_mcp/client/oauth.py +122 -18
  11. universal_mcp/client/token_store.py +62 -3
  12. universal_mcp/client/{client.py → transport.py} +127 -48
  13. universal_mcp/config.py +160 -46
  14. universal_mcp/exceptions.py +50 -6
  15. universal_mcp/integrations/__init__.py +1 -4
  16. universal_mcp/integrations/integration.py +220 -121
  17. universal_mcp/servers/__init__.py +1 -1
  18. universal_mcp/servers/server.py +114 -247
  19. universal_mcp/stores/store.py +126 -93
  20. universal_mcp/tools/func_metadata.py +1 -1
  21. universal_mcp/tools/manager.py +15 -3
  22. universal_mcp/tools/tools.py +2 -2
  23. universal_mcp/utils/agentr.py +3 -4
  24. universal_mcp/utils/installation.py +3 -4
  25. universal_mcp/utils/openapi/api_generator.py +28 -2
  26. universal_mcp/utils/openapi/api_splitter.py +0 -1
  27. universal_mcp/utils/openapi/cli.py +243 -0
  28. universal_mcp/utils/openapi/filters.py +114 -0
  29. universal_mcp/utils/openapi/openapi.py +31 -2
  30. universal_mcp/utils/openapi/preprocessor.py +62 -7
  31. universal_mcp/utils/prompts.py +787 -0
  32. universal_mcp/utils/singleton.py +4 -1
  33. universal_mcp/utils/testing.py +6 -6
  34. universal_mcp-0.1.24rc2.dist-info/METADATA +54 -0
  35. universal_mcp-0.1.24rc2.dist-info/RECORD +53 -0
  36. universal_mcp/applications/README.md +0 -122
  37. universal_mcp/client/__main__.py +0 -30
  38. universal_mcp/client/agent.py +0 -96
  39. universal_mcp/integrations/README.md +0 -25
  40. universal_mcp/servers/README.md +0 -79
  41. universal_mcp/stores/README.md +0 -74
  42. universal_mcp/tools/README.md +0 -86
  43. universal_mcp-0.1.23rc2.dist-info/METADATA +0 -283
  44. universal_mcp-0.1.23rc2.dist-info/RECORD +0 -51
  45. /universal_mcp/{utils → tools}/docstring_parser.py +0 -0
  46. {universal_mcp-0.1.23rc2.dist-info → universal_mcp-0.1.24rc2.dist-info}/WHEEL +0 -0
  47. {universal_mcp-0.1.23rc2.dist-info → universal_mcp-0.1.24rc2.dist-info}/entry_points.txt +0 -0
  48. {universal_mcp-0.1.23rc2.dist-info → universal_mcp-0.1.24rc2.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,6 @@
1
+ from typing import Any
2
+
3
+
1
4
  class Singleton(type):
2
5
  """Metaclass that ensures only one instance of a class exists.
3
6
 
@@ -15,7 +18,7 @@ class Singleton(type):
15
18
  assert a is b # True
16
19
  """
17
20
 
18
- _instances = {}
21
+ _instances: dict[type, Any] = {}
19
22
 
20
23
  def __call__(cls, *args, **kwargs):
21
24
  if cls not in cls._instances:
@@ -5,9 +5,9 @@ from universal_mcp.tools.tools import Tool
5
5
 
6
6
  def check_application_instance(app_instance, app_name):
7
7
  assert app_instance is not None, f"Application object is None for {app_name}"
8
- assert (
9
- app_instance.name == app_name
10
- ), f"Application instance name '{app_instance.name}' does not match expected name '{app_name}'"
8
+ assert app_instance.name == app_name, (
9
+ f"Application instance name '{app_instance.name}' does not match expected name '{app_name}'"
10
+ )
11
11
 
12
12
  tools = app_instance.list_tools()
13
13
  logger.info(f"Tools for {app_name}: {len(tools)}")
@@ -19,9 +19,9 @@ def check_application_instance(app_instance, app_name):
19
19
 
20
20
  for tool in tools:
21
21
  assert tool.name is not None, f"Tool name is None for a tool in {app_name}"
22
- assert (
23
- 0 < len(tool.name) <= 48
24
- ), f"Tool name '{tool.name}' for {app_name} has invalid length (must be between 1 and 47 characters)"
22
+ assert 0 < len(tool.name) <= 48, (
23
+ f"Tool name '{tool.name}' for {app_name} has invalid length (must be between 1 and 47 characters)"
24
+ )
25
25
  assert tool.description is not None, f"Tool description is None for tool '{tool.name}' in {app_name}"
26
26
  # assert 0 < len(tool.description) <= 255, f"Tool description for '{tool.name}' in {app_name} has invalid length (must be between 1 and 255 characters)"
27
27
  assert tool.name not in seen_names, f"Duplicate tool name: '{tool.name}' found for {app_name}"
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: universal-mcp
3
+ Version: 0.1.24rc2
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: black>=25.1.0
10
+ Requires-Dist: cookiecutter>=2.6.0
11
+ Requires-Dist: gql[all]>=3.5.2
12
+ Requires-Dist: jinja2>=3.1.3
13
+ Requires-Dist: jsonref>=1.1.0
14
+ Requires-Dist: keyring>=25.6.0
15
+ Requires-Dist: loguru>=0.7.3
16
+ Requires-Dist: mcp>=1.9.3
17
+ Requires-Dist: posthog>=3.24.0
18
+ Requires-Dist: pydantic-settings>=2.8.1
19
+ Requires-Dist: pydantic>=2.11.1
20
+ Requires-Dist: pyyaml>=6.0.2
21
+ Requires-Dist: rich>=14.0.0
22
+ Requires-Dist: typer>=0.15.2
23
+ Provides-Extra: dev
24
+ Requires-Dist: litellm>=1.30.7; extra == 'dev'
25
+ Requires-Dist: mypy>=1.16.0; 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
+ Description-Content-Type: text/markdown
32
+
33
+ # Universal MCP
34
+
35
+ 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.
36
+
37
+ ## Documentation
38
+
39
+ The primary documentation for Universal MCP is available in `/docs` folder in this repository.
40
+
41
+ Please refer to the following for more detailed information:
42
+
43
+ * **[Main Documentation](docs/index.md)**: For an overview of the project, features, quick start, and installation.
44
+ * **[Playground Usage](docs/playground.md)**: For instructions on using the interactive playground.
45
+ * **[Applications Framework](docs/applications.md)**: For details on the applications module.
46
+ * **[Integrations & Authentication](docs/integrations.md)**: For information on integration types.
47
+ * **[Server Implementations](docs/servers.md)**: For details on server types.
48
+ * **[Credential Stores](docs/stores.md)**: For information on credential stores.
49
+ * **[Tools Framework](docs/tools_framework.md)**: For details on the tool management system.
50
+ * **[Contributing Guidelines](CONTRIBUTING.md)**: For information on how to contribute to the project.
51
+
52
+ ## License
53
+
54
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,53 @@
1
+ universal_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ universal_mcp/analytics.py,sha256=8AjqAnqacos-1R9D6gf_eMbKFlBBIFSM9yv12AAnxlE,3961
3
+ universal_mcp/cli.py,sha256=aVTUGImHpEklW0OpLBLCYyvjv3M2Prf1ntkwmlG-Jxg,2238
4
+ universal_mcp/config.py,sha256=3CGLbwyhr4zq1kQ7vHIO4f6PyfmANFa9RVZEMVgSJ8U,10651
5
+ universal_mcp/exceptions.py,sha256=bf45HkNY-RVYzv8l_nPaxS5P2UCFww_oZmq508TMKgY,2070
6
+ universal_mcp/logger.py,sha256=VmH_83efpErLEDTJqz55Dp0dioTXfGvMBLZUx5smOLc,2116
7
+ universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ universal_mcp/applications/__init__.py,sha256=l19_sMs5766VFWU_7O2niamvvvfQOteysqylbqvjjGQ,3500
9
+ universal_mcp/applications/application.py,sha256=di4vuvAiOgVophzlvLiyVILdR8hPuSLS46YLQDEVq-c,23823
10
+ universal_mcp/applications/sample_tool_app.py,sha256=YfZGE6F-cqqJGLU3TxOk4fYlAuf-kCOdBw03S-5VcpE,2760
11
+ universal_mcp/client/cli.py,sha256=dZ_Uwp9grRN2UWOuE2PQ9eUAyGelNGI4GQkkliD_6Vs,6242
12
+ universal_mcp/client/oauth.py,sha256=O00zOUfQxINaruFU2zt-64DIR1_mAqrY8ykLQo-teJU,8679
13
+ universal_mcp/client/token_store.py,sha256=6VAzjzJG49wYvmEDqksFvb-fVqdjHIKWv7yYyh_AuF8,3912
14
+ universal_mcp/client/transport.py,sha256=xgAKBJ1-yCcTtl9cxzJgRn6to5Y9EvCwLc_WpDck3Dg,11838
15
+ universal_mcp/client/agents/__init__.py,sha256=ZeoMWi6C6ZaP28EzPhjTFlreZUP-FGo__VPgnKnU4uw,121
16
+ universal_mcp/client/agents/base.py,sha256=i8oAILtVoW4kHAx95fd8IaioqYrD1aqoWSRjUl05TaY,953
17
+ universal_mcp/client/agents/llm.py,sha256=O1cVPlXPhXb-x7GFIZ4dYFdB_Wd1eWHTTEV9FoBl_OE,5062
18
+ universal_mcp/client/agents/react.py,sha256=lI654OT-3gXwrTjbt0DTbB-tuim4ahqZ7vAFta_A6NY,2719
19
+ universal_mcp/integrations/__init__.py,sha256=UHno85kYa9nCjep31WpJlLu6ObNQxHzp4T57Q5eNILE,770
20
+ universal_mcp/integrations/integration.py,sha256=E-pC_VioPoJwyw5d_RquE7k2ygvXrAnphNzNt4NrOS0,19823
21
+ universal_mcp/servers/__init__.py,sha256=BbtZxl69EQcs9PpxBCkwa-vJKcfESgBfXQ5UYlkRQTo,542
22
+ universal_mcp/servers/server.py,sha256=CNLlVxNosqBipk1_WD0zQJz-MZDiK5k7d_tZMH3NpAQ,7542
23
+ universal_mcp/stores/__init__.py,sha256=quvuwhZnpiSLuojf0NfmBx2xpaCulv3fbKtKaSCEmuM,603
24
+ universal_mcp/stores/store.py,sha256=yWbEGZb53z3fpVyqGWbes63z1CtIzC_IuM49OXy__UY,10137
25
+ universal_mcp/tools/__init__.py,sha256=Fatza_R0qYWmNF1WQSfUZZKQFu5qf-16JhZzdmyx3KY,333
26
+ universal_mcp/tools/adapters.py,sha256=rnicV_WBgNe0WqVG60ms0o92BoRTRqd_C9jMMndx47c,3461
27
+ universal_mcp/tools/docstring_parser.py,sha256=efEOE-ME7G5Jbbzpn7pN2xNuyu2M5zfZ1Tqu1lRB0Gk,8392
28
+ universal_mcp/tools/func_metadata.py,sha256=F4jd--hoZWKPBbZihVtluYKUsIdXdq4a0VWRgMl5k-Q,10838
29
+ universal_mcp/tools/manager.py,sha256=Zpwr95rj4CvCRMkdX3_q3kZ9fYm8SkuLa-UkURG3WZQ,11740
30
+ universal_mcp/tools/tools.py,sha256=pHehD4dqaTSnMBNhsj0Gpb4_L8OIy1rlZOITIDt7cnU,3730
31
+ universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
32
+ universal_mcp/utils/agentr.py,sha256=8G9ZGQEA_Od2O9C6p439UclbzBgjvWB09Xej71NoAVk,3727
33
+ universal_mcp/utils/common.py,sha256=HEZC2Mhilb8DrGXQG2tboAIw1r4veGilGWjfnPF1lyA,888
34
+ universal_mcp/utils/installation.py,sha256=PU_GfHPqzkumKk-xG4L9CkBzSmABxmchwblZkx-zY-I,7204
35
+ universal_mcp/utils/prompts.py,sha256=g6esB47Z5BNZxubQtZ21faJUcpH8-wRfS4xgk-2vECs,33284
36
+ universal_mcp/utils/singleton.py,sha256=RoOiKxBOAhp0TK1QaMDYi-8GjRcy2Vh-bAOuIAcYan0,775
37
+ universal_mcp/utils/testing.py,sha256=Crk1OqHjXSHIMfPquIuzL4NBq7x1RxL4roTpJobDoY4,1464
38
+ universal_mcp/utils/openapi/__inti__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ universal_mcp/utils/openapi/api_generator.py,sha256=bX4nAZCZLh4cOO5deLh7MqJ3p3ZWOzggQsCwhUaFMb4,5696
40
+ universal_mcp/utils/openapi/api_splitter.py,sha256=io7fV-E8hUIR4NxFlakqydbgrQF6aBAnZHPMlpxw-wc,20967
41
+ universal_mcp/utils/openapi/cli.py,sha256=oQe8KzVa7OEe-ruJRaDlmKmhppEMb15qHyqbDc0QAAM,8715
42
+ universal_mcp/utils/openapi/docgen.py,sha256=DNmwlhg_-TRrHa74epyErMTRjV2nutfCQ7seb_Rq5hE,21366
43
+ universal_mcp/utils/openapi/filters.py,sha256=96FajO5nLbvjNPy2A1HvSS9jqpzMDHd4q_QTP-DIsPI,3842
44
+ universal_mcp/utils/openapi/openapi.py,sha256=xAzr7V1PHBPbRhGrjNoBxT1clvTL7y_9BghvYgEvBqw,52406
45
+ universal_mcp/utils/openapi/preprocessor.py,sha256=OYlJX9BOn-lBFmBEOii3S2_Vdp3EGXVu3Qc3vLXtGRI,63087
46
+ universal_mcp/utils/openapi/readme.py,sha256=R2Jp7DUXYNsXPDV6eFTkLiy7MXbSULUj1vHh4O_nB4c,2974
47
+ universal_mcp/utils/templates/README.md.j2,sha256=Mrm181YX-o_-WEfKs01Bi2RJy43rBiq2j6fTtbWgbTA,401
48
+ universal_mcp/utils/templates/api_client.py.j2,sha256=972Im7LNUAq3yZTfwDcgivnb-b8u6_JLKWXwoIwXXXQ,908
49
+ universal_mcp-0.1.24rc2.dist-info/METADATA,sha256=YiW1lPdirDqFJDTvpi5Ah-INW9p0_btzqiSKE2kQrxA,2546
50
+ universal_mcp-0.1.24rc2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
51
+ universal_mcp-0.1.24rc2.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
52
+ universal_mcp-0.1.24rc2.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
53
+ universal_mcp-0.1.24rc2.dist-info/RECORD,,
@@ -1,122 +0,0 @@
1
- # Universal MCP Applications Module
2
-
3
- This module provides the core functionality for managing and integrating applications within the Universal MCP system. It offers a flexible framework for creating, managing, and interacting with various types of applications through a unified interface.
4
-
5
- ## Overview
6
-
7
- The applications module provides three main base classes for building application integrations:
8
-
9
- 1. `BaseApplication`: The abstract base class that defines the common interface for all applications
10
- 2. `APIApplication`: A concrete implementation for applications that communicate via HTTP APIs
11
- 3. `GraphQLApplication`: A specialized implementation for applications that use GraphQL APIs
12
-
13
- ## Key Features
14
-
15
- - **Dynamic Application Loading**: Applications can be loaded dynamically from external packages
16
- - **Unified Credential Management**: Centralized handling of application credentials
17
- - **HTTP API Support**: Built-in support for RESTful API interactions
18
- - **GraphQL Support**: Specialized support for GraphQL-based applications
19
- - **Automatic Package Installation**: Automatic installation of application packages from GitHub
20
-
21
- ## Base Classes
22
-
23
- ### BaseApplication
24
-
25
- The foundation class for all applications, providing:
26
- - Basic initialization
27
- - Credential management
28
- - Tool listing interface
29
-
30
- ### APIApplication
31
-
32
- Extends BaseApplication to provide:
33
- - HTTP client management
34
- - Authentication handling
35
- - Common HTTP methods (GET, POST, PUT, DELETE, PATCH)
36
- - Request/response handling
37
-
38
- ### GraphQLApplication
39
-
40
- Specialized for GraphQL-based applications, offering:
41
- - GraphQL client management
42
- - Query and mutation execution
43
- - Authentication handling
44
-
45
- ## Usage
46
-
47
- ### Creating a New Application
48
-
49
- 1. Create a new package following the naming convention: `universal_mcp_<app_name>`
50
- 2. Implement your application class inheriting from one of the base classes
51
- 3. Name your class following the convention: `<AppName>App`
52
-
53
- Example:
54
- ```python
55
- from universal_mcp.applications import APIApplication
56
-
57
- class MyApp(APIApplication):
58
- def __init__(self, name: str, integration=None, **kwargs):
59
- super().__init__(name, integration, **kwargs)
60
- self.base_url = "https://api.example.com"
61
-
62
- def list_tools(self):
63
- return [self.my_tool]
64
-
65
- def my_tool(self):
66
- # Implementation here
67
- pass
68
- ```
69
-
70
- ### Loading an Application
71
-
72
- ```python
73
- from universal_mcp.applications import app_from_slug
74
-
75
- # The system will automatically install the package if needed
76
- MyApp = app_from_slug("my-app")
77
- app = MyApp("my-app-instance")
78
- ```
79
-
80
- ## Authentication
81
-
82
- The module supports various authentication methods:
83
- - API Keys
84
- - Access Tokens
85
- - Custom Headers
86
- - Bearer Tokens
87
-
88
- Credentials are managed through the integration system and can be accessed via the `credentials` property.
89
-
90
- ## Error Handling
91
-
92
- The module includes comprehensive error handling for:
93
- - Package installation failures
94
- - Import errors
95
- - API request failures
96
- - Authentication issues
97
-
98
- ## Logging
99
-
100
- All operations are logged using the `loguru` logger, providing detailed information about:
101
- - Application initialization
102
- - API requests
103
- - Authentication attempts
104
- - Package installation
105
- - Error conditions
106
-
107
- ## Requirements
108
-
109
- - Python 3.8+
110
- - httpx
111
- - gql
112
- - loguru
113
- - uv (for package installation)
114
-
115
- ## Contributing
116
-
117
- To contribute a new application:
118
- 1. Create a new package following the naming conventions
119
- 2. Implement the application class
120
- 3. Add proper error handling and logging
121
- 4. Include comprehensive documentation
122
- 5. Submit a pull request to the Universal MCP repository
@@ -1,30 +0,0 @@
1
- import asyncio
2
- import os
3
- import sys
4
-
5
- from loguru import logger
6
- from pydantic import ValidationError
7
-
8
- from universal_mcp.client.agent import ChatSession
9
- from universal_mcp.client.client import MultiClientServer
10
- from universal_mcp.config import ClientConfig
11
-
12
-
13
- async def main() -> None:
14
- """Initialize and run the chat session."""
15
- # Load settings and config using Pydantic BaseSettings
16
-
17
- config_path = os.getenv("MCP_CONFIG_PATH", "servers.json")
18
- try:
19
- app_config = ClientConfig.load_json_config(config_path)
20
- except (FileNotFoundError, ValidationError) as e:
21
- logger.error(f"Error loading config: {e}")
22
- sys.exit(1)
23
-
24
- async with MultiClientServer(app_config.mcpServers) as mcp_server:
25
- chat_session = ChatSession(mcp_server, app_config.llm)
26
- await chat_session.interactive_loop()
27
-
28
-
29
- if __name__ == "__main__":
30
- asyncio.run(main())
@@ -1,96 +0,0 @@
1
- import json
2
-
3
- from loguru import logger
4
- from mcp.server import Server as MCPServer
5
- from openai import AsyncOpenAI
6
-
7
- from universal_mcp.config import LLMConfig
8
-
9
-
10
- class ChatSession:
11
- """Orchestrates the interaction between user, LLM, and tools."""
12
-
13
- def __init__(self, mcp_server: MCPServer, llm: LLMConfig | None) -> None:
14
- self.mcp_server: MCPServer = mcp_server
15
- self.llm: AsyncOpenAI | None = AsyncOpenAI(api_key=llm.api_key, base_url=llm.base_url) if llm else None
16
- self.model = llm.model if llm else None
17
-
18
- async def run(self, messages, tools) -> None:
19
- """Run the chat session."""
20
- llm_response = await self.llm.chat.completions.create(
21
- model=self.model,
22
- messages=messages,
23
- tools=tools,
24
- tool_choice="auto",
25
- )
26
-
27
- tool_calls = llm_response.choices[0].message.tool_calls
28
- if tool_calls:
29
- for tool_call in tool_calls:
30
- result = await self.mcp_server.call_tool(
31
- tool_name=tool_call.function.name,
32
- arguments=json.loads(tool_call.function.arguments) if tool_call.function.arguments else {},
33
- )
34
- result_content = [rc.text for rc in result.content] if result.content else "No result"
35
- messages.append(
36
- {
37
- "tool_call_id": tool_call.id,
38
- "role": "tool",
39
- "name": tool_call.function.name,
40
- "content": result_content,
41
- }
42
- )
43
- else:
44
- messages.append(llm_response.choices[0].message)
45
- return messages
46
-
47
- async def interactive_loop(self) -> None:
48
- """Main chat session handler."""
49
- all_openai_tools = await self.mcp_server.list_tools(format="openai")
50
- system_message = "You are a helpful assistant"
51
- messages = [{"role": "system", "content": system_message}]
52
-
53
- print("\n🎯 Interactive MCP Client")
54
- print("Commands:")
55
- print(" list - List available tools")
56
- print(" call <tool_name> [args] - Call a tool")
57
- print(" quit - Exit the client")
58
- print()
59
- while True:
60
- try:
61
- user_input = input("You: ").strip()
62
- if user_input.lower() in {"quit", "exit"}:
63
- logger.info("\nExiting...")
64
- break
65
- elif user_input.lower() == "list":
66
- tools = await self.mcp_server.list_tools()
67
- print("\nAvailable tools:")
68
- for tool in tools:
69
- print(f" {tool.name}")
70
- continue
71
- elif user_input.startswith("call "):
72
- parts = user_input.split(maxsplit=2)
73
- tool_name = parts[1] if len(parts) > 1 else ""
74
-
75
- if not tool_name:
76
- print("❌ Please specify a tool name")
77
- continue
78
-
79
- # Parse arguments (simple JSON-like format)
80
- arguments = {}
81
- if len(parts) > 2:
82
- try:
83
- arguments = json.loads(parts[2])
84
- except json.JSONDecodeError:
85
- print("❌ Invalid arguments format (expected JSON)")
86
- continue
87
- await self.mcp_server.call_tool(tool_name, arguments)
88
-
89
- messages.append({"role": "user", "content": user_input})
90
-
91
- messages = await self.run(messages, all_openai_tools)
92
- print("\nAssistant: ", messages[-1]["content"])
93
-
94
- except KeyboardInterrupt:
95
- print("\nExiting...")
96
- break
@@ -1,25 +0,0 @@
1
- # Integrations
2
-
3
- This package provides integration classes for handling authentication and authorization with external services.
4
-
5
- ## Overview
6
-
7
- An Integration defines how an application authenticates and authorizes with a service provider. The base `Integration` class provides an interface that all integrations must implement.
8
-
9
- ## Supported Integrations
10
-
11
- ### AgentR Integration
12
- The `AgentRIntegration` class handles OAuth-based authentication flow with the AgentR API. It requires an API key which can be obtained from [agentr.dev](https://agentr.dev).
13
-
14
- ### API Key Integration
15
- The `ApiKeyIntegration` class provides a simple API key based authentication mechanism. API keys are configured via environment variables.
16
-
17
- ## Usage
18
-
19
- Each integration implements three key methods:
20
-
21
- - `authorize()` - Initiates the authorization flow
22
- - `get_credentials()` - Retrieves stored credentials
23
- - `set_credentials()` - Stores new credentials
24
-
25
- See the individual integration classes for specific usage details.
@@ -1,79 +0,0 @@
1
- # Servers
2
-
3
- This package provides server implementations for hosting and managing MCP (Model Control Protocol) applications.
4
-
5
- ## Overview
6
-
7
- The server implementations provide different ways to host and expose MCP applications and their tools. The base `BaseServer` class provides common functionality that all server implementations inherit.
8
-
9
- ## Supported Server Types
10
-
11
- ### Local Server
12
- The `LocalServer` class provides a local development server implementation that:
13
- - Loads applications from local configuration
14
- - Manages a local store for data persistence
15
- - Supports integration with external services
16
- - Exposes application tools through the MCP protocol
17
-
18
- ### AgentR Server
19
- The `AgentRServer` class provides a server implementation that:
20
- - Connects to the AgentR API
21
- - Dynamically fetches and loads available applications
22
- - Manages AgentR-specific integrations
23
- - Requires an API key for authentication
24
-
25
- ### Single MCP Server
26
- The `SingleMCPServer` class provides a minimal server implementation that:
27
- - Hosts a single application instance
28
- - Ideal for development and testing
29
- - Does not manage integrations or stores internally
30
- - Exposes only the tools from the provided application
31
-
32
- ## Core Features
33
-
34
- All server implementations provide:
35
-
36
- - Tool management and registration
37
- - Application loading and configuration
38
- - Error handling and logging
39
- - MCP protocol compliance
40
- - Integration support
41
-
42
- ## Usage
43
-
44
- Each server implementation can be initialized with a `ServerConfig` object that specifies:
45
- - Server name and description
46
- - Port configuration
47
- - Application configurations
48
- - Store configuration (where applicable)
49
-
50
- Example:
51
- ```python
52
- from universal_mcp.servers import LocalServer
53
- from universal_mcp.config import ServerConfig
54
-
55
- config = ServerConfig(
56
- name="My Local Server",
57
- description="Development server for testing applications",
58
- port=8000,
59
- # ... additional configuration
60
- )
61
-
62
- server = LocalServer(config)
63
- ```
64
-
65
- ## Tool Management
66
-
67
- Servers provide methods for:
68
- - Adding individual tools
69
- - Listing available tools
70
- - Calling tools with proper error handling
71
- - Formatting tool results
72
-
73
- ## Error Handling
74
-
75
- All servers implement comprehensive error handling for:
76
- - Tool execution failures
77
- - Application loading errors
78
- - Integration setup issues
79
- - API communication problems
@@ -1,74 +0,0 @@
1
- # Universal MCP Stores
2
-
3
- The stores module provides a flexible and secure way to manage credentials and sensitive data across different storage backends. It implements a common interface for storing, retrieving, and deleting sensitive information.
4
-
5
- ## Features
6
-
7
- - Abstract base class defining a consistent interface for credential stores
8
- - Multiple storage backend implementations:
9
- - In-memory store (temporary storage)
10
- - Environment variable store
11
- - System keyring store (secure credential storage)
12
- - Exception handling for common error cases
13
- - Type hints and comprehensive documentation
14
-
15
- ## Available Store Implementations
16
-
17
- ### MemoryStore
18
- A simple in-memory store that persists data only for the duration of program execution. Useful for testing or temporary storage.
19
-
20
- ```python
21
- from universal_mcp.stores import MemoryStore
22
-
23
- store = MemoryStore()
24
- store.set("api_key", "secret123")
25
- value = store.get("api_key") # Returns "secret123"
26
- ```
27
-
28
- ### EnvironmentStore
29
- Uses environment variables to store and retrieve credentials. Useful for containerized environments or CI/CD pipelines.
30
-
31
- ```python
32
- from universal_mcp.stores import EnvironmentStore
33
-
34
- store = EnvironmentStore()
35
- store.set("API_KEY", "secret123")
36
- value = store.get("API_KEY") # Returns "secret123"
37
- ```
38
-
39
- ### KeyringStore
40
- Leverages the system's secure credential storage facility. Provides the most secure option for storing sensitive data.
41
-
42
- ```python
43
- from universal_mcp.stores import KeyringStore
44
-
45
- store = KeyringStore(app_name="my_app")
46
- store.set("api_key", "secret123")
47
- value = store.get("api_key") # Returns "secret123"
48
- ```
49
-
50
- ## Error Handling
51
-
52
- The module provides specific exception types for handling errors:
53
-
54
- - `StoreError`: Base exception for all store-related errors
55
- - `KeyNotFoundError`: Raised when a requested key is not found in the store
56
-
57
- ## Best Practices
58
-
59
- 1. Use `KeyringStore` for production environments where security is a priority
60
- 2. Use `EnvironmentStore` for containerized or cloud environments
61
- 3. Use `MemoryStore` for testing or temporary storage only
62
- 4. Always handle `StoreError` and `KeyNotFoundError` exceptions appropriately
63
-
64
- ## Dependencies
65
-
66
- - `keyring`: Required for the KeyringStore implementation
67
- - `loguru`: Used for logging operations in the KeyringStore
68
-
69
- ## Contributing
70
-
71
- New store implementations should inherit from `BaseStore` and implement all required abstract methods:
72
- - `get(key: str) -> Any`
73
- - `set(key: str, value: str) -> None`
74
- - `delete(key: str) -> None`
@@ -1,86 +0,0 @@
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