agentr 0.1.3__py3-none-any.whl → 0.1.5__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.
- agentr/__init__.py +1 -1
- agentr/application.py +56 -56
- agentr/applications/github/app.py +55 -51
- agentr/applications/google_calendar/app.py +73 -73
- agentr/applications/google_mail/app.py +67 -67
- agentr/applications/reddit/app.py +29 -29
- agentr/applications/resend/app.py +43 -43
- agentr/applications/tavily/app.py +57 -57
- agentr/applications/zenquotes/app.py +20 -20
- agentr/cli.py +75 -58
- agentr/exceptions.py +5 -0
- agentr/integration.py +98 -91
- agentr/server.py +105 -105
- agentr/store.py +70 -70
- agentr/test.py +37 -37
- agentr/utils/openapi.py +184 -184
- agentr-0.1.5.dist-info/METADATA +160 -0
- agentr-0.1.5.dist-info/RECORD +23 -0
- agentr-0.1.5.dist-info/licenses/LICENSE +21 -0
- agentr-0.1.3.dist-info/METADATA +0 -10
- agentr-0.1.3.dist-info/RECORD +0 -21
- {agentr-0.1.3.dist-info → agentr-0.1.5.dist-info}/WHEEL +0 -0
- {agentr-0.1.3.dist-info → agentr-0.1.5.dist-info}/entry_points.txt +0 -0
agentr/server.py
CHANGED
@@ -1,105 +1,105 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import Literal
|
3
|
-
from mcp.server.fastmcp import FastMCP
|
4
|
-
from agentr.integration import AgentRIntegration, ApiKeyIntegration
|
5
|
-
from agentr.store import EnvironmentStore, MemoryStore
|
6
|
-
from pydantic import BaseModel
|
7
|
-
from loguru import logger
|
8
|
-
|
9
|
-
class StoreConfig(BaseModel):
|
10
|
-
type: Literal["memory", "environment"]
|
11
|
-
|
12
|
-
class IntegrationConfig(BaseModel):
|
13
|
-
name: str
|
14
|
-
type: Literal["api_key", "agentr"]
|
15
|
-
credentials: dict | None = None
|
16
|
-
store: StoreConfig | None = None
|
17
|
-
|
18
|
-
class AppConfig(BaseModel):
|
19
|
-
name: str
|
20
|
-
integration: IntegrationConfig | None = None
|
21
|
-
|
22
|
-
class Server(FastMCP, ABC):
|
23
|
-
"""
|
24
|
-
Server is responsible for managing the applications and the store
|
25
|
-
It also acts as a router for the applications, and exposed to the client
|
26
|
-
|
27
|
-
"""
|
28
|
-
def __init__(self, name: str, description: str, **kwargs):
|
29
|
-
super().__init__(name, description, **kwargs)
|
30
|
-
|
31
|
-
@abstractmethod
|
32
|
-
def _load_apps(self):
|
33
|
-
pass
|
34
|
-
|
35
|
-
|
36
|
-
class TestServer(Server):
|
37
|
-
"""
|
38
|
-
Test server for development purposes
|
39
|
-
"""
|
40
|
-
def __init__(self, name: str, description: str, apps_list: list[AppConfig] = [], **kwargs):
|
41
|
-
super().__init__(name, description=description, **kwargs)
|
42
|
-
self.apps_list = [AppConfig.model_validate(app) for app in apps_list]
|
43
|
-
self._load_apps()
|
44
|
-
|
45
|
-
def _get_store(self, store_config: StoreConfig):
|
46
|
-
if store_config.type == "memory":
|
47
|
-
return MemoryStore()
|
48
|
-
elif store_config.type == "environment":
|
49
|
-
return EnvironmentStore()
|
50
|
-
return None
|
51
|
-
|
52
|
-
def _get_integration(self, integration_config: IntegrationConfig):
|
53
|
-
if integration_config.type == "api_key":
|
54
|
-
store = self._get_store(integration_config.store)
|
55
|
-
integration = ApiKeyIntegration(integration_config.name, store=store)
|
56
|
-
if integration_config.credentials:
|
57
|
-
integration.set_credentials(integration_config.credentials)
|
58
|
-
return integration
|
59
|
-
elif integration_config.type == "agentr":
|
60
|
-
integration = AgentRIntegration(integration_config.name, api_key=integration_config.credentials.get("api_key") if integration_config.credentials else None)
|
61
|
-
return integration
|
62
|
-
return None
|
63
|
-
|
64
|
-
def _load_app(self, app_config: AppConfig):
|
65
|
-
name = app_config.name
|
66
|
-
if name == "zenquotes":
|
67
|
-
from agentr.applications.zenquotes.app import ZenQuoteApp
|
68
|
-
return ZenQuoteApp()
|
69
|
-
elif name == "tavily":
|
70
|
-
from agentr.applications.tavily.app import TavilyApp
|
71
|
-
integration = self._get_integration(app_config.integration)
|
72
|
-
return TavilyApp(integration=integration)
|
73
|
-
elif name == "github":
|
74
|
-
from agentr.applications.github.app import GithubApp
|
75
|
-
integration = self._get_integration(app_config.integration)
|
76
|
-
return GithubApp(integration=integration)
|
77
|
-
elif name == "google-calendar":
|
78
|
-
from agentr.applications.google_calendar.app import GoogleCalendarApp
|
79
|
-
integration = self._get_integration(app_config.integration)
|
80
|
-
return GoogleCalendarApp(integration=integration)
|
81
|
-
elif name == "gmail":
|
82
|
-
from agentr.applications.google_mail.app import GmailApp
|
83
|
-
integration = self._get_integration(app_config.integration)
|
84
|
-
return GmailApp(integration=integration)
|
85
|
-
elif name == "resend":
|
86
|
-
from agentr.applications.resend.app import ResendApp
|
87
|
-
integration = self._get_integration(app_config.integration)
|
88
|
-
return ResendApp(integration=integration)
|
89
|
-
elif name == "reddit":
|
90
|
-
from agentr.applications.reddit.app import RedditApp
|
91
|
-
integration = self._get_integration(app_config.integration)
|
92
|
-
return RedditApp(integration=integration)
|
93
|
-
else:
|
94
|
-
return None
|
95
|
-
|
96
|
-
def _load_apps(self):
|
97
|
-
logger.info(f"Loading apps: {self.apps_list}")
|
98
|
-
for app_config in self.apps_list:
|
99
|
-
app = self._load_app(app_config)
|
100
|
-
if app:
|
101
|
-
tools = app.list_tools()
|
102
|
-
for tool in tools:
|
103
|
-
self.add_tool(tool)
|
104
|
-
|
105
|
-
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Literal
|
3
|
+
from mcp.server.fastmcp import FastMCP
|
4
|
+
from agentr.integration import AgentRIntegration, ApiKeyIntegration
|
5
|
+
from agentr.store import EnvironmentStore, MemoryStore
|
6
|
+
from pydantic import BaseModel
|
7
|
+
from loguru import logger
|
8
|
+
|
9
|
+
class StoreConfig(BaseModel):
|
10
|
+
type: Literal["memory", "environment"]
|
11
|
+
|
12
|
+
class IntegrationConfig(BaseModel):
|
13
|
+
name: str
|
14
|
+
type: Literal["api_key", "agentr"]
|
15
|
+
credentials: dict | None = None
|
16
|
+
store: StoreConfig | None = None
|
17
|
+
|
18
|
+
class AppConfig(BaseModel):
|
19
|
+
name: str
|
20
|
+
integration: IntegrationConfig | None = None
|
21
|
+
|
22
|
+
class Server(FastMCP, ABC):
|
23
|
+
"""
|
24
|
+
Server is responsible for managing the applications and the store
|
25
|
+
It also acts as a router for the applications, and exposed to the client
|
26
|
+
|
27
|
+
"""
|
28
|
+
def __init__(self, name: str, description: str, **kwargs):
|
29
|
+
super().__init__(name, description, **kwargs)
|
30
|
+
|
31
|
+
@abstractmethod
|
32
|
+
def _load_apps(self):
|
33
|
+
pass
|
34
|
+
|
35
|
+
|
36
|
+
class TestServer(Server):
|
37
|
+
"""
|
38
|
+
Test server for development purposes
|
39
|
+
"""
|
40
|
+
def __init__(self, name: str, description: str, apps_list: list[AppConfig] = [], **kwargs):
|
41
|
+
super().__init__(name, description=description, **kwargs)
|
42
|
+
self.apps_list = [AppConfig.model_validate(app) for app in apps_list]
|
43
|
+
self._load_apps()
|
44
|
+
|
45
|
+
def _get_store(self, store_config: StoreConfig):
|
46
|
+
if store_config.type == "memory":
|
47
|
+
return MemoryStore()
|
48
|
+
elif store_config.type == "environment":
|
49
|
+
return EnvironmentStore()
|
50
|
+
return None
|
51
|
+
|
52
|
+
def _get_integration(self, integration_config: IntegrationConfig):
|
53
|
+
if integration_config.type == "api_key":
|
54
|
+
store = self._get_store(integration_config.store)
|
55
|
+
integration = ApiKeyIntegration(integration_config.name, store=store)
|
56
|
+
if integration_config.credentials:
|
57
|
+
integration.set_credentials(integration_config.credentials)
|
58
|
+
return integration
|
59
|
+
elif integration_config.type == "agentr":
|
60
|
+
integration = AgentRIntegration(integration_config.name, api_key=integration_config.credentials.get("api_key") if integration_config.credentials else None)
|
61
|
+
return integration
|
62
|
+
return None
|
63
|
+
|
64
|
+
def _load_app(self, app_config: AppConfig):
|
65
|
+
name = app_config.name
|
66
|
+
if name == "zenquotes":
|
67
|
+
from agentr.applications.zenquotes.app import ZenQuoteApp
|
68
|
+
return ZenQuoteApp()
|
69
|
+
elif name == "tavily":
|
70
|
+
from agentr.applications.tavily.app import TavilyApp
|
71
|
+
integration = self._get_integration(app_config.integration)
|
72
|
+
return TavilyApp(integration=integration)
|
73
|
+
elif name == "github":
|
74
|
+
from agentr.applications.github.app import GithubApp
|
75
|
+
integration = self._get_integration(app_config.integration)
|
76
|
+
return GithubApp(integration=integration)
|
77
|
+
elif name == "google-calendar":
|
78
|
+
from agentr.applications.google_calendar.app import GoogleCalendarApp
|
79
|
+
integration = self._get_integration(app_config.integration)
|
80
|
+
return GoogleCalendarApp(integration=integration)
|
81
|
+
elif name == "gmail":
|
82
|
+
from agentr.applications.google_mail.app import GmailApp
|
83
|
+
integration = self._get_integration(app_config.integration)
|
84
|
+
return GmailApp(integration=integration)
|
85
|
+
elif name == "resend":
|
86
|
+
from agentr.applications.resend.app import ResendApp
|
87
|
+
integration = self._get_integration(app_config.integration)
|
88
|
+
return ResendApp(integration=integration)
|
89
|
+
elif name == "reddit":
|
90
|
+
from agentr.applications.reddit.app import RedditApp
|
91
|
+
integration = self._get_integration(app_config.integration)
|
92
|
+
return RedditApp(integration=integration)
|
93
|
+
else:
|
94
|
+
return None
|
95
|
+
|
96
|
+
def _load_apps(self):
|
97
|
+
logger.info(f"Loading apps: {self.apps_list}")
|
98
|
+
for app_config in self.apps_list:
|
99
|
+
app = self._load_app(app_config)
|
100
|
+
if app:
|
101
|
+
tools = app.list_tools()
|
102
|
+
for tool in tools:
|
103
|
+
self.add_tool(tool)
|
104
|
+
|
105
|
+
|
agentr/store.py
CHANGED
@@ -1,71 +1,71 @@
|
|
1
|
-
import os
|
2
|
-
from abc import ABC, abstractmethod
|
3
|
-
|
4
|
-
|
5
|
-
class Store(ABC):
|
6
|
-
@abstractmethod
|
7
|
-
def get(self, key: str):
|
8
|
-
pass
|
9
|
-
|
10
|
-
@abstractmethod
|
11
|
-
def set(self, key: str, value: str):
|
12
|
-
pass
|
13
|
-
|
14
|
-
@abstractmethod
|
15
|
-
def delete(self, key: str):
|
16
|
-
pass
|
17
|
-
|
18
|
-
class MemoryStore:
|
19
|
-
"""
|
20
|
-
Acts as credential store for the applications.
|
21
|
-
Responsible for storing and retrieving credentials.
|
22
|
-
Ideally should be a key value store
|
23
|
-
"""
|
24
|
-
def __init__(self):
|
25
|
-
self.data = {}
|
26
|
-
|
27
|
-
def get(self, key: str):
|
28
|
-
return self.data.get(key)
|
29
|
-
|
30
|
-
def set(self, key: str, value: str):
|
31
|
-
self.data[key] = value
|
32
|
-
|
33
|
-
def delete(self, key: str):
|
34
|
-
del self.data[key]
|
35
|
-
|
36
|
-
|
37
|
-
class EnvironmentStore(Store):
|
38
|
-
"""
|
39
|
-
Store that uses environment variables to store credentials.
|
40
|
-
"""
|
41
|
-
def __init__(self):
|
42
|
-
pass
|
43
|
-
|
44
|
-
def get(self, key: str):
|
45
|
-
return {"api_key": os.getenv(key)}
|
46
|
-
|
47
|
-
def set(self, key: str, value: str):
|
48
|
-
os.environ[key] = value
|
49
|
-
|
50
|
-
def delete(self, key: str):
|
51
|
-
del os.environ[key]
|
52
|
-
|
53
|
-
class RedisStore(Store):
|
54
|
-
"""
|
55
|
-
Store that uses a redis database to store credentials.
|
56
|
-
"""
|
57
|
-
def __init__(self, host: str, port: int, db: int):
|
58
|
-
import redis
|
59
|
-
self.host = host
|
60
|
-
self.port = port
|
61
|
-
self.db = db
|
62
|
-
self.redis = redis.Redis(host=self.host, port=self.port, db=self.db)
|
63
|
-
|
64
|
-
def get(self, key: str):
|
65
|
-
return self.redis.get(key)
|
66
|
-
|
67
|
-
def set(self, key: str, value: str):
|
68
|
-
self.redis.set(key, value)
|
69
|
-
|
70
|
-
def delete(self, key: str):
|
1
|
+
import os
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
|
4
|
+
|
5
|
+
class Store(ABC):
|
6
|
+
@abstractmethod
|
7
|
+
def get(self, key: str):
|
8
|
+
pass
|
9
|
+
|
10
|
+
@abstractmethod
|
11
|
+
def set(self, key: str, value: str):
|
12
|
+
pass
|
13
|
+
|
14
|
+
@abstractmethod
|
15
|
+
def delete(self, key: str):
|
16
|
+
pass
|
17
|
+
|
18
|
+
class MemoryStore:
|
19
|
+
"""
|
20
|
+
Acts as credential store for the applications.
|
21
|
+
Responsible for storing and retrieving credentials.
|
22
|
+
Ideally should be a key value store
|
23
|
+
"""
|
24
|
+
def __init__(self):
|
25
|
+
self.data = {}
|
26
|
+
|
27
|
+
def get(self, key: str):
|
28
|
+
return self.data.get(key)
|
29
|
+
|
30
|
+
def set(self, key: str, value: str):
|
31
|
+
self.data[key] = value
|
32
|
+
|
33
|
+
def delete(self, key: str):
|
34
|
+
del self.data[key]
|
35
|
+
|
36
|
+
|
37
|
+
class EnvironmentStore(Store):
|
38
|
+
"""
|
39
|
+
Store that uses environment variables to store credentials.
|
40
|
+
"""
|
41
|
+
def __init__(self):
|
42
|
+
pass
|
43
|
+
|
44
|
+
def get(self, key: str):
|
45
|
+
return {"api_key": os.getenv(key)}
|
46
|
+
|
47
|
+
def set(self, key: str, value: str):
|
48
|
+
os.environ[key] = value
|
49
|
+
|
50
|
+
def delete(self, key: str):
|
51
|
+
del os.environ[key]
|
52
|
+
|
53
|
+
class RedisStore(Store):
|
54
|
+
"""
|
55
|
+
Store that uses a redis database to store credentials.
|
56
|
+
"""
|
57
|
+
def __init__(self, host: str, port: int, db: int):
|
58
|
+
import redis
|
59
|
+
self.host = host
|
60
|
+
self.port = port
|
61
|
+
self.db = db
|
62
|
+
self.redis = redis.Redis(host=self.host, port=self.port, db=self.db)
|
63
|
+
|
64
|
+
def get(self, key: str):
|
65
|
+
return self.redis.get(key)
|
66
|
+
|
67
|
+
def set(self, key: str, value: str):
|
68
|
+
self.redis.set(key, value)
|
69
|
+
|
70
|
+
def delete(self, key: str):
|
71
71
|
self.redis.delete(key)
|
agentr/test.py
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
-
from agentr.server import TestServer
|
2
|
-
from agentr.store import MemoryStore
|
3
|
-
|
4
|
-
store = MemoryStore()
|
5
|
-
apps_list = [
|
6
|
-
{
|
7
|
-
"name": "tavily",
|
8
|
-
"integration": {
|
9
|
-
"name": "tavily_api_key",
|
10
|
-
"type": "api_key",
|
11
|
-
"store": {
|
12
|
-
"type": "environment",
|
13
|
-
}
|
14
|
-
},
|
15
|
-
},
|
16
|
-
{
|
17
|
-
"name": "zenquotes",
|
18
|
-
"integration": None
|
19
|
-
},
|
20
|
-
{
|
21
|
-
"name": "github",
|
22
|
-
"integration": {
|
23
|
-
"name": "github",
|
24
|
-
"type": "agentr",
|
25
|
-
}
|
26
|
-
}
|
27
|
-
]
|
28
|
-
mcp = TestServer(name="Test Server", description="Test Server", apps_list=apps_list)
|
29
|
-
|
30
|
-
async def test():
|
31
|
-
tools = await mcp.list_tools()
|
32
|
-
print(tools)
|
33
|
-
result = await mcp.call_tool("
|
34
|
-
print(result)
|
35
|
-
|
36
|
-
if __name__ == "__main__":
|
37
|
-
import asyncio
|
1
|
+
from agentr.server import TestServer
|
2
|
+
from agentr.store import MemoryStore
|
3
|
+
|
4
|
+
store = MemoryStore()
|
5
|
+
apps_list = [
|
6
|
+
{
|
7
|
+
"name": "tavily",
|
8
|
+
"integration": {
|
9
|
+
"name": "tavily_api_key",
|
10
|
+
"type": "api_key",
|
11
|
+
"store": {
|
12
|
+
"type": "environment",
|
13
|
+
}
|
14
|
+
},
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"name": "zenquotes",
|
18
|
+
"integration": None
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"name": "github",
|
22
|
+
"integration": {
|
23
|
+
"name": "github",
|
24
|
+
"type": "agentr",
|
25
|
+
}
|
26
|
+
}
|
27
|
+
]
|
28
|
+
mcp = TestServer(name="Test Server", description="Test Server", apps_list=apps_list)
|
29
|
+
|
30
|
+
async def test():
|
31
|
+
tools = await mcp.list_tools()
|
32
|
+
print(tools)
|
33
|
+
result = await mcp.call_tool("star_repository", {"repo_full_name": "manojbajaj95/config"})
|
34
|
+
print(result)
|
35
|
+
|
36
|
+
if __name__ == "__main__":
|
37
|
+
import asyncio
|
38
38
|
asyncio.run(test())
|