11from contextlib import asynccontextmanager
2- from typing import Annotated , AsyncGenerator
2+ from typing import Annotated
33
4- import psycopg .errors
54from fastapi import Depends
65from langchain_mcp_adapters .tools import load_mcp_tools
76from langchain_openai import ChatOpenAI
8- from langgraph .checkpoint .postgres .aio import AsyncPostgresSaver
9- from mcp import ClientSession
10- from mcp .client .sse import sse_client
11- from psycopg_pool import AsyncConnectionPool
127from sqlalchemy .ext .asyncio import AsyncEngine , create_async_engine
138
9+ from api .core .agent .persistence import checkpointer_context
1410from api .core .config import settings
15- from api .core .logs import uvicorn
11+ from api .core .mcps import mcp_sse_client
12+ from api .core .models import Resource
1613
1714
1815def get_llm () -> ChatOpenAI :
@@ -38,39 +35,15 @@ def get_engine() -> AsyncEngine:
3835EngineDep = Annotated [AsyncEngine , Depends (get_engine )]
3936
4037
41- @asynccontextmanager
42- async def mcp_sse_client () -> AsyncGenerator [ClientSession , None ]:
43- async with sse_client (f"http://mcp:{ settings .mcp_server_port } /sse" ) as (
44- read_stream ,
45- write_stream ,
46- ):
47- async with ClientSession (read_stream , write_stream ) as session :
48- await session .initialize ()
49- yield session
50-
51-
52- async def checkpointer_setup (pool ):
53- checkpointer = AsyncPostgresSaver (pool )
54- try :
55- await checkpointer .setup ()
56- except (
57- psycopg .errors .DuplicateColumn ,
58- psycopg .errors .ActiveSqlTransaction ,
59- ):
60- uvicorn .warning ("Skipping checkpointer setup — already configured." )
61- return checkpointer
62-
63-
6438@asynccontextmanager
6539async def setup_graph ():
66- # NOTE: LangGraph AsyncPostgresSaver does not support SQLAlchemy ORM Connections.
67- # A compatible psycopg connection is created via the connection pool to connect to the checkpointer.
68- async with AsyncConnectionPool (
69- conninfo = settings .checkpoint_conn_str ,
70- kwargs = dict (prepare_threshold = None ),
71- ) as pool :
72- checkpointer = await checkpointer_setup (pool )
73-
40+ async with checkpointer_context (
41+ settings .checkpoint_conn_str
42+ ) as checkpointer :
7443 async with mcp_sse_client () as session :
7544 tools = await load_mcp_tools (session )
76- yield checkpointer , tools , session
45+ yield Resource (
46+ checkpointer = checkpointer ,
47+ tools = tools ,
48+ session = session ,
49+ )
0 commit comments