mcp: split mcp into server and client for better option grouping (#5666)

This commit is contained in:
Denis Mishin 2025-06-24 10:21:32 -07:00 committed by GitHub
parent d36c48a2bc
commit db6449ecca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1156 additions and 934 deletions

View file

@ -212,15 +212,23 @@ type Policy struct {
// MCP is an experimental support for Model Context Protocol upstreams configuration
type MCP struct {
// exactly one of server or client should be specified
Server *MCPServer `mapstructure:"server" yaml:"server,omitempty" json:"server,omitempty"`
Client *MCPClient `mapstructure:"client" yaml:"client,omitempty" json:"client,omitempty"`
}
// MCPServer holds configuration for an MCP server route
type MCPServer struct {
// UpstreamOAuth2 specifies that before the request reaches the MCP upstream server, it should acquire an OAuth2 token
UpstreamOAuth2 *UpstreamOAuth2 `mapstructure:"upstream_oauth2" yaml:"upstream_oauth2,omitempty" json:"upstream_oauth2,omitempty"`
// PassUpstreamAccessToken indicates whether to pass the upstream access token in the `Authorization: Bearer` header that is suitable for calling the MCP routes
PassUpstreamAccessToken bool `mapstructure:"pass_upstream_access_token" yaml:"pass_upstream_access_token,omitempty" json:"pass_upstream_access_token,omitempty"`
// MaxRequestBytes is the maximum request body size in bytes that can be sent to the MCP server
MaxRequestBytes *uint32 `mapstructure:"max_request_bytes" yaml:"max_request_bytes,omitempty" json:"max_request_bytes,omitempty"`
}
func (p *MCP) GetMaxRequestBytes() uint32 {
// MCPClient holds configuration for an MCP client route
type MCPClient struct{}
func (p *MCPServer) GetMaxRequestBytes() uint32 {
if p == nil || p.MaxRequestBytes == nil {
return 4 * 1024
}
@ -228,13 +236,11 @@ func (p *MCP) GetMaxRequestBytes() uint32 {
}
// HasUpstreamOAuth2 checks if the route is for the MCP Server and if it has an upstream OAuth2 configuration
func (p *MCP) HasUpstreamOAuth2() bool {
return p != nil && p.UpstreamOAuth2 != nil
}
// IsUpstreamClientNeedsAccessToken checks if the route is for the MCP Client and if it needs to pass the upstream access token
func (p *MCP) IsUpstreamClientNeedsAccessToken() bool {
return p != nil && p.PassUpstreamAccessToken
func (p *MCP) GetServerUpstreamOAuth2() *UpstreamOAuth2 {
if p != nil && p.Server != nil {
return p.Server.UpstreamOAuth2
}
return nil
}
type UpstreamOAuth2 struct {
@ -756,6 +762,9 @@ func (p *Policy) Validate() error {
return fmt.Errorf("config: depends_on is limited to 5 additional redirect hosts, got %v", p.DependsOn)
}
if p.MCP != nil && p.MCP.Server == nil && p.MCP.Client == nil {
return fmt.Errorf("config: mcp must have either server or client set")
}
return nil
}
@ -893,12 +902,12 @@ func (p *Policy) IsForKubernetes() bool {
// IsMCPServer returns true if the route is for the Model Context Protocol upstream server.
func (p *Policy) IsMCPServer() bool {
return p != nil && p.MCP != nil && !p.MCP.PassUpstreamAccessToken
return p != nil && p.MCP != nil && p.MCP.Server != nil
}
// IsMCPClient returns true if the route is for the Model Context Protocol client application upstream.
func (p *Policy) IsMCPClient() bool {
return p != nil && p.MCP != nil && p.MCP.PassUpstreamAccessToken
return p != nil && p.MCP != nil && p.MCP.Client != nil
}
// IsTCP returns true if the route is for TCP.