1
1
"""The core of the MCP server for the Docs API."""
2
2
3
3
import asyncio
4
+ from contextlib import asynccontextmanager
4
5
5
6
import httpx
6
7
from fastmcp import FastMCP
8
+ from starlette .requests import Request
9
+ from starlette .responses import PlainTextResponse
7
10
8
11
from . import settings , utils
9
12
from .auth .forwarder import HeaderForwarderAuthentication
10
13
from .auth .token import UserTokenAuthentication
11
14
12
- # Create a server instance from the OpenAPI spec
13
- mcp = FastMCP ( name = "Docs MCP Server" )
15
+ # Global variable for the API client
16
+ api_client = None
14
17
15
18
16
- def setup_mcp_server ():
17
- """Configure the tools and resources for the MCP server."""
18
- print ("#" * 70 )
19
+ @asynccontextmanager
20
+ async def lifespan (app : FastMCP ):
21
+ """
22
+ Manage the lifecycle of resources for the MCP server.
23
+
24
+ This context manager initializes resources on startup and
25
+ ensures proper cleanup on shutdown.
26
+ """
27
+ global api_client
28
+
29
+ # Initialize API client on startup
19
30
if settings .DOCS_API_TOKEN :
20
31
print ("Setting up Docs MCP Server with user token authentication" )
21
32
api_client = httpx .AsyncClient (
@@ -24,8 +35,23 @@ def setup_mcp_server():
24
35
)
25
36
else :
26
37
print ("Setting up Docs MCP Server with header forwarder authentication" )
27
- api_client = httpx .AsyncClient (base_url = settings .DOCS_API_URL , auth = HeaderForwarderAuthentication ())
28
- print ("#" * 70 )
38
+ api_client = httpx .AsyncClient (
39
+ base_url = settings .DOCS_API_URL , auth = HeaderForwarderAuthentication ()
40
+ )
41
+
42
+ print ("API client initialized" )
43
+ yield
44
+ # Cleanup resources on shutdown
45
+ print ("Closing API client" )
46
+ await api_client .aclose ()
47
+
48
+
49
+ # Create a server instance from the OpenAPI spec with lifespan
50
+ mcp = FastMCP (name = "Docs MCP Server" , lifespan = lifespan )
51
+
52
+
53
+ def setup_mcp_server ():
54
+ """Configure the tools and resources for the MCP server."""
29
55
30
56
@mcp .tool ()
31
57
async def create_document_tool (document_title : str , document_content : str ) -> None :
@@ -37,6 +63,9 @@ async def create_document_tool(document_title: str, document_content: str) -> No
37
63
document_content: The content of the document (required)
38
64
39
65
"""
66
+ if api_client is None :
67
+ raise RuntimeError ("API client is not initialized" )
68
+
40
69
# Get current user information
41
70
user_response = await api_client .get ("/api/v1.0/users/me/" )
42
71
user_response .raise_for_status ()
@@ -57,6 +86,11 @@ async def create_document_tool(document_title: str, document_content: str) -> No
57
86
)
58
87
create_response .raise_for_status ()
59
88
89
+ # Add health check endpoint
90
+ @mcp .custom_route ("/health" , methods = ["GET" ])
91
+ async def health_check (request : Request ) -> PlainTextResponse :
92
+ return PlainTextResponse ("OK" )
93
+
60
94
61
95
if __name__ == "__main__" :
62
96
setup_mcp_server ()
0 commit comments