mcp: make request headers available to tools (#333)
Add HTTP request headers to RequestExtra, so tools and other user-defined handlers can access them. Fixes #331.
This commit is contained in:
parent
48abccbf6b
commit
73b8a7f134
2 changed files with 10 additions and 9 deletions
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -400,6 +401,7 @@ type ServerRequest[P Params] struct {
|
||||||
// the transport layer.
|
// the transport layer.
|
||||||
type RequestExtra struct {
|
type RequestExtra struct {
|
||||||
TokenInfo *auth.TokenInfo // bearer token info (e.g. from OAuth) if any
|
TokenInfo *auth.TokenInfo // bearer token info (e.g. from OAuth) if any
|
||||||
|
Header http.Header // header from HTTP request, if any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ClientRequest[P]) isRequest() {}
|
func (*ClientRequest[P]) isRequest() {}
|
||||||
|
|
|
||||||
|
|
@ -580,10 +580,6 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
|
||||||
// This also requires access to the negotiated version, which would either be
|
// This also requires access to the negotiated version, which would either be
|
||||||
// set by the MCP-Protocol-Version header, or would require peeking into the
|
// set by the MCP-Protocol-Version header, or would require peeking into the
|
||||||
// session.
|
// session.
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("malformed payload: %v", err), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
incoming, _, err := readBatch(body)
|
incoming, _, err := readBatch(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("malformed payload: %v", err), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("malformed payload: %v", err), http.StatusBadRequest)
|
||||||
|
|
@ -592,17 +588,20 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
|
||||||
requests := make(map[jsonrpc.ID]struct{})
|
requests := make(map[jsonrpc.ID]struct{})
|
||||||
tokenInfo := auth.TokenInfoFromContext(req.Context())
|
tokenInfo := auth.TokenInfoFromContext(req.Context())
|
||||||
for _, msg := range incoming {
|
for _, msg := range incoming {
|
||||||
if req, ok := msg.(*jsonrpc.Request); ok {
|
if jreq, ok := msg.(*jsonrpc.Request); ok {
|
||||||
// Preemptively check that this is a valid request, so that we can fail
|
// Preemptively check that this is a valid request, so that we can fail
|
||||||
// the HTTP request. If we didn't do this, a request with a bad method or
|
// the HTTP request. If we didn't do this, a request with a bad method or
|
||||||
// missing ID could be silently swallowed.
|
// missing ID could be silently swallowed.
|
||||||
if _, err := checkRequest(req, serverMethodInfos); err != nil {
|
if _, err := checkRequest(jreq, serverMethodInfos); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Extra = &RequestExtra{TokenInfo: tokenInfo}
|
jreq.Extra = &RequestExtra{
|
||||||
if req.IsCall() {
|
TokenInfo: tokenInfo,
|
||||||
requests[req.ID] = struct{}{}
|
Header: req.Header,
|
||||||
|
}
|
||||||
|
if jreq.IsCall() {
|
||||||
|
requests[jreq.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue