universal-mcp 0.1.23rc1__tar.gz → 0.1.24rc2__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.
- universal_mcp-0.1.24rc2/PKG-INFO +54 -0
- universal_mcp-0.1.24rc2/README.md +22 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/pyproject.toml +8 -41
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_applications.py +3 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_tool.py +1 -1
- universal_mcp-0.1.24rc2/src/universal_mcp/analytics.py +113 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/applications/application.py +569 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/applications/sample_tool_app.py +80 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/cli.py +75 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/agents/__init__.py +4 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/agents/base.py +38 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/agents/llm.py +115 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/agents/react.py +67 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/cli.py +181 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/oauth.py +218 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/token_store.py +91 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/client/transport.py +277 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/config.py +245 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/exceptions.py +69 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/integrations/__init__.py +1 -4
- universal_mcp-0.1.24rc2/src/universal_mcp/integrations/integration.py +488 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/servers/__init__.py +1 -1
- universal_mcp-0.1.24rc2/src/universal_mcp/servers/server.py +184 -0
- universal_mcp-0.1.24rc2/src/universal_mcp/stores/store.py +273 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/tools/adapters.py +16 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/tools/func_metadata.py +1 -1
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/tools/manager.py +15 -3
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/tools/tools.py +2 -2
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/agentr.py +3 -4
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/installation.py +3 -4
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/api_generator.py +28 -2
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/api_splitter.py +8 -19
- {universal_mcp-0.1.23rc1/src/universal_mcp → universal_mcp-0.1.24rc2/src/universal_mcp/utils/openapi}/cli.py +5 -60
- universal_mcp-0.1.24rc2/src/universal_mcp/utils/openapi/filters.py +114 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/openapi.py +45 -12
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/preprocessor.py +62 -7
- universal_mcp-0.1.24rc2/src/universal_mcp/utils/prompts.py +787 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/singleton.py +4 -1
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/testing.py +6 -6
- universal_mcp-0.1.23rc1/PKG-INFO +0 -283
- universal_mcp-0.1.23rc1/README.md +0 -242
- universal_mcp-0.1.23rc1/src/universal_mcp/analytics.py +0 -81
- universal_mcp-0.1.23rc1/src/universal_mcp/applications/README.md +0 -122
- universal_mcp-0.1.23rc1/src/universal_mcp/applications/application.py +0 -622
- universal_mcp-0.1.23rc1/src/universal_mcp/config.py +0 -72
- universal_mcp-0.1.23rc1/src/universal_mcp/exceptions.py +0 -25
- universal_mcp-0.1.23rc1/src/universal_mcp/integrations/README.md +0 -25
- universal_mcp-0.1.23rc1/src/universal_mcp/integrations/integration.py +0 -389
- universal_mcp-0.1.23rc1/src/universal_mcp/servers/README.md +0 -79
- universal_mcp-0.1.23rc1/src/universal_mcp/servers/server.py +0 -317
- universal_mcp-0.1.23rc1/src/universal_mcp/stores/README.md +0 -74
- universal_mcp-0.1.23rc1/src/universal_mcp/stores/store.py +0 -240
- universal_mcp-0.1.23rc1/src/universal_mcp/tools/README.md +0 -86
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/.gitignore +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/LICENSE +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/__init__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/conftest.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_api_generator.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_api_integration.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_localserver.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_stores.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_tool_manager.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/tests/test_zenquotes.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/__init__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/applications/__init__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/logger.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/py.typed +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/stores/__init__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/tools/__init__.py +0 -0
- {universal_mcp-0.1.23rc1/src/universal_mcp/utils → universal_mcp-0.1.24rc2/src/universal_mcp/tools}/docstring_parser.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/__init__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/common.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/__inti__.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/docgen.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/openapi/readme.py +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/templates/README.md.j2 +0 -0
- {universal_mcp-0.1.23rc1 → universal_mcp-0.1.24rc2}/src/universal_mcp/utils/templates/api_client.py.j2 +0 -0
@@ -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,22 @@
|
|
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
|
+
## Documentation
|
6
|
+
|
7
|
+
The primary documentation for Universal MCP is available in `/docs` folder in this repository.
|
8
|
+
|
9
|
+
Please refer to the following for more detailed information:
|
10
|
+
|
11
|
+
* **[Main Documentation](docs/index.md)**: For an overview of the project, features, quick start, and installation.
|
12
|
+
* **[Playground Usage](docs/playground.md)**: For instructions on using the interactive playground.
|
13
|
+
* **[Applications Framework](docs/applications.md)**: For details on the applications module.
|
14
|
+
* **[Integrations & Authentication](docs/integrations.md)**: For information on integration types.
|
15
|
+
* **[Server Implementations](docs/servers.md)**: For details on server types.
|
16
|
+
* **[Credential Stores](docs/stores.md)**: For information on credential stores.
|
17
|
+
* **[Tools Framework](docs/tools_framework.md)**: For details on the tool management system.
|
18
|
+
* **[Contributing Guidelines](CONTRIBUTING.md)**: For information on how to contribute to the project.
|
19
|
+
|
20
|
+
## License
|
21
|
+
|
22
|
+
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.
|
7
|
+
version = "0.1.24-rc2"
|
8
8
|
description = "Universal MCP acts as a middle ware for your API applications. It can store your credentials, authorize, enable disable apps on the fly and much more."
|
9
9
|
readme = "README.md"
|
10
10
|
authors = [
|
@@ -19,10 +19,8 @@ dependencies = [
|
|
19
19
|
"gql[all]>=3.5.2",
|
20
20
|
"jsonref>=1.1.0",
|
21
21
|
"keyring>=25.6.0",
|
22
|
-
"langchain-mcp-adapters>=0.0.3",
|
23
|
-
"litellm>=1.30.7",
|
24
22
|
"loguru>=0.7.3",
|
25
|
-
"mcp>=1.9.
|
23
|
+
"mcp>=1.9.3",
|
26
24
|
"posthog>=3.24.0",
|
27
25
|
"pydantic>=2.11.1",
|
28
26
|
"pydantic-settings>=2.8.1",
|
@@ -33,6 +31,7 @@ dependencies = [
|
|
33
31
|
|
34
32
|
[project.optional-dependencies]
|
35
33
|
dev = [
|
34
|
+
"mypy>=1.16.0",
|
36
35
|
"litellm>=1.30.7",
|
37
36
|
"pre-commit>=4.2.0",
|
38
37
|
"pyright>=1.1.398",
|
@@ -40,15 +39,6 @@ dev = [
|
|
40
39
|
"pytest-asyncio>=0.26.0",
|
41
40
|
"ruff>=0.11.4",
|
42
41
|
]
|
43
|
-
playground = [
|
44
|
-
"langchain-openai>=0.3.12",
|
45
|
-
"langgraph>=0.3.24",
|
46
|
-
"langgraph-checkpoint-sqlite>=2.0.6",
|
47
|
-
"python-dotenv>=1.0.1",
|
48
|
-
"streamlit>=1.44.1",
|
49
|
-
"watchdog>=6.0.0",
|
50
|
-
"litellm>=1.30.7",
|
51
|
-
]
|
52
42
|
|
53
43
|
[project.scripts]
|
54
44
|
universal_mcp = "universal_mcp.cli:app"
|
@@ -71,34 +61,6 @@ packages = ["src/universal_mcp"]
|
|
71
61
|
# Tool configurations
|
72
62
|
# ------------------------------
|
73
63
|
[tool.ruff]
|
74
|
-
exclude = [
|
75
|
-
".bzr",
|
76
|
-
".direnv",
|
77
|
-
".eggs",
|
78
|
-
".git",
|
79
|
-
".git-rewrite",
|
80
|
-
".hg",
|
81
|
-
".ipynb_checkpoints",
|
82
|
-
".mypy_cache",
|
83
|
-
".nox",
|
84
|
-
".pants.d",
|
85
|
-
".pyenv",
|
86
|
-
".pytest_cache",
|
87
|
-
".pytype",
|
88
|
-
".ruff_cache",
|
89
|
-
".svn",
|
90
|
-
".tox",
|
91
|
-
".venv",
|
92
|
-
".vscode",
|
93
|
-
"__pypackages__",
|
94
|
-
"_build",
|
95
|
-
"buck-out",
|
96
|
-
"build",
|
97
|
-
"dist",
|
98
|
-
"node_modules",
|
99
|
-
"site-packages",
|
100
|
-
"venv",
|
101
|
-
]
|
102
64
|
line-length = 120
|
103
65
|
indent-width = 4
|
104
66
|
target-version = "py312"
|
@@ -127,3 +89,8 @@ docstring-code-line-length = "dynamic"
|
|
127
89
|
[tool.pytest.ini_options]
|
128
90
|
asyncio_mode = "strict"
|
129
91
|
asyncio_default_fixture_loop_scope = "function"
|
92
|
+
|
93
|
+
[tool.mypy]
|
94
|
+
exclude = [
|
95
|
+
'^src/universal_mcp/utils/openapi/\.*',
|
96
|
+
]
|
@@ -6,6 +6,7 @@ from universal_mcp.utils.testing import check_application_instance
|
|
6
6
|
ALL_APPS = [
|
7
7
|
"ahrefs",
|
8
8
|
"airtable",
|
9
|
+
"aws-s3",
|
9
10
|
"apollo",
|
10
11
|
"asana",
|
11
12
|
"box",
|
@@ -39,6 +40,7 @@ ALL_APPS = [
|
|
39
40
|
"mailchimp",
|
40
41
|
"markitdown",
|
41
42
|
"miro",
|
43
|
+
"ms-teams",
|
42
44
|
"neon",
|
43
45
|
"notion",
|
44
46
|
"perplexity",
|
@@ -50,6 +52,7 @@ ALL_APPS = [
|
|
50
52
|
"retell",
|
51
53
|
"rocketlane",
|
52
54
|
"serpapi",
|
55
|
+
"sharepoint",
|
53
56
|
"shopify",
|
54
57
|
"shortcut",
|
55
58
|
"spotify",
|
@@ -3,9 +3,9 @@ from typing import Annotated
|
|
3
3
|
|
4
4
|
from pydantic import Field
|
5
5
|
|
6
|
+
from universal_mcp.tools.docstring_parser import parse_docstring # Assuming this is the updated one
|
6
7
|
from universal_mcp.tools.func_metadata import FuncMetadata
|
7
8
|
from universal_mcp.tools.tools import Tool
|
8
|
-
from universal_mcp.utils.docstring_parser import parse_docstring # Assuming this is the updated one
|
9
9
|
|
10
10
|
|
11
11
|
def test_func_metadata_annotated():
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import os
|
2
|
+
import uuid
|
3
|
+
from functools import lru_cache
|
4
|
+
from importlib.metadata import version
|
5
|
+
|
6
|
+
import posthog
|
7
|
+
from loguru import logger
|
8
|
+
|
9
|
+
|
10
|
+
class Analytics:
|
11
|
+
"""A singleton class for tracking analytics events using PostHog.
|
12
|
+
|
13
|
+
This class handles the initialization of the PostHog client and provides
|
14
|
+
methods to track key events such as application loading and tool execution.
|
15
|
+
Telemetry can be disabled by setting the TELEMETRY_DISABLED environment
|
16
|
+
variable to "true".
|
17
|
+
"""
|
18
|
+
|
19
|
+
_instance = None
|
20
|
+
|
21
|
+
def __new__(cls):
|
22
|
+
if cls._instance is None:
|
23
|
+
cls._instance = super().__new__(cls)
|
24
|
+
cls._instance._initialize()
|
25
|
+
return cls._instance
|
26
|
+
|
27
|
+
def _initialize(self):
|
28
|
+
"""Initializes the PostHog client and sets up analytics properties.
|
29
|
+
|
30
|
+
This internal method configures the PostHog API key and host.
|
31
|
+
It also determines if analytics should be enabled based on the
|
32
|
+
TELEMETRY_DISABLED environment variable and generates a unique
|
33
|
+
user ID.
|
34
|
+
"""
|
35
|
+
posthog.host = "https://us.i.posthog.com"
|
36
|
+
posthog.api_key = "phc_6HXMDi8CjfIW0l04l34L7IDkpCDeOVz9cOz1KLAHXh8"
|
37
|
+
self.enabled = os.getenv("TELEMETRY_DISABLED", "false").lower() != "true"
|
38
|
+
self.user_id = str(uuid.uuid4())[:8]
|
39
|
+
|
40
|
+
@staticmethod
|
41
|
+
@lru_cache(maxsize=1)
|
42
|
+
def get_version():
|
43
|
+
"""Retrieves the installed version of the universal_mcp package.
|
44
|
+
|
45
|
+
Uses importlib.metadata to get the package version.
|
46
|
+
Caches the result for efficiency.
|
47
|
+
|
48
|
+
Returns:
|
49
|
+
str: The package version string, or "unknown" if not found.
|
50
|
+
"""
|
51
|
+
try:
|
52
|
+
return version("universal_mcp")
|
53
|
+
except ImportError: # Should be PackageNotFoundError, but matching existing code
|
54
|
+
return "unknown"
|
55
|
+
|
56
|
+
def track_app_loaded(self, app_name: str):
|
57
|
+
"""Tracks an event when an application is successfully loaded.
|
58
|
+
|
59
|
+
This event helps understand which applications are being utilized.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
app_name (str): The name of the application that was loaded.
|
63
|
+
"""
|
64
|
+
if not self.enabled:
|
65
|
+
return
|
66
|
+
try:
|
67
|
+
properties = {
|
68
|
+
"version": self.get_version(),
|
69
|
+
"app_name": app_name,
|
70
|
+
}
|
71
|
+
posthog.capture(self.user_id, "app_loaded", properties)
|
72
|
+
except Exception as e:
|
73
|
+
logger.error(f"Failed to track app_loaded event: {e}")
|
74
|
+
|
75
|
+
def track_tool_called(
|
76
|
+
self,
|
77
|
+
tool_name: str,
|
78
|
+
app_name: str,
|
79
|
+
status: str,
|
80
|
+
error: str = None,
|
81
|
+
user_id=None, # Note: user_id is captured in PostHog but not used from this param
|
82
|
+
):
|
83
|
+
"""Tracks an event when a tool is called within an application.
|
84
|
+
|
85
|
+
This event provides insights into tool usage patterns, success rates,
|
86
|
+
and potential errors.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
tool_name (str): The name of the tool that was called.
|
90
|
+
app_name (str): The name of the application the tool belongs to.
|
91
|
+
status (str): The status of the tool call (e.g., "success", "error").
|
92
|
+
error (str, optional): The error message if the tool call failed.
|
93
|
+
Defaults to None.
|
94
|
+
user_id (str, optional): An optional user identifier.
|
95
|
+
Note: Currently, the class uses an internally
|
96
|
+
generated user_id for PostHog events.
|
97
|
+
"""
|
98
|
+
if not self.enabled:
|
99
|
+
return
|
100
|
+
try:
|
101
|
+
properties = {
|
102
|
+
"tool_name": tool_name,
|
103
|
+
"app_name": app_name,
|
104
|
+
"status": status,
|
105
|
+
"error": error,
|
106
|
+
"version": self.get_version(),
|
107
|
+
}
|
108
|
+
posthog.capture(self.user_id, "tool_called", properties)
|
109
|
+
except Exception as e:
|
110
|
+
logger.error(f"Failed to track tool_called event: {e}")
|
111
|
+
|
112
|
+
|
113
|
+
analytics = Analytics()
|