aeonshift commited on
Commit
15914ab
·
verified ·
1 Parent(s): a6e1e4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -8
app.py CHANGED
@@ -10,6 +10,11 @@ import uvicorn
10
  from sse_starlette import EventSourceResponse
11
  import anyio
12
  import asyncio
 
 
 
 
 
13
 
14
  app = FastAPI()
15
 
@@ -32,33 +37,43 @@ def airtable_request(method, endpoint="", data=None):
32
 
33
  # Tool to list records
34
  async def list_records_tool(request: mcp_types.CallToolRequest):
 
35
  try:
36
  records = airtable_request("GET")
37
- return {
38
  "success": True,
39
  "result": json.dumps(records)
40
  }
 
 
41
  except Exception as e:
42
- return {
43
  "success": False,
44
  "error": str(e)
45
  }
 
 
46
 
47
  # Tool to create a record
48
  async def create_record_tool(request: mcp_types.CallToolRequest):
 
49
  try:
50
  record_data = request.input.get("record_data", {})
51
  data = {"records": [{"fields": record_data}]}
52
- response = airtable_request("POST", data=data)
53
- return {
54
  "success": True,
55
- "result": json.dumps(response)
56
  }
 
 
57
  except Exception as e:
58
- return {
59
  "success": False,
60
  "error": str(e)
61
  }
 
 
62
 
63
  # Define tools separately (for Deep Agent to discover them)
