universal-mcp 0.1.8rc3__py3-none-any.whl → 0.1.8rc4__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.
- universal_mcp/applications/ahrefs/README.md +76 -0
- universal_mcp/applications/ahrefs/__init__.py +0 -0
- universal_mcp/applications/ahrefs/app.py +2291 -0
- universal_mcp/applications/application.py +67 -0
- universal_mcp/applications/calendly/app.py +0 -12
- universal_mcp/applications/coda/app.py +0 -33
- universal_mcp/applications/e2b/app.py +2 -28
- universal_mcp/applications/figma/README.md +74 -0
- universal_mcp/applications/figma/__init__.py +0 -0
- universal_mcp/applications/figma/app.py +1261 -0
- universal_mcp/applications/firecrawl/app.py +2 -32
- universal_mcp/applications/google_calendar/app.py +0 -11
- universal_mcp/applications/google_docs/app.py +0 -18
- universal_mcp/applications/google_drive/app.py +0 -17
- universal_mcp/applications/google_mail/app.py +0 -16
- universal_mcp/applications/google_sheet/app.py +0 -18
- universal_mcp/applications/perplexity/app.py +0 -34
- universal_mcp/applications/resend/app.py +0 -18
- universal_mcp/applications/serpapi/app.py +2 -28
- universal_mcp/applications/tavily/app.py +0 -20
- universal_mcp/applications/wrike/app.py +0 -12
- universal_mcp/applications/youtube/app.py +0 -18
- universal_mcp/integrations/agentr.py +27 -4
- universal_mcp/integrations/integration.py +14 -6
- universal_mcp/servers/server.py +0 -3
- universal_mcp/utils/installation.py +199 -8
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.8rc4.dist-info}/METADATA +1 -1
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.8rc4.dist-info}/RECORD +30 -24
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.8rc4.dist-info}/WHEEL +0 -0
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.8rc4.dist-info}/entry_points.txt +0 -0
@@ -15,41 +15,11 @@ class FirecrawlApp(APIApplication):
|
|
15
15
|
|
16
16
|
def __init__(self, integration: Integration | None = None) -> None:
|
17
17
|
super().__init__(name="firecrawl", integration=integration)
|
18
|
-
self.api_key: str | None = None
|
19
|
-
|
20
|
-
def _set_api_key(self):
|
21
|
-
"""
|
22
|
-
Ensures the API key is loaded from the integration.
|
23
|
-
Raises ValueError if the integration or key is missing/misconfigured.
|
24
|
-
"""
|
25
|
-
if self.api_key:
|
26
|
-
return
|
27
|
-
|
28
|
-
if not self.integration:
|
29
|
-
raise ValueError("Integration is None. Cannot retrieve Firecrawl API Key.")
|
30
|
-
|
31
|
-
credentials = self.integration.get_credentials()
|
32
|
-
if not credentials:
|
33
|
-
raise ValueError(
|
34
|
-
f"Failed to retrieve Firecrawl API Key using integration '{self.integration.name}'. "
|
35
|
-
f"Check store configuration (e.g., ensure the correct source like environment variable is set)."
|
36
|
-
)
|
37
|
-
api_key = (
|
38
|
-
credentials.get("api_key")
|
39
|
-
or credentials.get("API_KEY")
|
40
|
-
or credentials.get("apiKey")
|
41
|
-
)
|
42
|
-
if not api_key:
|
43
|
-
raise ValueError(
|
44
|
-
f"Failed to retrieve Firecrawl API Key using integration '{self.integration.name}'. "
|
45
|
-
f"Check store configuration (e.g., ensure the correct environment variable is set)."
|
46
|
-
)
|
47
|
-
self.api_key = api_key
|
48
18
|
|
49
19
|
def _get_client(self) -> FirecrawlApiClient:
|
50
20
|
"""Initializes and returns the Firecrawl client after ensuring API key is set."""
|
51
|
-
self.
|
52
|
-
return FirecrawlApiClient(api_key=
|
21
|
+
api_key = self.integration.get_credentials().get("api_key")
|
22
|
+
return FirecrawlApiClient(api_key=api_key)
|
53
23
|
|
54
24
|
def scrape_url(
|
55
25
|
self, url: str, params: dict[str, Any] | None = None
|
@@ -11,17 +11,6 @@ class GoogleCalendarApp(APIApplication):
|
|
11
11
|
super().__init__(name="google-calendar", integration=integration)
|
12
12
|
self.base_api_url = "https://www.googleapis.com/calendar/v3/calendars/primary"
|
13
13
|
|
14
|
-
def _get_headers(self):
|
15
|
-
if not self.integration:
|
16
|
-
raise ValueError("Integration not configured for GoogleCalendarApp")
|
17
|
-
credentials = self.integration.get_credentials()
|
18
|
-
if "headers" in credentials:
|
19
|
-
return credentials["headers"]
|
20
|
-
return {
|
21
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
22
|
-
"Accept": "application/json",
|
23
|
-
}
|
24
|
-
|
25
14
|
def _format_datetime(self, dt_string: str) -> str:
|
26
15
|
"""Format a datetime string from ISO format to a human-readable format.
|
27
16
|
|
@@ -1,9 +1,6 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
-
from loguru import logger
|
4
|
-
|
5
3
|
from universal_mcp.applications.application import APIApplication
|
6
|
-
from universal_mcp.exceptions import NotAuthorizedError
|
7
4
|
from universal_mcp.integrations import Integration
|
8
5
|
|
9
6
|
|
@@ -12,21 +9,6 @@ class GoogleDocsApp(APIApplication):
|
|
12
9
|
super().__init__(name="google-docs", integration=integration)
|
13
10
|
self.base_api_url = "https://docs.googleapis.com/v1/documents"
|
14
11
|
|
15
|
-
def _get_headers(self):
|
16
|
-
if not self.integration:
|
17
|
-
raise ValueError("Integration not configured for GoogleDocsApp")
|
18
|
-
credentials = self.integration.get_credentials()
|
19
|
-
if not credentials:
|
20
|
-
logger.warning("No Google credentials found via integration.")
|
21
|
-
action = self.integration.authorize()
|
22
|
-
raise NotAuthorizedError(action)
|
23
|
-
if "headers" in credentials:
|
24
|
-
return credentials["headers"]
|
25
|
-
return {
|
26
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
27
|
-
"Content-Type": "application/json",
|
28
|
-
}
|
29
|
-
|
30
12
|
def create_document(self, title: str) -> dict[str, Any]:
|
31
13
|
"""
|
32
14
|
Creates a new blank Google Document with the specified title and returns the API response.
|
@@ -4,7 +4,6 @@ import httpx
|
|
4
4
|
from loguru import logger
|
5
5
|
|
6
6
|
from universal_mcp.applications.application import APIApplication
|
7
|
-
from universal_mcp.exceptions import NotAuthorizedError
|
8
7
|
from universal_mcp.integrations import Integration
|
9
8
|
|
10
9
|
|
@@ -18,22 +17,6 @@ class GoogleDriveApp(APIApplication):
|
|
18
17
|
super().__init__(name="google-drive", integration=integration)
|
19
18
|
self.base_url = "https://www.googleapis.com/drive/v3"
|
20
19
|
|
21
|
-
def _get_headers(self):
|
22
|
-
if not self.integration:
|
23
|
-
raise ValueError("Integration not configured for GoogleDriveApp")
|
24
|
-
credentials = self.integration.get_credentials()
|
25
|
-
if not credentials:
|
26
|
-
logger.warning("No Google Drive credentials found via integration.")
|
27
|
-
action = self.integration.authorize()
|
28
|
-
raise NotAuthorizedError(action)
|
29
|
-
|
30
|
-
if "headers" in credentials:
|
31
|
-
return credentials["headers"]
|
32
|
-
return {
|
33
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
34
|
-
"Content-Type": "application/json",
|
35
|
-
}
|
36
|
-
|
37
20
|
def get_drive_info(self) -> dict[str, Any]:
|
38
21
|
"""
|
39
22
|
Retrieves detailed information about the user's Google Drive storage and account.
|
@@ -13,22 +13,6 @@ class GoogleMailApp(APIApplication):
|
|
13
13
|
super().__init__(name="google-mail", integration=integration)
|
14
14
|
self.base_api_url = "https://gmail.googleapis.com/gmail/v1/users/me"
|
15
15
|
|
16
|
-
def _get_headers(self):
|
17
|
-
if not self.integration:
|
18
|
-
raise ValueError("Integration not configured for GmailApp")
|
19
|
-
credentials = self.integration.get_credentials()
|
20
|
-
if not credentials:
|
21
|
-
logger.warning("No Gmail credentials found via integration.")
|
22
|
-
action = self.integration.authorize()
|
23
|
-
raise NotAuthorizedError(action)
|
24
|
-
|
25
|
-
if "headers" in credentials:
|
26
|
-
return credentials["headers"]
|
27
|
-
return {
|
28
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
29
|
-
"Content-Type": "application/json",
|
30
|
-
}
|
31
|
-
|
32
16
|
def send_email(self, to: str, subject: str, body: str) -> str:
|
33
17
|
"""
|
34
18
|
Sends an email using the Gmail API and returns a confirmation or error message.
|
@@ -1,9 +1,6 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
-
from loguru import logger
|
4
|
-
|
5
3
|
from universal_mcp.applications.application import APIApplication
|
6
|
-
from universal_mcp.exceptions import NotAuthorizedError
|
7
4
|
from universal_mcp.integrations import Integration
|
8
5
|
|
9
6
|
|
@@ -17,21 +14,6 @@ class GoogleSheetApp(APIApplication):
|
|
17
14
|
super().__init__(name="google-sheet", integration=integration)
|
18
15
|
self.base_api_url = "https://sheets.googleapis.com/v4/spreadsheets"
|
19
16
|
|
20
|
-
def _get_headers(self):
|
21
|
-
if not self.integration:
|
22
|
-
raise ValueError("Integration not configured for GoogleSheetsApp")
|
23
|
-
credentials = self.integration.get_credentials()
|
24
|
-
if not credentials:
|
25
|
-
logger.warning("No Google credentials found via integration.")
|
26
|
-
action = self.integration.authorize()
|
27
|
-
raise NotAuthorizedError(action)
|
28
|
-
if "headers" in credentials:
|
29
|
-
return credentials["headers"]
|
30
|
-
return {
|
31
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
32
|
-
"Content-Type": "application/json",
|
33
|
-
}
|
34
|
-
|
35
17
|
def create_spreadsheet(self, title: str) -> dict[str, Any]:
|
36
18
|
"""
|
37
19
|
Creates a new blank Google Spreadsheet with the specified title and returns the API response.
|
@@ -1,7 +1,5 @@
|
|
1
1
|
from typing import Any, Literal
|
2
2
|
|
3
|
-
from loguru import logger
|
4
|
-
|
5
3
|
from universal_mcp.applications.application import APIApplication
|
6
4
|
from universal_mcp.integrations import Integration
|
7
5
|
|
@@ -12,38 +10,6 @@ class PerplexityApp(APIApplication):
|
|
12
10
|
self.api_key: str | None = None
|
13
11
|
self.base_url = "https://api.perplexity.ai"
|
14
12
|
|
15
|
-
def _set_api_key(self):
|
16
|
-
if self.api_key:
|
17
|
-
return
|
18
|
-
|
19
|
-
if not self.integration:
|
20
|
-
raise ValueError("Integration is None. Cannot retrieve Perplexity API Key.")
|
21
|
-
|
22
|
-
credentials = self.integration.get_credentials()
|
23
|
-
if not credentials:
|
24
|
-
raise ValueError(
|
25
|
-
f"Failed to retrieve Perplexity API Key using integration '{self.integration.name}'. "
|
26
|
-
)
|
27
|
-
api_key = (
|
28
|
-
credentials.get("api_key")
|
29
|
-
or credentials.get("API_KEY")
|
30
|
-
or credentials.get("apiKey")
|
31
|
-
)
|
32
|
-
if not api_key:
|
33
|
-
raise ValueError(
|
34
|
-
f"Invalid credential format received for Perplexity API Key via integration '{self.integration.name}'. "
|
35
|
-
)
|
36
|
-
self.api_key = api_key
|
37
|
-
|
38
|
-
def _get_headers(self) -> dict[str, str]:
|
39
|
-
self._set_api_key()
|
40
|
-
logger.debug(f"Perplexity API Key: {self.api_key}")
|
41
|
-
return {
|
42
|
-
"Authorization": f"Bearer {self.api_key}",
|
43
|
-
"Content-Type": "application/json",
|
44
|
-
"Accept": "application/json",
|
45
|
-
}
|
46
|
-
|
47
13
|
def chat(
|
48
14
|
self,
|
49
15
|
query: str,
|
@@ -5,24 +5,6 @@ from universal_mcp.integrations import Integration
|
|
5
5
|
class ResendApp(APIApplication):
|
6
6
|
def __init__(self, integration: Integration) -> None:
|
7
7
|
super().__init__(name="resend", integration=integration)
|
8
|
-
self.api_key = None
|
9
|
-
|
10
|
-
def _get_headers(self):
|
11
|
-
if not self.api_key:
|
12
|
-
credentials = self.integration.get_credentials()
|
13
|
-
if not credentials:
|
14
|
-
raise ValueError("No credentials found")
|
15
|
-
api_key = (
|
16
|
-
credentials.get("api_key")
|
17
|
-
or credentials.get("API_KEY")
|
18
|
-
or credentials.get("apiKey")
|
19
|
-
)
|
20
|
-
if not api_key:
|
21
|
-
raise ValueError("No API key found")
|
22
|
-
self.api_key = api_key
|
23
|
-
return {
|
24
|
-
"Authorization": f"Bearer {self.api_key}",
|
25
|
-
}
|
26
8
|
|
27
9
|
def send_email(self, to: str, subject: str, content: str) -> str:
|
28
10
|
"""
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import httpx
|
2
|
-
from loguru import logger
|
3
2
|
from serpapi import SerpApiClient as SerpApiSearch
|
4
3
|
|
5
4
|
from universal_mcp.applications.application import APIApplication
|
@@ -8,31 +7,6 @@ from universal_mcp.applications.application import APIApplication
|
|
8
7
|
class SerpapiApp(APIApplication):
|
9
8
|
def __init__(self, **kwargs):
|
10
9
|
super().__init__(name="serpapi", **kwargs)
|
11
|
-
self.api_key: str | None = None
|
12
|
-
|
13
|
-
def _set_api_key(self):
|
14
|
-
if self.api_key is not None:
|
15
|
-
return
|
16
|
-
if not self.integration:
|
17
|
-
raise ValueError("Integration is None. Cannot retrieve SERP API Key.")
|
18
|
-
|
19
|
-
credentials = self.integration.get_credentials()
|
20
|
-
if not credentials:
|
21
|
-
raise ValueError(
|
22
|
-
f"Failed to retrieve SERP API Key using integration '{self.integration.name}'. "
|
23
|
-
f"Check store configuration (e.g., ensure the correct environment variable is set)."
|
24
|
-
)
|
25
|
-
api_key = (
|
26
|
-
credentials.get("api_key")
|
27
|
-
or credentials.get("API_KEY")
|
28
|
-
or credentials.get("apiKey")
|
29
|
-
)
|
30
|
-
if not api_key:
|
31
|
-
raise ValueError(
|
32
|
-
f"Invalid credential format received for SERP API Key via integration '{self.integration.name}'. "
|
33
|
-
)
|
34
|
-
self.api_key = api_key
|
35
|
-
logger.info("SERP API Key successfully retrieved via integration.")
|
36
10
|
|
37
11
|
async def search(self, params: dict[str, any] = None) -> str:
|
38
12
|
"""
|
@@ -53,9 +27,9 @@ class SerpapiApp(APIApplication):
|
|
53
27
|
"""
|
54
28
|
if params is None:
|
55
29
|
params = {}
|
56
|
-
self.
|
30
|
+
api_key = self.integration.get_credentials().get("api_key")
|
57
31
|
params = {
|
58
|
-
"api_key":
|
32
|
+
"api_key": api_key,
|
59
33
|
"engine": "google_light", # Fastest engine by default
|
60
34
|
**params, # Include any additional parameters
|
61
35
|
}
|
@@ -7,25 +7,6 @@ class TavilyApp(APIApplication):
|
|
7
7
|
name = "tavily"
|
8
8
|
self.base_url = "https://api.tavily.com"
|
9
9
|
super().__init__(name=name, integration=integration)
|
10
|
-
self.api_key = None
|
11
|
-
|
12
|
-
def _get_headers(self):
|
13
|
-
if not self.api_key:
|
14
|
-
credentials = self.integration.get_credentials()
|
15
|
-
if not credentials:
|
16
|
-
raise ValueError("No credentials found")
|
17
|
-
api_key = (
|
18
|
-
credentials.get("api_key")
|
19
|
-
or credentials.get("API_KEY")
|
20
|
-
or credentials.get("apiKey")
|
21
|
-
)
|
22
|
-
if not api_key:
|
23
|
-
raise ValueError("No API key found")
|
24
|
-
self.api_key = api_key
|
25
|
-
return {
|
26
|
-
"Authorization": f"Bearer {self.api_key}",
|
27
|
-
"Content-Type": "application/json",
|
28
|
-
}
|
29
10
|
|
30
11
|
def search(self, query: str) -> str:
|
31
12
|
"""
|
@@ -44,7 +25,6 @@ class TavilyApp(APIApplication):
|
|
44
25
|
Tags:
|
45
26
|
search, ai, web, query, important, api-client, text-processing
|
46
27
|
"""
|
47
|
-
self.validate()
|
48
28
|
url = f"{self.base_url}/search"
|
49
29
|
payload = {
|
50
30
|
"query": query,
|
@@ -19,18 +19,6 @@ class WrikeApp(APIApplication):
|
|
19
19
|
super().__init__(name="wrike", integration=integration, **kwargs)
|
20
20
|
self.base_url = "https://www.wrike.com/api/v4"
|
21
21
|
|
22
|
-
def _get_headers(self):
|
23
|
-
if not self.integration:
|
24
|
-
raise ValueError("Integration not configured for WrikeApp")
|
25
|
-
credentials = self.integration.get_credentials()
|
26
|
-
|
27
|
-
if "headers" in credentials:
|
28
|
-
return credentials["headers"]
|
29
|
-
return {
|
30
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
31
|
-
"Content-Type": "application/json",
|
32
|
-
}
|
33
|
-
|
34
22
|
def get_contacts(self, deleted=None, fields=None, metadata=None) -> Any:
|
35
23
|
"""
|
36
24
|
Retrieves a list of contacts from the server, with optional filtering and field selection.
|
@@ -1,9 +1,6 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
-
from loguru import logger
|
4
|
-
|
5
3
|
from universal_mcp.applications import APIApplication
|
6
|
-
from universal_mcp.exceptions import NotAuthorizedError
|
7
4
|
from universal_mcp.integrations import Integration
|
8
5
|
|
9
6
|
|
@@ -22,21 +19,6 @@ class YoutubeApp(APIApplication):
|
|
22
19
|
super().__init__(name="youtube", integration=integration, **kwargs)
|
23
20
|
self.base_url = "https://www.googleapis.com/youtube/v3"
|
24
21
|
|
25
|
-
def _get_headers(self):
|
26
|
-
if not self.integration:
|
27
|
-
raise ValueError("Integration not configured for YoutubeApp")
|
28
|
-
credentials = self.integration.get_credentials()
|
29
|
-
if not credentials:
|
30
|
-
logger.warning("No Google credentials found via integration.")
|
31
|
-
action = self.integration.authorize()
|
32
|
-
raise NotAuthorizedError(action)
|
33
|
-
if "headers" in credentials:
|
34
|
-
return credentials["headers"]
|
35
|
-
return {
|
36
|
-
"Authorization": f"Bearer {credentials['access_token']}",
|
37
|
-
"Content-Type": "application/json",
|
38
|
-
}
|
39
|
-
|
40
22
|
def get_jobs_job_reports(
|
41
23
|
self,
|
42
24
|
jobId,
|
@@ -29,7 +29,10 @@ class AgentRIntegration(Integration):
|
|
29
29
|
"API key for AgentR is missing. Please visit https://agentr.dev to create an API key, then set it as AGENTR_API_KEY environment variable."
|
30
30
|
)
|
31
31
|
raise ValueError("AgentR API key required - get one at https://agentr.dev")
|
32
|
-
self.base_url = os.getenv("AGENTR_BASE_URL", "https://api.agentr.dev")
|
32
|
+
self.base_url = os.getenv("AGENTR_BASE_URL", "https://api.agentr.dev").rstrip(
|
33
|
+
"/"
|
34
|
+
)
|
35
|
+
self._credentials = None
|
33
36
|
|
34
37
|
def set_credentials(self, credentials: dict | None = None):
|
35
38
|
"""Set credentials for the integration.
|
@@ -43,9 +46,9 @@ class AgentRIntegration(Integration):
|
|
43
46
|
str: Authorization URL from authorize() method
|
44
47
|
"""
|
45
48
|
return self.authorize()
|
46
|
-
# raise NotImplementedError("AgentR Integration does not support setting credentials. Visit the authorize url to set credentials.")
|
47
49
|
|
48
|
-
|
50
|
+
@property
|
51
|
+
def credentials(self):
|
49
52
|
"""Get credentials for the integration from the AgentR API.
|
50
53
|
|
51
54
|
Makes API request to retrieve stored credentials for this integration.
|
@@ -57,16 +60,36 @@ class AgentRIntegration(Integration):
|
|
57
60
|
NotAuthorizedError: If credentials are not found (404 response)
|
58
61
|
HTTPError: For other API errors
|
59
62
|
"""
|
63
|
+
if self._credentials is not None:
|
64
|
+
return self._credentials
|
60
65
|
response = httpx.get(
|
61
66
|
f"{self.base_url}/api/{self.name}/credentials/",
|
62
67
|
headers={"accept": "application/json", "X-API-KEY": self.api_key},
|
63
68
|
)
|
64
69
|
if response.status_code == 404:
|
70
|
+
logger.warning(
|
71
|
+
f"No credentials found for {self.name}. Requesting authorization..."
|
72
|
+
)
|
65
73
|
action = self.authorize()
|
66
74
|
raise NotAuthorizedError(action)
|
67
75
|
response.raise_for_status()
|
68
76
|
data = response.json()
|
69
|
-
|
77
|
+
self._credentials = data
|
78
|
+
return self._credentials
|
79
|
+
|
80
|
+
def get_credentials(self):
|
81
|
+
"""Get credentials for the integration from the AgentR API.
|
82
|
+
|
83
|
+
Makes API request to retrieve stored credentials for this integration.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
dict: Credentials data from API response
|
87
|
+
|
88
|
+
Raises:
|
89
|
+
NotAuthorizedError: If credentials are not found (404 response)
|
90
|
+
HTTPError: For other API errors
|
91
|
+
"""
|
92
|
+
return self.credentials
|
70
93
|
|
71
94
|
def authorize(self):
|
72
95
|
"""Get authorization URL for the integration.
|
@@ -91,9 +91,22 @@ class ApiKeyIntegration(Integration):
|
|
91
91
|
"""
|
92
92
|
|
93
93
|
def __init__(self, name: str, store: BaseStore | None = None, **kwargs):
|
94
|
+
self.type = "api_key"
|
94
95
|
sanitized_name = sanitize_api_key_name(name)
|
95
96
|
super().__init__(sanitized_name, store, **kwargs)
|
96
97
|
logger.info(f"Initializing API Key Integration: {name} with store: {store}")
|
98
|
+
self._api_key: str | None = None
|
99
|
+
|
100
|
+
@property
|
101
|
+
def api_key(self) -> str | None:
|
102
|
+
if not self._api_key:
|
103
|
+
try:
|
104
|
+
credentials = self.store.get(self.name)
|
105
|
+
self.api_key = credentials
|
106
|
+
except KeyNotFoundError as e:
|
107
|
+
action = self.authorize()
|
108
|
+
raise NotAuthorizedError(action) from e
|
109
|
+
return self._api_key
|
97
110
|
|
98
111
|
def get_credentials(self) -> dict[str, str]:
|
99
112
|
"""Get API key credentials.
|
@@ -104,12 +117,7 @@ class ApiKeyIntegration(Integration):
|
|
104
117
|
Raises:
|
105
118
|
NotAuthorizedError: If API key is not found.
|
106
119
|
"""
|
107
|
-
|
108
|
-
credentials = self.store.get(self.name)
|
109
|
-
except KeyNotFoundError as e:
|
110
|
-
action = self.authorize()
|
111
|
-
raise NotAuthorizedError(action) from e
|
112
|
-
return {"api_key": credentials}
|
120
|
+
return {"api_key": self.api_key}
|
113
121
|
|
114
122
|
def set_credentials(self, credentials: dict[str, Any]) -> None:
|
115
123
|
"""Set API key credentials.
|
universal_mcp/servers/server.py
CHANGED
@@ -9,7 +9,6 @@ from loguru import logger
|
|
9
9
|
from mcp.server.fastmcp import FastMCP
|
10
10
|
from mcp.types import TextContent
|
11
11
|
|
12
|
-
from universal_mcp.analytics import analytics
|
13
12
|
from universal_mcp.applications import Application, app_from_slug
|
14
13
|
from universal_mcp.config import AppConfig, ServerConfig, StoreConfig
|
15
14
|
from universal_mcp.integrations import AgentRIntegration, integration_from_config
|
@@ -145,7 +144,6 @@ class LocalServer(BaseServer):
|
|
145
144
|
if app_config.integration
|
146
145
|
else None
|
147
146
|
)
|
148
|
-
analytics.track_app_loaded(app_config.name) # Track app loading
|
149
147
|
return app_from_slug(app_config.name)(integration=integration)
|
150
148
|
except Exception as e:
|
151
149
|
logger.error(f"Failed to load app {app_config.name}: {e}", exc_info=True)
|
@@ -221,7 +219,6 @@ class AgentRServer(BaseServer):
|
|
221
219
|
if app_config.integration
|
222
220
|
else None
|
223
221
|
)
|
224
|
-
analytics.track_app_loaded(app_config.name) # Track app loading
|
225
222
|
return app_from_slug(app_config.name)(integration=integration)
|
226
223
|
except Exception as e:
|
227
224
|
logger.error(f"Failed to load app {app_config.name}: {e}", exc_info=True)
|