agno 2.3.16__py3-none-any.whl → 2.3.18__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.
- agno/agent/__init__.py +2 -0
- agno/agent/agent.py +4 -53
- agno/agent/remote.py +351 -0
- agno/client/__init__.py +3 -0
- agno/client/os.py +2669 -0
- agno/db/base.py +20 -0
- agno/db/mongo/async_mongo.py +11 -0
- agno/db/mongo/mongo.py +10 -0
- agno/db/mysql/async_mysql.py +9 -0
- agno/db/mysql/mysql.py +9 -0
- agno/db/postgres/async_postgres.py +9 -0
- agno/db/postgres/postgres.py +9 -0
- agno/db/postgres/utils.py +3 -2
- agno/db/sqlite/async_sqlite.py +9 -0
- agno/db/sqlite/sqlite.py +11 -1
- agno/exceptions.py +23 -0
- agno/knowledge/chunking/semantic.py +123 -46
- agno/knowledge/reader/csv_reader.py +1 -1
- agno/knowledge/reader/field_labeled_csv_reader.py +1 -1
- agno/knowledge/reader/json_reader.py +1 -1
- agno/models/google/gemini.py +5 -0
- agno/os/app.py +108 -25
- agno/os/auth.py +25 -1
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +13 -13
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +23 -16
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +6 -6
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +29 -6
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +651 -79
- agno/os/router.py +125 -18
- agno/os/routers/agents/router.py +65 -22
- agno/os/routers/agents/schema.py +16 -4
- agno/os/routers/database.py +5 -0
- agno/os/routers/evals/evals.py +93 -11
- agno/os/routers/evals/utils.py +6 -6
- agno/os/routers/knowledge/knowledge.py +104 -16
- agno/os/routers/memory/memory.py +124 -7
- agno/os/routers/metrics/metrics.py +21 -4
- agno/os/routers/session/session.py +141 -12
- agno/os/routers/teams/router.py +40 -14
- agno/os/routers/teams/schema.py +12 -4
- agno/os/routers/traces/traces.py +54 -4
- agno/os/routers/workflows/router.py +223 -117
- agno/os/routers/workflows/schema.py +65 -1
- agno/os/schema.py +38 -12
- agno/os/utils.py +87 -166
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +484 -0
- agno/run/workflow.py +1 -0
- agno/team/__init__.py +2 -0
- agno/team/remote.py +287 -0
- agno/team/team.py +25 -54
- agno/tracing/exporter.py +10 -6
- agno/tracing/setup.py +2 -1
- agno/utils/agent.py +58 -1
- agno/utils/http.py +68 -20
- agno/utils/os.py +0 -0
- agno/utils/remote.py +23 -0
- agno/vectordb/chroma/chromadb.py +452 -16
- agno/vectordb/pgvector/pgvector.py +7 -0
- agno/vectordb/redis/redisdb.py +1 -1
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +2 -2
- agno/workflow/remote.py +222 -0
- agno/workflow/types.py +0 -73
- agno/workflow/workflow.py +119 -68
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/METADATA +1 -1
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/RECORD +76 -66
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/WHEEL +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/top_level.txt +0 -0
agno/os/mcp.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Router for MCP interface providing Model Context Protocol endpoints."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import TYPE_CHECKING, List, Optional, cast
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, cast
|
|
5
5
|
from uuid import uuid4
|
|
6
6
|
|
|
7
7
|
from fastmcp import FastMCP
|
|
@@ -9,17 +9,23 @@ from fastmcp.server.http import (
|
|
|
9
9
|
StarletteWithLifespan,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
from agno.db.base import AsyncBaseDb, SessionType
|
|
12
|
+
from agno.db.base import AsyncBaseDb, BaseDb, SessionType
|
|
13
13
|
from agno.db.schemas import UserMemory
|
|
14
14
|
from agno.os.routers.memory.schemas import (
|
|
15
15
|
UserMemorySchema,
|
|
16
16
|
)
|
|
17
17
|
from agno.os.schema import (
|
|
18
|
+
AgentSessionDetailSchema,
|
|
18
19
|
AgentSummaryResponse,
|
|
19
20
|
ConfigResponse,
|
|
20
21
|
InterfaceResponse,
|
|
22
|
+
RunSchema,
|
|
21
23
|
SessionSchema,
|
|
24
|
+
TeamRunSchema,
|
|
25
|
+
TeamSessionDetailSchema,
|
|
22
26
|
TeamSummaryResponse,
|
|
27
|
+
WorkflowRunSchema,
|
|
28
|
+
WorkflowSessionDetailSchema,
|
|
23
29
|
WorkflowSummaryResponse,
|
|
24
30
|
)
|
|
25
31
|
from agno.os.utils import (
|
|
@@ -28,9 +34,11 @@ from agno.os.utils import (
|
|
|
28
34
|
get_team_by_id,
|
|
29
35
|
get_workflow_by_id,
|
|
30
36
|
)
|
|
37
|
+
from agno.remote.base import RemoteDb
|
|
31
38
|
from agno.run.agent import RunOutput
|
|
32
39
|
from agno.run.team import TeamRunOutput
|
|
33
40
|
from agno.run.workflow import WorkflowRunOutput
|
|
41
|
+
from agno.session import AgentSession, TeamSession, WorkflowSession
|
|
34
42
|
|
|
35
43
|
if TYPE_CHECKING:
|
|
36
44
|
from agno.os.app import AgentOS
|
|
@@ -74,128 +82,531 @@ def get_mcp_server(
|
|
|
74
82
|
],
|
|
75
83
|
)
|
|
76
84
|
|
|
77
|
-
|
|
85
|
+
# ==================== Core Run Tools ====================
|
|
86
|
+
|
|
87
|
+
@mcp.tool(name="run_agent", description="Run an agent with a message", tags={"core"}) # type: ignore
|
|
78
88
|
async def run_agent(agent_id: str, message: str) -> RunOutput:
|
|
79
89
|
agent = get_agent_by_id(agent_id, os.agents)
|
|
80
90
|
if agent is None:
|
|
81
91
|
raise Exception(f"Agent {agent_id} not found")
|
|
82
92
|
return await agent.arun(message)
|
|
83
93
|
|
|
84
|
-
@mcp.tool(name="run_team", description="Run a team", tags={"core"}) # type: ignore
|
|
94
|
+
@mcp.tool(name="run_team", description="Run a team with a message", tags={"core"}) # type: ignore
|
|
85
95
|
async def run_team(team_id: str, message: str) -> TeamRunOutput:
|
|
86
96
|
team = get_team_by_id(team_id, os.teams)
|
|
87
97
|
if team is None:
|
|
88
98
|
raise Exception(f"Team {team_id} not found")
|
|
89
99
|
return await team.arun(message)
|
|
90
100
|
|
|
91
|
-
@mcp.tool(name="run_workflow", description="Run a workflow", tags={"core"}) # type: ignore
|
|
101
|
+
@mcp.tool(name="run_workflow", description="Run a workflow with a message", tags={"core"}) # type: ignore
|
|
92
102
|
async def run_workflow(workflow_id: str, message: str) -> WorkflowRunOutput:
|
|
93
103
|
workflow = get_workflow_by_id(workflow_id, os.workflows)
|
|
94
104
|
if workflow is None:
|
|
95
105
|
raise Exception(f"Workflow {workflow_id} not found")
|
|
96
106
|
return await workflow.arun(message)
|
|
97
107
|
|
|
98
|
-
# Session Management Tools
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
108
|
+
# ==================== Session Management Tools ====================
|
|
109
|
+
|
|
110
|
+
@mcp.tool(
|
|
111
|
+
name="get_sessions",
|
|
112
|
+
description="Get paginated list of sessions with optional filtering by type, component, user, and name",
|
|
113
|
+
tags={"session"},
|
|
114
|
+
) # type: ignore
|
|
115
|
+
async def get_sessions(
|
|
102
116
|
db_id: str,
|
|
117
|
+
session_type: str = "agent",
|
|
118
|
+
component_id: Optional[str] = None,
|
|
103
119
|
user_id: Optional[str] = None,
|
|
120
|
+
session_name: Optional[str] = None,
|
|
121
|
+
limit: int = 20,
|
|
122
|
+
page: int = 1,
|
|
104
123
|
sort_by: str = "created_at",
|
|
105
124
|
sort_order: str = "desc",
|
|
106
|
-
):
|
|
125
|
+
) -> Dict[str, Any]:
|
|
107
126
|
db = await get_db(os.dbs, db_id)
|
|
127
|
+
session_type_enum = SessionType(session_type)
|
|
128
|
+
if isinstance(db, RemoteDb):
|
|
129
|
+
result = await db.get_sessions(
|
|
130
|
+
session_type=session_type_enum,
|
|
131
|
+
component_id=component_id,
|
|
132
|
+
user_id=user_id,
|
|
133
|
+
session_name=session_name,
|
|
134
|
+
limit=limit,
|
|
135
|
+
page=page,
|
|
136
|
+
sort_by=sort_by,
|
|
137
|
+
sort_order=sort_order,
|
|
138
|
+
db_id=db_id,
|
|
139
|
+
)
|
|
140
|
+
return result.model_dump()
|
|
141
|
+
|
|
108
142
|
if isinstance(db, AsyncBaseDb):
|
|
109
143
|
db = cast(AsyncBaseDb, db)
|
|
110
|
-
sessions = await db.get_sessions(
|
|
111
|
-
session_type=
|
|
112
|
-
component_id=
|
|
144
|
+
sessions, total_count = await db.get_sessions(
|
|
145
|
+
session_type=session_type_enum,
|
|
146
|
+
component_id=component_id,
|
|
113
147
|
user_id=user_id,
|
|
148
|
+
session_name=session_name,
|
|
149
|
+
limit=limit,
|
|
150
|
+
page=page,
|
|
114
151
|
sort_by=sort_by,
|
|
115
152
|
sort_order=sort_order,
|
|
116
153
|
deserialize=False,
|
|
117
154
|
)
|
|
118
155
|
else:
|
|
119
|
-
sessions = db.get_sessions(
|
|
120
|
-
session_type=
|
|
121
|
-
component_id=
|
|
156
|
+
sessions, total_count = db.get_sessions(
|
|
157
|
+
session_type=session_type_enum,
|
|
158
|
+
component_id=component_id,
|
|
122
159
|
user_id=user_id,
|
|
160
|
+
session_name=session_name,
|
|
161
|
+
limit=limit,
|
|
162
|
+
page=page,
|
|
123
163
|
sort_by=sort_by,
|
|
124
164
|
sort_order=sort_order,
|
|
125
165
|
deserialize=False,
|
|
126
166
|
)
|
|
127
167
|
|
|
128
168
|
return {
|
|
129
|
-
"data": [SessionSchema.from_dict(session) for session in sessions], # type: ignore
|
|
169
|
+
"data": [SessionSchema.from_dict(session).model_dump() for session in sessions], # type: ignore
|
|
170
|
+
"meta": {
|
|
171
|
+
"page": page,
|
|
172
|
+
"limit": limit,
|
|
173
|
+
"total_count": total_count,
|
|
174
|
+
"total_pages": (total_count + limit - 1) // limit if limit > 0 else 0, # type: ignore
|
|
175
|
+
},
|
|
130
176
|
}
|
|
131
177
|
|
|
132
|
-
@mcp.tool(
|
|
133
|
-
|
|
134
|
-
|
|
178
|
+
@mcp.tool(
|
|
179
|
+
name="get_session",
|
|
180
|
+
description="Get detailed information about a specific session by ID",
|
|
181
|
+
tags={"session"},
|
|
182
|
+
) # type: ignore
|
|
183
|
+
async def get_session(
|
|
184
|
+
session_id: str,
|
|
135
185
|
db_id: str,
|
|
186
|
+
session_type: str = "agent",
|
|
136
187
|
user_id: Optional[str] = None,
|
|
137
|
-
|
|
138
|
-
sort_order: str = "desc",
|
|
139
|
-
):
|
|
188
|
+
) -> Dict[str, Any]:
|
|
140
189
|
db = await get_db(os.dbs, db_id)
|
|
190
|
+
session_type_enum = SessionType(session_type)
|
|
191
|
+
|
|
192
|
+
if isinstance(db, RemoteDb):
|
|
193
|
+
result = await db.get_session(
|
|
194
|
+
session_id=session_id,
|
|
195
|
+
session_type=session_type_enum,
|
|
196
|
+
user_id=user_id,
|
|
197
|
+
db_id=db_id,
|
|
198
|
+
)
|
|
199
|
+
return result.model_dump()
|
|
200
|
+
|
|
141
201
|
if isinstance(db, AsyncBaseDb):
|
|
142
202
|
db = cast(AsyncBaseDb, db)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
203
|
+
session = await db.get_session(session_id=session_id, session_type=session_type_enum, user_id=user_id)
|
|
204
|
+
else:
|
|
205
|
+
db = cast(BaseDb, db)
|
|
206
|
+
session = db.get_session(session_id=session_id, session_type=session_type_enum, user_id=user_id)
|
|
207
|
+
|
|
208
|
+
if not session:
|
|
209
|
+
raise Exception(f"Session {session_id} not found")
|
|
210
|
+
|
|
211
|
+
if session_type_enum == SessionType.AGENT:
|
|
212
|
+
return AgentSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
213
|
+
elif session_type_enum == SessionType.TEAM:
|
|
214
|
+
return TeamSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
215
|
+
else:
|
|
216
|
+
return WorkflowSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
217
|
+
|
|
218
|
+
@mcp.tool(
|
|
219
|
+
name="create_session",
|
|
220
|
+
description="Create a new session for an agent, team, or workflow",
|
|
221
|
+
tags={"session"},
|
|
222
|
+
) # type: ignore
|
|
223
|
+
async def create_session(
|
|
224
|
+
db_id: str,
|
|
225
|
+
session_type: str = "agent",
|
|
226
|
+
session_id: Optional[str] = None,
|
|
227
|
+
session_name: Optional[str] = None,
|
|
228
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
229
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
230
|
+
user_id: Optional[str] = None,
|
|
231
|
+
agent_id: Optional[str] = None,
|
|
232
|
+
team_id: Optional[str] = None,
|
|
233
|
+
workflow_id: Optional[str] = None,
|
|
234
|
+
) -> Dict[str, Any]:
|
|
235
|
+
import time
|
|
236
|
+
|
|
237
|
+
db = await get_db(os.dbs, db_id)
|
|
238
|
+
session_type_enum = SessionType(session_type)
|
|
239
|
+
|
|
240
|
+
# Generate session_id if not provided
|
|
241
|
+
session_id = session_id or str(uuid4())
|
|
242
|
+
|
|
243
|
+
if isinstance(db, RemoteDb):
|
|
244
|
+
result = await db.create_session(
|
|
245
|
+
session_type=session_type_enum,
|
|
246
|
+
session_id=session_id,
|
|
247
|
+
session_name=session_name,
|
|
248
|
+
session_state=session_state,
|
|
249
|
+
metadata=metadata,
|
|
146
250
|
user_id=user_id,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
251
|
+
agent_id=agent_id,
|
|
252
|
+
team_id=team_id,
|
|
253
|
+
workflow_id=workflow_id,
|
|
254
|
+
db_id=db_id,
|
|
255
|
+
)
|
|
256
|
+
return result.model_dump()
|
|
257
|
+
|
|
258
|
+
# Prepare session_data
|
|
259
|
+
session_data: Dict[str, Any] = {}
|
|
260
|
+
if session_state is not None:
|
|
261
|
+
session_data["session_state"] = session_state
|
|
262
|
+
if session_name is not None:
|
|
263
|
+
session_data["session_name"] = session_name
|
|
264
|
+
|
|
265
|
+
current_time = int(time.time())
|
|
266
|
+
|
|
267
|
+
# Create the appropriate session type
|
|
268
|
+
session: Union[AgentSession, TeamSession, WorkflowSession]
|
|
269
|
+
if session_type_enum == SessionType.AGENT:
|
|
270
|
+
session = AgentSession(
|
|
271
|
+
session_id=session_id,
|
|
272
|
+
agent_id=agent_id,
|
|
273
|
+
user_id=user_id,
|
|
274
|
+
session_data=session_data if session_data else None,
|
|
275
|
+
metadata=metadata,
|
|
276
|
+
created_at=current_time,
|
|
277
|
+
updated_at=current_time,
|
|
278
|
+
)
|
|
279
|
+
elif session_type_enum == SessionType.TEAM:
|
|
280
|
+
session = TeamSession(
|
|
281
|
+
session_id=session_id,
|
|
282
|
+
team_id=team_id,
|
|
283
|
+
user_id=user_id,
|
|
284
|
+
session_data=session_data if session_data else None,
|
|
285
|
+
metadata=metadata,
|
|
286
|
+
created_at=current_time,
|
|
287
|
+
updated_at=current_time,
|
|
150
288
|
)
|
|
151
289
|
else:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
290
|
+
session = WorkflowSession(
|
|
291
|
+
session_id=session_id,
|
|
292
|
+
workflow_id=workflow_id,
|
|
155
293
|
user_id=user_id,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
294
|
+
session_data=session_data if session_data else None,
|
|
295
|
+
metadata=metadata,
|
|
296
|
+
created_at=current_time,
|
|
297
|
+
updated_at=current_time,
|
|
159
298
|
)
|
|
160
299
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
300
|
+
if isinstance(db, AsyncBaseDb):
|
|
301
|
+
db = cast(AsyncBaseDb, db)
|
|
302
|
+
created_session = await db.upsert_session(session, deserialize=True)
|
|
303
|
+
else:
|
|
304
|
+
created_session = db.upsert_session(session, deserialize=True)
|
|
305
|
+
|
|
306
|
+
if not created_session:
|
|
307
|
+
raise Exception("Failed to create session")
|
|
164
308
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
309
|
+
if session_type_enum == SessionType.AGENT:
|
|
310
|
+
return AgentSessionDetailSchema.from_session(created_session).model_dump() # type: ignore
|
|
311
|
+
elif session_type_enum == SessionType.TEAM:
|
|
312
|
+
return TeamSessionDetailSchema.from_session(created_session).model_dump() # type: ignore
|
|
313
|
+
else:
|
|
314
|
+
return WorkflowSessionDetailSchema.from_session(created_session).model_dump() # type: ignore
|
|
315
|
+
|
|
316
|
+
@mcp.tool(
|
|
317
|
+
name="get_session_runs",
|
|
318
|
+
description="Get all runs for a specific session",
|
|
319
|
+
tags={"session"},
|
|
320
|
+
) # type: ignore
|
|
321
|
+
async def get_session_runs(
|
|
322
|
+
session_id: str,
|
|
168
323
|
db_id: str,
|
|
324
|
+
session_type: str = "agent",
|
|
169
325
|
user_id: Optional[str] = None,
|
|
170
|
-
|
|
171
|
-
sort_order: str = "desc",
|
|
172
|
-
):
|
|
326
|
+
) -> List[Dict[str, Any]]:
|
|
173
327
|
db = await get_db(os.dbs, db_id)
|
|
328
|
+
session_type_enum = SessionType(session_type)
|
|
329
|
+
|
|
330
|
+
if isinstance(db, RemoteDb):
|
|
331
|
+
result = await db.get_session_runs(
|
|
332
|
+
session_id=session_id,
|
|
333
|
+
session_type=session_type_enum,
|
|
334
|
+
user_id=user_id,
|
|
335
|
+
db_id=db_id,
|
|
336
|
+
)
|
|
337
|
+
return [r.model_dump() for r in result]
|
|
338
|
+
|
|
174
339
|
if isinstance(db, AsyncBaseDb):
|
|
175
340
|
db = cast(AsyncBaseDb, db)
|
|
176
|
-
|
|
177
|
-
session_type=
|
|
178
|
-
|
|
341
|
+
session = await db.get_session(
|
|
342
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=False
|
|
343
|
+
)
|
|
344
|
+
else:
|
|
345
|
+
session = db.get_session(
|
|
346
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=False
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
if not session:
|
|
350
|
+
raise Exception(f"Session {session_id} not found")
|
|
351
|
+
|
|
352
|
+
runs = session.get("runs") # type: ignore
|
|
353
|
+
if not runs:
|
|
354
|
+
return []
|
|
355
|
+
|
|
356
|
+
run_responses: List[Dict[str, Any]] = []
|
|
357
|
+
for run in runs:
|
|
358
|
+
if session_type_enum == SessionType.AGENT:
|
|
359
|
+
run_responses.append(RunSchema.from_dict(run).model_dump())
|
|
360
|
+
elif session_type_enum == SessionType.TEAM:
|
|
361
|
+
if run.get("agent_id") is not None:
|
|
362
|
+
run_responses.append(RunSchema.from_dict(run).model_dump())
|
|
363
|
+
else:
|
|
364
|
+
run_responses.append(TeamRunSchema.from_dict(run).model_dump())
|
|
365
|
+
else:
|
|
366
|
+
if run.get("workflow_id") is not None:
|
|
367
|
+
run_responses.append(WorkflowRunSchema.from_dict(run).model_dump())
|
|
368
|
+
elif run.get("team_id") is not None:
|
|
369
|
+
run_responses.append(TeamRunSchema.from_dict(run).model_dump())
|
|
370
|
+
else:
|
|
371
|
+
run_responses.append(RunSchema.from_dict(run).model_dump())
|
|
372
|
+
|
|
373
|
+
return run_responses
|
|
374
|
+
|
|
375
|
+
@mcp.tool(
|
|
376
|
+
name="get_session_run",
|
|
377
|
+
description="Get a specific run from a session",
|
|
378
|
+
tags={"session"},
|
|
379
|
+
) # type: ignore
|
|
380
|
+
async def get_session_run(
|
|
381
|
+
session_id: str,
|
|
382
|
+
run_id: str,
|
|
383
|
+
db_id: str,
|
|
384
|
+
session_type: str = "agent",
|
|
385
|
+
user_id: Optional[str] = None,
|
|
386
|
+
) -> Dict[str, Any]:
|
|
387
|
+
db = await get_db(os.dbs, db_id)
|
|
388
|
+
session_type_enum = SessionType(session_type)
|
|
389
|
+
|
|
390
|
+
if isinstance(db, RemoteDb):
|
|
391
|
+
result = await db.get_session_run(
|
|
392
|
+
session_id=session_id,
|
|
393
|
+
run_id=run_id,
|
|
394
|
+
session_type=session_type_enum,
|
|
179
395
|
user_id=user_id,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
396
|
+
db_id=db_id,
|
|
397
|
+
)
|
|
398
|
+
return result.model_dump()
|
|
399
|
+
|
|
400
|
+
if isinstance(db, AsyncBaseDb):
|
|
401
|
+
db = cast(AsyncBaseDb, db)
|
|
402
|
+
session = await db.get_session(
|
|
403
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=False
|
|
404
|
+
)
|
|
405
|
+
else:
|
|
406
|
+
session = db.get_session(
|
|
407
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=False
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
if not session:
|
|
411
|
+
raise Exception(f"Session {session_id} not found")
|
|
412
|
+
|
|
413
|
+
runs = session.get("runs") # type: ignore
|
|
414
|
+
if not runs:
|
|
415
|
+
raise Exception(f"Session {session_id} has no runs")
|
|
416
|
+
|
|
417
|
+
target_run = None
|
|
418
|
+
for run in runs:
|
|
419
|
+
if run.get("run_id") == run_id:
|
|
420
|
+
target_run = run
|
|
421
|
+
break
|
|
422
|
+
|
|
423
|
+
if not target_run:
|
|
424
|
+
raise Exception(f"Run {run_id} not found in session {session_id}")
|
|
425
|
+
|
|
426
|
+
if target_run.get("workflow_id") is not None:
|
|
427
|
+
return WorkflowRunSchema.from_dict(target_run).model_dump()
|
|
428
|
+
elif target_run.get("team_id") is not None:
|
|
429
|
+
return TeamRunSchema.from_dict(target_run).model_dump()
|
|
430
|
+
else:
|
|
431
|
+
return RunSchema.from_dict(target_run).model_dump()
|
|
432
|
+
|
|
433
|
+
@mcp.tool(
|
|
434
|
+
name="rename_session",
|
|
435
|
+
description="Rename an existing session",
|
|
436
|
+
tags={"session"},
|
|
437
|
+
) # type: ignore
|
|
438
|
+
async def rename_session(
|
|
439
|
+
session_id: str,
|
|
440
|
+
session_name: str,
|
|
441
|
+
db_id: str,
|
|
442
|
+
session_type: str = "agent",
|
|
443
|
+
) -> Dict[str, Any]:
|
|
444
|
+
db = await get_db(os.dbs, db_id)
|
|
445
|
+
session_type_enum = SessionType(session_type)
|
|
446
|
+
|
|
447
|
+
if isinstance(db, RemoteDb):
|
|
448
|
+
result = await db.rename_session(
|
|
449
|
+
session_id=session_id,
|
|
450
|
+
session_name=session_name,
|
|
451
|
+
session_type=session_type_enum,
|
|
452
|
+
db_id=db_id,
|
|
183
453
|
)
|
|
454
|
+
return result.model_dump()
|
|
455
|
+
|
|
456
|
+
if isinstance(db, AsyncBaseDb):
|
|
457
|
+
db = cast(AsyncBaseDb, db)
|
|
458
|
+
session = await db.rename_session(
|
|
459
|
+
session_id=session_id, session_type=session_type_enum, session_name=session_name
|
|
460
|
+
)
|
|
461
|
+
else:
|
|
462
|
+
db = cast(BaseDb, db)
|
|
463
|
+
session = db.rename_session(
|
|
464
|
+
session_id=session_id, session_type=session_type_enum, session_name=session_name
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
if not session:
|
|
468
|
+
raise Exception(f"Session {session_id} not found")
|
|
469
|
+
|
|
470
|
+
if session_type_enum == SessionType.AGENT:
|
|
471
|
+
return AgentSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
472
|
+
elif session_type_enum == SessionType.TEAM:
|
|
473
|
+
return TeamSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
184
474
|
else:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
475
|
+
return WorkflowSessionDetailSchema.from_session(session).model_dump() # type: ignore
|
|
476
|
+
|
|
477
|
+
@mcp.tool(
|
|
478
|
+
name="update_session",
|
|
479
|
+
description="Update session properties like name, state, metadata, or summary",
|
|
480
|
+
tags={"session"},
|
|
481
|
+
) # type: ignore
|
|
482
|
+
async def update_session(
|
|
483
|
+
session_id: str,
|
|
484
|
+
db_id: str,
|
|
485
|
+
session_type: str = "agent",
|
|
486
|
+
session_name: Optional[str] = None,
|
|
487
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
488
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
489
|
+
summary: Optional[Dict[str, Any]] = None,
|
|
490
|
+
user_id: Optional[str] = None,
|
|
491
|
+
) -> Dict[str, Any]:
|
|
492
|
+
db = await get_db(os.dbs, db_id)
|
|
493
|
+
session_type_enum = SessionType(session_type)
|
|
494
|
+
|
|
495
|
+
if isinstance(db, RemoteDb):
|
|
496
|
+
result = await db.update_session(
|
|
497
|
+
session_id=session_id,
|
|
498
|
+
session_type=session_type_enum,
|
|
499
|
+
session_name=session_name,
|
|
500
|
+
session_state=session_state,
|
|
501
|
+
metadata=metadata,
|
|
502
|
+
summary=summary,
|
|
188
503
|
user_id=user_id,
|
|
189
|
-
|
|
190
|
-
sort_order=sort_order,
|
|
191
|
-
deserialize=False,
|
|
504
|
+
db_id=db_id,
|
|
192
505
|
)
|
|
506
|
+
return result.model_dump()
|
|
193
507
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
508
|
+
# Get the existing session
|
|
509
|
+
if isinstance(db, AsyncBaseDb):
|
|
510
|
+
db = cast(AsyncBaseDb, db)
|
|
511
|
+
existing_session = await db.get_session(
|
|
512
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=True
|
|
513
|
+
)
|
|
514
|
+
else:
|
|
515
|
+
existing_session = db.get_session(
|
|
516
|
+
session_id=session_id, session_type=session_type_enum, user_id=user_id, deserialize=True
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
if not existing_session:
|
|
520
|
+
raise Exception(f"Session {session_id} not found")
|
|
521
|
+
|
|
522
|
+
# Update session properties
|
|
523
|
+
if session_name is not None:
|
|
524
|
+
if existing_session.session_data is None: # type: ignore
|
|
525
|
+
existing_session.session_data = {} # type: ignore
|
|
526
|
+
existing_session.session_data["session_name"] = session_name # type: ignore
|
|
527
|
+
|
|
528
|
+
if session_state is not None:
|
|
529
|
+
if existing_session.session_data is None: # type: ignore
|
|
530
|
+
existing_session.session_data = {} # type: ignore
|
|
531
|
+
existing_session.session_data["session_state"] = session_state # type: ignore
|
|
532
|
+
|
|
533
|
+
if metadata is not None:
|
|
534
|
+
existing_session.metadata = metadata # type: ignore
|
|
535
|
+
|
|
536
|
+
if summary is not None:
|
|
537
|
+
from agno.session.summary import SessionSummary
|
|
538
|
+
|
|
539
|
+
existing_session.summary = SessionSummary.from_dict(summary) # type: ignore
|
|
540
|
+
|
|
541
|
+
# Upsert the updated session
|
|
542
|
+
if isinstance(db, AsyncBaseDb):
|
|
543
|
+
updated_session = await db.upsert_session(existing_session, deserialize=True) # type: ignore
|
|
544
|
+
else:
|
|
545
|
+
updated_session = db.upsert_session(existing_session, deserialize=True) # type: ignore
|
|
546
|
+
|
|
547
|
+
if not updated_session:
|
|
548
|
+
raise Exception("Failed to update session")
|
|
549
|
+
|
|
550
|
+
if session_type_enum == SessionType.AGENT:
|
|
551
|
+
return AgentSessionDetailSchema.from_session(updated_session).model_dump() # type: ignore
|
|
552
|
+
elif session_type_enum == SessionType.TEAM:
|
|
553
|
+
return TeamSessionDetailSchema.from_session(updated_session).model_dump() # type: ignore
|
|
554
|
+
else:
|
|
555
|
+
return WorkflowSessionDetailSchema.from_session(updated_session).model_dump() # type: ignore
|
|
556
|
+
|
|
557
|
+
@mcp.tool(
|
|
558
|
+
name="delete_session",
|
|
559
|
+
description="Delete a specific session and all its runs",
|
|
560
|
+
tags={"session"},
|
|
561
|
+
) # type: ignore
|
|
562
|
+
async def delete_session(
|
|
563
|
+
session_id: str,
|
|
564
|
+
db_id: str,
|
|
565
|
+
) -> str:
|
|
566
|
+
db = await get_db(os.dbs, db_id)
|
|
567
|
+
|
|
568
|
+
if isinstance(db, RemoteDb):
|
|
569
|
+
await db.delete_session(session_id=session_id, db_id=db_id)
|
|
570
|
+
return "Session deleted successfully"
|
|
571
|
+
|
|
572
|
+
if isinstance(db, AsyncBaseDb):
|
|
573
|
+
db = cast(AsyncBaseDb, db)
|
|
574
|
+
await db.delete_session(session_id=session_id)
|
|
575
|
+
else:
|
|
576
|
+
db = cast(BaseDb, db)
|
|
577
|
+
db.delete_session(session_id=session_id)
|
|
578
|
+
|
|
579
|
+
return "Session deleted successfully"
|
|
580
|
+
|
|
581
|
+
@mcp.tool(
|
|
582
|
+
name="delete_sessions",
|
|
583
|
+
description="Delete multiple sessions by their IDs",
|
|
584
|
+
tags={"session"},
|
|
585
|
+
) # type: ignore
|
|
586
|
+
async def delete_sessions(
|
|
587
|
+
session_ids: List[str],
|
|
588
|
+
db_id: str,
|
|
589
|
+
session_types: Optional[List[str]] = None,
|
|
590
|
+
) -> str:
|
|
591
|
+
db = await get_db(os.dbs, db_id)
|
|
592
|
+
|
|
593
|
+
if isinstance(db, RemoteDb):
|
|
594
|
+
# Convert session_types strings to SessionType enums
|
|
595
|
+
session_type_enums = [SessionType(st) for st in session_types] if session_types else []
|
|
596
|
+
await db.delete_sessions(session_ids=session_ids, session_types=session_type_enums, db_id=db_id)
|
|
597
|
+
return "Sessions deleted successfully"
|
|
598
|
+
|
|
599
|
+
if isinstance(db, AsyncBaseDb):
|
|
600
|
+
db = cast(AsyncBaseDb, db)
|
|
601
|
+
await db.delete_sessions(session_ids=session_ids)
|
|
602
|
+
else:
|
|
603
|
+
db = cast(BaseDb, db)
|
|
604
|
+
db.delete_sessions(session_ids=session_ids)
|
|
605
|
+
|
|
606
|
+
return "Sessions deleted successfully"
|
|
607
|
+
|
|
608
|
+
# ==================== Memory Management Tools ====================
|
|
197
609
|
|
|
198
|
-
# Memory Management Tools
|
|
199
610
|
@mcp.tool(name="create_memory", description="Create a new user memory", tags={"memory"}) # type: ignore
|
|
200
611
|
async def create_memory(
|
|
201
612
|
db_id: str,
|
|
@@ -204,90 +615,251 @@ def get_mcp_server(
|
|
|
204
615
|
topics: Optional[List[str]] = None,
|
|
205
616
|
) -> UserMemorySchema:
|
|
206
617
|
db = await get_db(os.dbs, db_id)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
618
|
+
|
|
619
|
+
if isinstance(db, RemoteDb):
|
|
620
|
+
return await db.create_memory(
|
|
210
621
|
memory=memory,
|
|
211
622
|
topics=topics or [],
|
|
212
623
|
user_id=user_id,
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
624
|
+
db_id=db_id,
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
if isinstance(db, AsyncBaseDb):
|
|
628
|
+
db = cast(AsyncBaseDb, db)
|
|
629
|
+
user_memory = await db.upsert_user_memory(
|
|
630
|
+
memory=UserMemory(
|
|
631
|
+
memory_id=str(uuid4()),
|
|
632
|
+
memory=memory,
|
|
633
|
+
topics=topics or [],
|
|
634
|
+
user_id=user_id,
|
|
635
|
+
),
|
|
636
|
+
deserialize=False,
|
|
637
|
+
)
|
|
638
|
+
else:
|
|
639
|
+
db = cast(BaseDb, db)
|
|
640
|
+
user_memory = db.upsert_user_memory(
|
|
641
|
+
memory=UserMemory(
|
|
642
|
+
memory_id=str(uuid4()),
|
|
643
|
+
memory=memory,
|
|
644
|
+
topics=topics or [],
|
|
645
|
+
user_id=user_id,
|
|
646
|
+
),
|
|
647
|
+
deserialize=False,
|
|
648
|
+
)
|
|
649
|
+
|
|
216
650
|
if not user_memory:
|
|
217
651
|
raise Exception("Failed to create memory")
|
|
218
652
|
|
|
219
653
|
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
220
654
|
|
|
221
|
-
@mcp.tool(
|
|
222
|
-
|
|
223
|
-
|
|
655
|
+
@mcp.tool(
|
|
656
|
+
name="get_memory",
|
|
657
|
+
description="Get a specific memory by ID",
|
|
658
|
+
tags={"memory"},
|
|
659
|
+
) # type: ignore
|
|
660
|
+
async def get_memory(
|
|
661
|
+
memory_id: str,
|
|
662
|
+
db_id: str,
|
|
663
|
+
user_id: Optional[str] = None,
|
|
664
|
+
) -> UserMemorySchema:
|
|
665
|
+
db = await get_db(os.dbs, db_id)
|
|
666
|
+
|
|
667
|
+
if isinstance(db, RemoteDb):
|
|
668
|
+
return await db.get_memory(memory_id=memory_id, user_id=user_id, db_id=db_id)
|
|
669
|
+
|
|
670
|
+
if isinstance(db, AsyncBaseDb):
|
|
671
|
+
db = cast(AsyncBaseDb, db)
|
|
672
|
+
user_memory = await db.get_user_memory(memory_id=memory_id, user_id=user_id, deserialize=False)
|
|
673
|
+
else:
|
|
674
|
+
db = cast(BaseDb, db)
|
|
675
|
+
user_memory = db.get_user_memory(memory_id=memory_id, user_id=user_id, deserialize=False)
|
|
676
|
+
|
|
677
|
+
if not user_memory:
|
|
678
|
+
raise Exception(f"Memory {memory_id} not found")
|
|
679
|
+
|
|
680
|
+
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
681
|
+
|
|
682
|
+
@mcp.tool(
|
|
683
|
+
name="get_memories",
|
|
684
|
+
description="Get a paginated list of memories with optional filtering",
|
|
685
|
+
tags={"memory"},
|
|
686
|
+
) # type: ignore
|
|
687
|
+
async def get_memories(
|
|
688
|
+
db_id: str,
|
|
689
|
+
user_id: Optional[str] = None,
|
|
690
|
+
agent_id: Optional[str] = None,
|
|
691
|
+
team_id: Optional[str] = None,
|
|
692
|
+
topics: Optional[List[str]] = None,
|
|
693
|
+
search_content: Optional[str] = None,
|
|
694
|
+
limit: int = 20,
|
|
695
|
+
page: int = 1,
|
|
224
696
|
sort_by: str = "updated_at",
|
|
225
697
|
sort_order: str = "desc",
|
|
226
|
-
|
|
227
|
-
):
|
|
698
|
+
) -> Dict[str, Any]:
|
|
228
699
|
db = await get_db(os.dbs, db_id)
|
|
700
|
+
|
|
701
|
+
if isinstance(db, RemoteDb):
|
|
702
|
+
result = await db.get_memories(
|
|
703
|
+
user_id=user_id or "",
|
|
704
|
+
agent_id=agent_id,
|
|
705
|
+
team_id=team_id,
|
|
706
|
+
topics=topics,
|
|
707
|
+
search_content=search_content,
|
|
708
|
+
limit=limit,
|
|
709
|
+
page=page,
|
|
710
|
+
sort_by=sort_by,
|
|
711
|
+
sort_order=sort_order,
|
|
712
|
+
db_id=db_id,
|
|
713
|
+
)
|
|
714
|
+
return result.model_dump()
|
|
715
|
+
|
|
229
716
|
if isinstance(db, AsyncBaseDb):
|
|
230
717
|
db = cast(AsyncBaseDb, db)
|
|
231
|
-
user_memories = await db.get_user_memories(
|
|
718
|
+
user_memories, total_count = await db.get_user_memories(
|
|
719
|
+
limit=limit,
|
|
720
|
+
page=page,
|
|
232
721
|
user_id=user_id,
|
|
722
|
+
agent_id=agent_id,
|
|
723
|
+
team_id=team_id,
|
|
724
|
+
topics=topics,
|
|
725
|
+
search_content=search_content,
|
|
233
726
|
sort_by=sort_by,
|
|
234
727
|
sort_order=sort_order,
|
|
235
728
|
deserialize=False,
|
|
236
729
|
)
|
|
237
730
|
else:
|
|
238
|
-
|
|
731
|
+
db = cast(BaseDb, db)
|
|
732
|
+
user_memories, total_count = db.get_user_memories(
|
|
733
|
+
limit=limit,
|
|
734
|
+
page=page,
|
|
239
735
|
user_id=user_id,
|
|
736
|
+
agent_id=agent_id,
|
|
737
|
+
team_id=team_id,
|
|
738
|
+
topics=topics,
|
|
739
|
+
search_content=search_content,
|
|
240
740
|
sort_by=sort_by,
|
|
241
741
|
sort_order=sort_order,
|
|
242
742
|
deserialize=False,
|
|
243
743
|
)
|
|
744
|
+
|
|
745
|
+
memories = [UserMemorySchema.from_dict(m) for m in user_memories] # type: ignore
|
|
244
746
|
return {
|
|
245
|
-
"data": [
|
|
747
|
+
"data": [m.model_dump() for m in memories if m is not None],
|
|
748
|
+
"meta": {
|
|
749
|
+
"page": page,
|
|
750
|
+
"limit": limit,
|
|
751
|
+
"total_count": total_count,
|
|
752
|
+
"total_pages": (total_count + limit - 1) // limit if limit > 0 else 0, # type: ignore
|
|
753
|
+
},
|
|
246
754
|
}
|
|
247
755
|
|
|
248
|
-
@mcp.tool(name="update_memory", description="Update
|
|
756
|
+
@mcp.tool(name="update_memory", description="Update an existing memory", tags={"memory"}) # type: ignore
|
|
249
757
|
async def update_memory(
|
|
250
758
|
db_id: str,
|
|
251
759
|
memory_id: str,
|
|
252
760
|
memory: str,
|
|
253
761
|
user_id: str,
|
|
762
|
+
topics: Optional[List[str]] = None,
|
|
254
763
|
) -> UserMemorySchema:
|
|
255
764
|
db = await get_db(os.dbs, db_id)
|
|
765
|
+
|
|
766
|
+
if isinstance(db, RemoteDb):
|
|
767
|
+
return await db.update_memory(
|
|
768
|
+
memory_id=memory_id,
|
|
769
|
+
memory=memory,
|
|
770
|
+
topics=topics or [],
|
|
771
|
+
user_id=user_id,
|
|
772
|
+
db_id=db_id,
|
|
773
|
+
)
|
|
774
|
+
|
|
256
775
|
if isinstance(db, AsyncBaseDb):
|
|
257
776
|
db = cast(AsyncBaseDb, db)
|
|
258
777
|
user_memory = await db.upsert_user_memory(
|
|
259
778
|
memory=UserMemory(
|
|
260
779
|
memory_id=memory_id,
|
|
261
780
|
memory=memory,
|
|
781
|
+
topics=topics or [],
|
|
262
782
|
user_id=user_id,
|
|
263
783
|
),
|
|
264
784
|
deserialize=False,
|
|
265
785
|
)
|
|
266
786
|
else:
|
|
787
|
+
db = cast(BaseDb, db)
|
|
267
788
|
user_memory = db.upsert_user_memory(
|
|
268
789
|
memory=UserMemory(
|
|
269
790
|
memory_id=memory_id,
|
|
270
791
|
memory=memory,
|
|
792
|
+
topics=topics or [],
|
|
271
793
|
user_id=user_id,
|
|
272
794
|
),
|
|
273
795
|
deserialize=False,
|
|
274
796
|
)
|
|
797
|
+
|
|
275
798
|
if not user_memory:
|
|
276
799
|
raise Exception("Failed to update memory")
|
|
277
800
|
|
|
278
801
|
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
279
802
|
|
|
280
|
-
@mcp.tool(name="delete_memory", description="Delete a memory by ID", tags={"memory"}) # type: ignore
|
|
803
|
+
@mcp.tool(name="delete_memory", description="Delete a specific memory by ID", tags={"memory"}) # type: ignore
|
|
281
804
|
async def delete_memory(
|
|
282
805
|
db_id: str,
|
|
283
806
|
memory_id: str,
|
|
284
|
-
|
|
807
|
+
user_id: Optional[str] = None,
|
|
808
|
+
) -> str:
|
|
285
809
|
db = await get_db(os.dbs, db_id)
|
|
810
|
+
|
|
811
|
+
if isinstance(db, RemoteDb):
|
|
812
|
+
await db.delete_memory(memory_id=memory_id, user_id=user_id, db_id=db_id)
|
|
813
|
+
return "Memory deleted successfully"
|
|
814
|
+
|
|
286
815
|
if isinstance(db, AsyncBaseDb):
|
|
287
816
|
db = cast(AsyncBaseDb, db)
|
|
288
|
-
await db.delete_user_memory(memory_id=memory_id)
|
|
817
|
+
await db.delete_user_memory(memory_id=memory_id, user_id=user_id)
|
|
289
818
|
else:
|
|
290
|
-
db
|
|
819
|
+
db = cast(BaseDb, db)
|
|
820
|
+
db.delete_user_memory(memory_id=memory_id, user_id=user_id)
|
|
291
821
|
|
|
822
|
+
return "Memory deleted successfully"
|
|
823
|
+
|
|
824
|
+
@mcp.tool(
|
|
825
|
+
name="delete_memories",
|
|
826
|
+
description="Delete multiple memories by their IDs",
|
|
827
|
+
tags={"memory"},
|
|
828
|
+
) # type: ignore
|
|
829
|
+
async def delete_memories(
|
|
830
|
+
memory_ids: List[str],
|
|
831
|
+
db_id: str,
|
|
832
|
+
user_id: Optional[str] = None,
|
|
833
|
+
) -> str:
|
|
834
|
+
db = await get_db(os.dbs, db_id)
|
|
835
|
+
|
|
836
|
+
if isinstance(db, RemoteDb):
|
|
837
|
+
await db.delete_memories(memory_ids=memory_ids, user_id=user_id, db_id=db_id)
|
|
838
|
+
return "Memories deleted successfully"
|
|
839
|
+
|
|
840
|
+
if isinstance(db, AsyncBaseDb):
|
|
841
|
+
db = cast(AsyncBaseDb, db)
|
|
842
|
+
await db.delete_user_memories(memory_ids=memory_ids, user_id=user_id)
|
|
843
|
+
else:
|
|
844
|
+
db = cast(BaseDb, db)
|
|
845
|
+
db.delete_user_memories(memory_ids=memory_ids, user_id=user_id)
|
|
846
|
+
|
|
847
|
+
return "Memories deleted successfully"
|
|
848
|
+
|
|
849
|
+
# Use http_app for Streamable HTTP transport (modern MCP standard)
|
|
292
850
|
mcp_app = mcp.http_app(path="/mcp")
|
|
851
|
+
|
|
852
|
+
# Add JWT middleware to MCP app if authorization is enabled
|
|
853
|
+
if os.authorization and os.authorization_config:
|
|
854
|
+
from agno.os.middleware.jwt import JWTMiddleware
|
|
855
|
+
|
|
856
|
+
mcp_app.add_middleware(
|
|
857
|
+
JWTMiddleware,
|
|
858
|
+
verification_keys=os.authorization_config.verification_keys,
|
|
859
|
+
jwks_file=os.authorization_config.jwks_file,
|
|
860
|
+
algorithm=os.authorization_config.algorithm or "RS256",
|
|
861
|
+
authorization=os.authorization,
|
|
862
|
+
verify_audience=os.authorization_config.verify_audience or False,
|
|
863
|
+
)
|
|
864
|
+
|
|
293
865
|
return mcp_app
|