NewServer creates a new MCP server.
(store *store.Store, profile *config.Profile, secret string)
| 34 | |
| 35 | // NewServer creates a new MCP server. |
| 36 | func NewServer(store *store.Store, profile *config.Profile, secret string) (*Server, error) { |
| 37 | mcpServer := mcp.NewServer(&mcp.Implementation{ |
| 38 | Name: "bytebase", |
| 39 | Version: profile.Version, |
| 40 | }, nil) |
| 41 | |
| 42 | // Load OpenAPI index for API discovery and execution (embedded) |
| 43 | openAPIIndex, err := NewOpenAPIIndex() |
| 44 | if err != nil { |
| 45 | return nil, errors.Wrap(err, "failed to load OpenAPI spec") |
| 46 | } |
| 47 | |
| 48 | s := &Server{ |
| 49 | mcpServer: mcpServer, |
| 50 | store: store, |
| 51 | profile: profile, |
| 52 | secret: secret, |
| 53 | openAPIIndex: openAPIIndex, |
| 54 | } |
| 55 | s.registerTools() |
| 56 | |
| 57 | // Create HTTP handler for streamable HTTP transport. |
| 58 | // |
| 59 | // DisableLocalhostProtection turns off the SDK's DNS-rebinding check |
| 60 | // (auto-enabled since go-sdk v1.4.0). That check rejects requests that |
| 61 | // arrive over a loopback connection while carrying a non-loopback Host |
| 62 | // header. Behind a same-host reverse proxy (proxy_pass http://127.0.0.1), |
| 63 | // Bytebase accepts a loopback connection while the proxy preserves the |
| 64 | // public Host, so the check fires on legitimate traffic and returns |
| 65 | // "403 Forbidden: invalid Host header" (BYT-9693). It is safe to disable: |
| 66 | // /mcp is gated by mandatory OAuth bearer-token auth (authMiddleware), so |
| 67 | // the token — not network position — is the security boundary, and the |
| 68 | // rebinding threat targets unauthenticated, browser-reached localhost |
| 69 | // servers, which Bytebase is not. |
| 70 | s.httpHandler = mcp.NewStreamableHTTPHandler(func(_ *http.Request) *mcp.Server { |
| 71 | return s.mcpServer |
| 72 | }, &mcp.StreamableHTTPOptions{DisableLocalhostProtection: true}) |
| 73 | |
| 74 | return s, nil |
| 75 | } |
| 76 | |
| 77 | // registerTools registers all MCP tools. |
| 78 | func (s *Server) registerTools() { |