| 94 | } |
| 95 | |
| 96 | func (s *Server) handlePost(c *gin.Context) { |
| 97 | if !validateOrigin(c.Request) { |
| 98 | c.Status(http.StatusForbidden) |
| 99 | return |
| 100 | } |
| 101 | if !acceptsStreamableHTTP(c.GetHeader("Accept")) { |
| 102 | c.JSON(http.StatusNotAcceptable, response{ |
| 103 | JSONRPC: "2.0", |
| 104 | Error: &rpcError{ |
| 105 | Code: -32000, |
| 106 | Message: "Not Acceptable: client must accept both application/json and text/event-stream", |
| 107 | }, |
| 108 | }) |
| 109 | return |
| 110 | } |
| 111 | |
| 112 | body, err := io.ReadAll(io.LimitReader(c.Request.Body, 1<<20)) |
| 113 | if err != nil { |
| 114 | c.JSON(http.StatusBadRequest, response{ |
| 115 | JSONRPC: "2.0", |
| 116 | Error: &rpcError{Code: -32700, Message: "failed to read request body"}, |
| 117 | }) |
| 118 | return |
| 119 | } |
| 120 | |
| 121 | var req request |
| 122 | if err := json.Unmarshal(body, &req); err != nil { |
| 123 | c.JSON(http.StatusBadRequest, response{ |
| 124 | JSONRPC: "2.0", |
| 125 | Error: &rpcError{Code: -32700, Message: "parse error"}, |
| 126 | }) |
| 127 | return |
| 128 | } |
| 129 | if req.JSONRPC != "2.0" { |
| 130 | c.JSON(http.StatusBadRequest, response{ |
| 131 | JSONRPC: "2.0", |
| 132 | ID: req.ID, |
| 133 | Error: &rpcError{Code: -32600, Message: "invalid request"}, |
| 134 | }) |
| 135 | return |
| 136 | } |
| 137 | |
| 138 | if req.Method == "initialize" { |
| 139 | s.handleInitialize(c, req) |
| 140 | return |
| 141 | } |
| 142 | sessionID := c.GetHeader(SessionHeader) |
| 143 | if sessionID == "" { |
| 144 | c.JSON(http.StatusBadRequest, response{ |
| 145 | JSONRPC: "2.0", |
| 146 | ID: req.ID, |
| 147 | Error: &rpcError{Code: -32000, Message: "missing MCP session"}, |
| 148 | }) |
| 149 | return |
| 150 | } |
| 151 | |
| 152 | currentSession, ok := s.getSession(sessionID) |
| 153 | if !ok { |