@@ -5,8 +5,23 @@ import (
5
5
"fmt"
6
6
"net/http"
7
7
"os"
8
+
9
+ "github.com/golang/glog"
8
10
)
9
11
12
+ // contextKey type for context value storage
13
+ type contextKey int
14
+
15
+ const (
16
+ // requestHeader key used by mcp-go framework to store HTTP headers in context
17
+ requestHeader contextKey = iota
18
+ )
19
+
20
+ // RequestHeaderKey returns the context key used for storing HTTP headers
21
+ func RequestHeaderKey () contextKey {
22
+ return requestHeader
23
+ }
24
+
10
25
const (
11
26
// SSE transport header for OCM offline token
12
27
// NOTE: http.Header keys are stored in canonical format, hence the different casing required here.
@@ -19,12 +34,16 @@ const (
19
34
20
35
// ExtractTokenFromSSE extracts OCM offline token from X-OCM-OFFLINE-TOKEN header
21
36
func ExtractTokenFromSSE (headers map [string ]string ) (string , error ) {
37
+ glog .V (3 ).Infof ("SSE headers received: %+v" , headers )
38
+
22
39
// Try exact header name first
23
40
token , exists := headers [SSETokenHeader ]
24
41
if exists && token != "" {
42
+ glog .V (3 ).Infof ("Found OCM token in header %s" , SSETokenHeader )
25
43
return token , nil
26
44
}
27
45
46
+ glog .Warningf ("Missing or empty %s header in SSE request. Available headers: %+v" , SSETokenHeader , headers )
28
47
return "" , fmt .Errorf ("missing or empty %s header" , SSETokenHeader )
29
48
}
30
49
@@ -39,57 +58,95 @@ func ExtractTokenFromStdio() (string, error) {
39
58
40
59
// ExtractTokenFromContext extracts OCM offline token from context based on transport mode
41
60
func ExtractTokenFromContext (ctx context.Context , transport string ) (string , error ) {
61
+ glog .V (2 ).Infof ("Extracting token for transport mode: %s" , transport )
62
+
42
63
switch transport {
43
64
case "stdio" :
44
65
return ExtractTokenFromStdio ()
45
66
case "sse" :
46
67
// For SSE transport, extract token from HTTP headers in the context
47
- if headers := extractHeadersFromContext (ctx ); headers != nil {
68
+ headers := extractHeadersFromContext (ctx )
69
+ if headers != nil {
70
+ glog .V (2 ).Infof ("Headers found in context for SSE transport" )
48
71
if token , err := ExtractTokenFromSSE (headers ); err == nil {
49
72
return token , nil
73
+ } else {
74
+ glog .Warningf ("Failed to extract token from SSE headers: %v" , err )
50
75
}
76
+ } else {
77
+ glog .Warningf ("No headers found in context for SSE transport" )
51
78
}
52
79
53
80
// Fallback to environment variable for MVP compatibility
54
81
token := os .Getenv (StdioTokenEnv )
55
82
if token == "" {
56
- return "" , fmt .Errorf ("SSE transport requires %s header or %s environment variable" , SSETokenHeader , StdioTokenEnv )
83
+ err := fmt .Errorf ("SSE transport requires %s header or %s environment variable" , SSETokenHeader , StdioTokenEnv )
84
+ glog .Errorf ("Authentication failed: %v" , err )
85
+ return "" , err
57
86
}
87
+ glog .V (2 ).Infof ("Using fallback environment variable for SSE transport" )
58
88
return token , nil
59
89
default :
60
- return "" , fmt .Errorf ("unsupported transport mode: %s" , transport )
90
+ err := fmt .Errorf ("unsupported transport mode: %s" , transport )
91
+ glog .Errorf ("Authentication failed: %v" , err )
92
+ return "" , err
61
93
}
62
94
}
63
95
64
96
// extractHeadersFromContext extracts HTTP headers from the context
65
97
// This function looks for headers stored in the context by the mcp-go SSE server
66
98
func extractHeadersFromContext (ctx context.Context ) map [string ]string {
67
- // Check for headers stored in context by mcp-go framework
99
+ glog .V (2 ).Infof ("Extracting headers from context" )
100
+
101
+ // Check for headers stored by mcp-go framework using requestHeader key
102
+ if headerValue := ctx .Value (requestHeader ); headerValue != nil {
103
+ glog .V (2 ).Infof ("Found requestHeader context value" )
104
+ if httpHeader , ok := headerValue .(http.Header ); ok {
105
+ headers := make (map [string ]string )
106
+ for key , values := range httpHeader {
107
+ if len (values ) > 0 {
108
+ headers [key ] = values [0 ]
109
+ }
110
+ }
111
+ glog .V (2 ).Infof ("Extracted %d headers from mcp-go context" , len (headers ))
112
+ return headers
113
+ } else {
114
+ glog .V (2 ).Infof ("requestHeader context value is not http.Header type: %T" , headerValue )
115
+ }
116
+ } else {
117
+ glog .V (2 ).Infof ("No requestHeader found in context" )
118
+ }
119
+
120
+ // Fallback: Check for headers stored as map[string]string (legacy)
68
121
if headers , ok := ctx .Value ("headers" ).(map [string ]string ); ok {
122
+ glog .V (2 ).Infof ("Found legacy headers map in context with %d entries" , len (headers ))
69
123
return headers
70
124
}
71
125
72
- // Check for HTTP request in context
126
+ // Fallback: Check for HTTP request in context
73
127
if req , ok := ctx .Value ("http.request" ).(* http.Request ); ok {
74
128
headers := make (map [string ]string )
75
129
for key , values := range req .Header {
76
130
if len (values ) > 0 {
77
131
headers [key ] = values [0 ]
78
132
}
79
133
}
134
+ glog .V (2 ).Infof ("Extracted %d headers from http.request context" , len (headers ))
80
135
return headers
81
136
}
82
137
83
- // Check for request context pattern used by some HTTP frameworks
138
+ // Fallback: Check for request context pattern used by some HTTP frameworks
84
139
if req , ok := ctx .Value ("request" ).(* http.Request ); ok {
85
140
headers := make (map [string ]string )
86
141
for key , values := range req .Header {
87
142
if len (values ) > 0 {
88
143
headers [key ] = values [0 ]
89
144
}
90
145
}
146
+ glog .V (2 ).Infof ("Extracted %d headers from request context" , len (headers ))
91
147
return headers
92
148
}
93
149
150
+ glog .V (2 ).Infof ("No headers found in any context format" )
94
151
return nil
95
152
}
0 commit comments