Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -110,12 +110,13 @@ mcp_server = Server(name="airtable-mcp")
|
|
110 |
mcp_server.tool_handlers = tool_handlers # Set as attribute
|
111 |
mcp_server.tools = tools # Set tools as attribute for Deep Agent to discover
|
112 |
|
113 |
-
#
|
114 |
-
|
115 |
|
116 |
# SSE endpoint for GET requests
|
117 |
@app.get("/airtable/mcp")
|
118 |
async def handle_sse(request: Request):
|
|
|
119 |
logger.debug("Handling SSE connection request")
|
120 |
async def sse_writer():
|
121 |
logger.debug("Starting SSE writer")
|
@@ -140,8 +141,9 @@ async def handle_sse(request: Request):
|
|
140 |
async with transport.connect_sse(request.scope, request.receive, request._send) as streams:
|
141 |
read_stream, write_stream = streams
|
142 |
write_stream_reader = write_stream # Since streams are MemoryObject streams
|
|
|
143 |
logger.debug("Running MCP server with streams")
|
144 |
-
await mcp_server.run(read_stream, write_stream, mcp_server.create_initialization_options())
|
145 |
return EventSourceResponse(sse_stream_reader, data_sender_callable=sse_writer)
|
146 |
|
147 |
# Message handling endpoint for POST requests
|
@@ -152,9 +154,36 @@ async def handle_post_message(request: Request):
|
|
152 |
logger.debug(f"Received POST message body: {body}")
|
153 |
try:
|
154 |
message = json.loads(body.decode())
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
logger.debug("Handling tools/list request manually")
|
157 |
-
# Create a ListToolsResult response
|
158 |
response = {
|
159 |
"jsonrpc": "2.0",
|
160 |
"id": message.get("id"),
|
@@ -162,11 +191,13 @@ async def handle_post_message(request: Request):
|
|
162 |
"tools": [tool.model_dump(by_alias=True, exclude_none=True) for tool in tools]
|
163 |
}
|
164 |
}
|
165 |
-
# Send the response back through the SSE stream
|
166 |
-
# Since we don't have direct access to transport's send method, log for now
|
167 |
logger.debug(f"Manual tools/list response: {response}")
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
|
|
170 |
await transport.handle_post_message(request.scope, request.receive, request._send)
|
171 |
logger.debug("POST message handled successfully")
|
172 |
except Exception as e:
|
|
|
110 |
mcp_server.tool_handlers = tool_handlers # Set as attribute
|
111 |
mcp_server.tools = tools # Set tools as attribute for Deep Agent to discover
|
112 |
|
113 |
+
# Store write_stream globally to access in POST handler
|
114 |
+
write_stream_global = None
|
115 |
|
116 |
# SSE endpoint for GET requests
|
117 |
@app.get("/airtable/mcp")
|
118 |
async def handle_sse(request: Request):
|
119 |
+
global write_stream_global
|
120 |
logger.debug("Handling SSE connection request")
|
121 |
async def sse_writer():
|
122 |
logger.debug("Starting SSE writer")
|
|
|
141 |
async with transport.connect_sse(request.scope, request.receive, request._send) as streams:
|
142 |
read_stream, write_stream = streams
|
143 |
write_stream_reader = write_stream # Since streams are MemoryObject streams
|
144 |
+
write_stream_global = write_stream # Store write_stream for POST handler
|
145 |
logger.debug("Running MCP server with streams")
|
146 |
+
await mcp_server.run(read_stream, write_stream, mcp_server.create_initialization_options(), tools=tools)
|
147 |
return EventSourceResponse(sse_stream_reader, data_sender_callable=sse_writer)
|
148 |
|
149 |
# Message handling endpoint for POST requests
|
|
|
154 |
logger.debug(f"Received POST message body: {body}")
|
155 |
try:
|
156 |
message = json.loads(body.decode())
|
157 |
+
# Handle initialize request manually to ensure capabilities include tools
|
158 |
+
if message.get("method") == "initialize" and write_stream_global:
|
159 |
+
logger.debug("Handling initialize request manually")
|
160 |
+
response = {
|
161 |
+
"jsonrpc": "2.0",
|
162 |
+
"id": message.get("id"),
|
163 |
+
"result": {
|
164 |
+
"protocolVersion": "2025-03-26",
|
165 |
+
"capabilities": {
|
166 |
+
"tools": {
|
167 |
+
"listChanged": True
|
168 |
+
}
|
169 |
+
},
|
170 |
+
"serverInfo": {
|
171 |
+
"name": "airtable-mcp",
|
172 |
+
"version": "1.0.0"
|
173 |
+
},
|
174 |
+
"instructions": "Airtable MCP server for listing and creating records."
|
175 |
+
}
|
176 |
+
}
|
177 |
+
logger.debug(f"Manual initialize response: {response}")
|
178 |
+
session_message = mcp_types.SessionMessage(
|
179 |
+
message=mcp_types.JSONRPCResponse(**response),
|
180 |
+
metadata=mcp_types.ServerMessageMetadata(request_context=request)
|
181 |
+
)
|
182 |
+
await write_stream_global.send(session_message)
|
183 |
+
return Response(status_code=202)
|
184 |
+
# Handle tools/list request manually
|
185 |
+
if message.get("method") == "tools/list" and write_stream_global:
|
186 |
logger.debug("Handling tools/list request manually")
|
|
|
187 |
response = {
|
188 |
"jsonrpc": "2.0",
|
189 |
"id": message.get("id"),
|
|
|
191 |
"tools": [tool.model_dump(by_alias=True, exclude_none=True) for tool in tools]
|
192 |
}
|
193 |
}
|
|
|
|
|
194 |
logger.debug(f"Manual tools/list response: {response}")
|
195 |
+
session_message = mcp_types.SessionMessage(
|
196 |
+
message=mcp_types.JSONRPCResponse(**response),
|
197 |
+
metadata=mcp_types.ServerMessageMetadata(request_context=request)
|
198 |
+
)
|
199 |
+
await write_stream_global.send(session_message)
|
200 |
+
return Response(status_code=202)
|
201 |
await transport.handle_post_message(request.scope, request.receive, request._send)
|
202 |
logger.debug("POST message handled successfully")
|
203 |
except Exception as e:
|