Files
1Panel/agent/utils/mcpapi/request.go
T
蘭 d7355f3ccc feat(mcp): add 1Panel MCP and enhance MCP credential management (#14189)
* feat(mcp): add 1Panel MCP and enhance MCP credential management

* feat(i18n): implement MCP document localization and remove legacy code
2026-10-26 13:59:49 +08:00

80 lines
2.2 KiB
Go

package mcpapi
import (
"context"
"net"
"net/http"
"strconv"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/google/uuid"
)
const (
InvocationHeader = "X-Panel-MCP-Invocation"
NodeHeader = "X-Panel-MCP-Node"
MethodHeader = "X-Panel-MCP-Method"
PathHeader = "X-Panel-MCP-Path"
CapabilitiesPath = "/api/v2/internal/mcp/capabilities"
ContractVersion = 4
)
type verifiedNodeTransportKey struct{}
func BindVerifiedNodeTransport(request *http.Request) *http.Request {
if request.TLS == nil || !request.TLS.HandshakeComplete || len(request.TLS.VerifiedChains) == 0 {
return request
}
return request.WithContext(context.WithValue(request.Context(), verifiedNodeTransportKey{}, request.TLS))
}
func validNodeID(id string) bool {
if id == "local" {
return true
}
value, err := strconv.ParseUint(id, 10, 64)
return err == nil && value != 0 && strconv.FormatUint(value, 10) == id
}
func TrustedTransport(request *http.Request) bool {
if global.IsMaster {
local, ok := request.Context().Value(http.LocalAddrContextKey).(net.Addr)
return ok && local.Network() == "unix"
}
verified := request.Context().Value(verifiedNodeTransportKey{})
return request.TLS != nil && verified == request.TLS
}
func Check(request *http.Request) (present, trusted bool) {
present = false
for _, name := range []string{InvocationHeader, NodeHeader, MethodHeader, PathHeader} {
if len(request.Header.Values(name)) != 0 {
present = true
}
}
if !present {
return false, false
}
for _, name := range []string{InvocationHeader, NodeHeader, MethodHeader, PathHeader} {
if len(request.Header.Values(name)) != 1 {
return true, false
}
}
if _, err := uuid.Parse(request.Header.Get(InvocationHeader)); err != nil {
return true, false
}
nodeID := request.Header.Get(NodeHeader)
if !validNodeID(nodeID) || request.Header.Get(MethodHeader) != request.Method || request.Header.Get(PathHeader) != request.URL.Path || request.URL.RawQuery != "" {
return true, false
}
return true, TrustedTransport(request) && ((nodeID == "local") == global.IsMaster)
}
func NodeID(request *http.Request) (string, bool) {
_, trusted := Check(request)
if !trusted {
return "", false
}
return request.Header.Get(NodeHeader), true
}