64
  tools = [
@@ -81,8 +96,9 @@ tool_handlers = {
81
  }
82
 
83
  # Create MCP server
84
- mcp_server = Server(name="airtable-mcp") # Added required 'name' argument
85
  mcp_server.tool_handlers = tool_handlers # Set as attribute
 
86
 
87
  # Initialize SseServerTransport
88
  transport = SseServerTransport("/airtable/mcp")
@@ -90,12 +106,17 @@ transport = SseServerTransport("/airtable/mcp")
90
  # SSE endpoint for GET requests
91
  @app.get("/airtable/mcp")
92
  async def handle_sse(request: Request):
 
93
  async def sse_writer():
 
94
  async with sse_stream_writer, write_stream_reader:
 
95
  await sse_stream_writer.send(
96
- {"event": "endpoint", "data": "/airtable/mcp?session_id={session_id}"}
97
  )
 
98
  async for session_message in write_stream_reader:
 
99
  await sse_stream_writer.send(
100
  {
101
  "event": "message",
@@ -109,13 +130,18 @@ async def handle_sse(request: Request):
109
  async with transport.connect_sse(request.scope, request.receive, request._send) as streams:
110
  read_stream, write_stream = streams
111
  write_stream_reader = write_stream # Since streams are MemoryObject streams
 
112
  await mcp_server.run(read_stream, write_stream, mcp_server.create_initialization_options())
113
  return EventSourceResponse(sse_stream_reader, data_sender_callable=sse_writer)
114
 
115
  # Message handling endpoint for POST requests
116
  @app.post("/airtable/mcp")
117
  async def handle_post_message(request: Request):
 
 
 
118
  await transport.handle_post_message(request.scope, request.receive, request._send)
 
119
  return Response(status_code=202)
120
 
121
  # Health check endpoint
@@ -123,6 +149,11 @@ async def handle_post_message(request: Request):
123
  async def health_check():
124
  return {"status": "healthy"}
125
 
 
 
 
 
 
126
  if __name__ == "__main__":
127
  port = int(os.getenv("PORT", 7860))
128
  uvicorn.run(app, host="0.0.0.0", port=port)
 
10
  from sse_starlette import EventSourceResponse
11
  import anyio
12
  import asyncio
13
+ import logging
14
+
15
+ # Set up logging
16
+ logging.basicConfig(level=logging.DEBUG)
17
+ logger = logging.getLogger(__name__)
18
 
19
  app = FastAPI()
20
 
 
37
 
38
  # Tool to list records
39
  async def list_records_tool(request: mcp_types.CallToolRequest):
40
+ logger.debug(f"Received list_records_tool request: {request}")
41
  try:
42
  records = airtable_request("GET")
43
+ response = {
44
  "success": True,
45
  "result": json.dumps(records)
46
  }
47
+ logger.debug(f"list_records_tool response: {response}")
48
+ return response
49
  except Exception as e:
50
+ response = {
51
  "success": False,
52
  "error": str(e)
53
  }
54
+ logger.error(f"list_records_tool error: {response}")
55
+ return response
56
 
57
  # Tool to create a record
58
  async def create_record_tool(request: mcp_types.CallToolRequest):
59
+ logger.debug(f"Received create_record_tool request: {request}")
60
  try:
61
  record_data = request.input.get("record_data", {})
62
  data = {"records": [{"fields": record_data}]}
63
+ response_data = airtable_request("POST", data=data)
64
+ response = {
65
  "success": True,
66
+ "result": json.dumps(response_data)
67
  }
68
+ logger.debug(f"create_record_tool response: {response}")
69
+ return response
70
  except Exception as e:
71
+ response = {
72
  "success": False,
73
  "error": str(e)
74
  }
75
+ logger.error(f"create_record_tool error: {response}")
76
+ return response
77
 
78
  # Define tools separately (for Deep Agent to discover them)
79
  tools = [
 
96
  }
97
 
98
  # Create MCP server
99
+ mcp_server = Server(name="airtable-mcp")
100
  mcp_server.tool_handlers = tool_handlers # Set as attribute
101
+ mcp_server.tools = tools # Set tools as attribute for Deep Agent to discover
102
 
103
  # Initialize SseServerTransport
104
  transport = SseServerTransport("/airtable/mcp")
 
106
  # SSE endpoint for GET requests
107
  @app.get("/airtable/mcp")
108
  async def handle_sse(request: Request):
109
+ logger.debug("Handling SSE connection request")
110
  async def sse_writer():
111
+ logger.debug("Starting SSE writer")
112
  async with sse_stream_writer, write_stream_reader:
113
+ endpoint_data = "/airtable/mcp?session_id={session_id}"
114
  await sse_stream_writer.send(
115
+ {"event": "endpoint", "data": endpoint_data}
116
  )
117
+ logger.debug(f"Sent endpoint event: {endpoint_data}")
118
  async for session_message in write_stream_reader:
119
+ logger.debug(f"Sending message via SSE: {session_message}")
120
  await sse_stream_writer.send(
121
  {
122
  "event": "message",
 
130
  async with transport.connect_sse(request.scope, request.receive, request._send) as streams:
131
  read_stream, write_stream = streams
132
  write_stream_reader = write_stream # Since streams are MemoryObject streams
133
+ logger.debug("Running MCP server with streams")
134
  await mcp_server.run(read_stream, write_stream, mcp_server.create_initialization_options())
135
  return EventSourceResponse(sse_stream_reader, data_sender_callable=sse_writer)
136
 
137
  # Message handling endpoint for POST requests
138
  @app.post("/airtable/mcp")
139
  async def handle_post_message(request: Request):
140
+ logger.debug("Handling POST message request")
141
+ body = await request.body()
142
+ logger.debug(f"Received POST message body: {body}")
143
  await transport.handle_post_message(request.scope, request.receive, request._send)
144
+ logger.debug("POST message handled successfully")
145
  return Response(status_code=202)
146
 
147
  # Health check endpoint
 
149
  async def health_check():
150
  return {"status": "healthy"}
151
 
152
+ # Endpoint to list tools (for debugging)
153
+ @app.get("/tools")
154
+ async def list_tools():
155
+ return {"tools": [tool.model_dump() for tool in tools]}
156
+
157
  if __name__ == "__main__":
158
  port = int(os.getenv("PORT", 7860))
159
  uvicorn.run(app, host="0.0.0.0", port=port)