@@ -9,7 +9,7 @@ MCP-Go provides client implementations for all supported transports. Each transp
9
9
| Transport | Best For | Connection | Real-time | Multi-client |
10
10
| -----------| ----------| ------------| -----------| --------------|
11
11
| ** STDIO** | CLI tools, desktop apps | Process pipes | No | No |
12
- | ** HTTP ** | Web services, APIs | HTTP requests | No | Yes |
12
+ | ** StreamableHTTP ** | Web services, APIs | HTTP requests | No | Yes |
13
13
| ** SSE** | Web apps, real-time | HTTP + EventSource | Yes | Yes |
14
14
| ** In-Process** | Testing, embedded | Direct calls | Yes | No |
15
15
@@ -244,31 +244,20 @@ var (
244
244
)
245
245
```
246
246
247
- ## HTTP Client
247
+ ## StreamableHTTP Client
248
248
249
- HTTP clients communicate with servers using traditional HTTP requests.
249
+ StreamableHTTP clients communicate with servers using traditional HTTP requests.
250
250
251
- ### Basic HTTP Client
251
+ ### Basic StreamableHTTP Client
252
252
253
253
``` go
254
- func createHTTPClient () {
255
- // Create HTTP client
256
- c := client.NewHTTPClient (" http://localhost:8080/mcp" )
254
+ func createStreamableHTTPClient () {
255
+ // Create StreamableHTTP client
256
+ c := client.NewStreamableHttpClient (" http://localhost:8080/mcp" )
257
257
defer c.Close ()
258
258
259
- // Set authentication
260
- c.SetHeader (" Authorization" , " Bearer your-token" )
261
- c.SetHeader (" X-API-Version" , " v1" )
262
-
263
- // Set timeout
264
- c.SetTimeout (30 * time.Second )
265
-
266
259
ctx := context.Background ()
267
260
268
- if err := c.Start (ctx); err != nil {
269
- return
270
- }
271
-
272
261
// Initialize
273
262
if err := c.Initialize (ctx); err != nil {
274
263
log.Fatal (err)
@@ -284,31 +273,30 @@ func createHTTPClient() {
284
273
}
285
274
```
286
275
287
- ### HTTP Client with Custom Configuration
276
+ ### StreamableHTTP Client with Custom Configuration
288
277
289
278
``` go
290
- func createCustomHTTPClient () {
291
- // Create custom HTTP client
292
- httpClient := &http.Client {
293
- Timeout: 30 * time.Second ,
294
- Transport: &http.Transport {
295
- MaxIdleConns: 100 ,
296
- MaxIdleConnsPerHost: 10 ,
297
- IdleConnTimeout: 90 * time.Second ,
298
- TLSClientConfig: &tls.Config {
299
- InsecureSkipVerify: false ,
279
+ func createCustomStreamableHTTPClient () {
280
+ // Create StreamableHTTP client with options
281
+ c := client.NewStreamableHttpClient (" https://api.example.com/mcp" ,
282
+ transport.WithHTTPTimeout (30 *time.Second ),
283
+ transport.WithHTTPHeaders (map [string ]string {
284
+ " User-Agent" : " MyApp/1.0" ,
285
+ " Accept" : " application/json" ,
286
+ }),
287
+ transport.WithHTTPBasicClient (&http.Client {
288
+ Transport: &http.Transport {
289
+ MaxIdleConns: 100 ,
290
+ MaxIdleConnsPerHost: 10 ,
291
+ IdleConnTimeout: 90 * time.Second ,
292
+ TLSClientConfig: &tls.Config {
293
+ InsecureSkipVerify: false ,
294
+ },
300
295
},
301
- },
302
- }
303
-
304
- // Create MCP client with custom HTTP client
305
- c := client.NewHTTPClientWithClient (" https://api.example.com/mcp" , httpClient)
296
+ }),
297
+ )
306
298
defer c.Close ()
307
299
308
- // Set custom headers
309
- c.SetHeader (" User-Agent" , " MyApp/1.0" )
310
- c.SetHeader (" Accept" , " application/json" )
311
-
312
300
ctx := context.Background ()
313
301
314
302
if err := c.Initialize (ctx); err != nil {
@@ -319,68 +307,28 @@ func createCustomHTTPClient() {
319
307
}
320
308
```
321
309
322
- ### HTTP Authentication
310
+ ### StreamableHTTP Authentication
323
311
324
312
``` go
325
- type AuthenticatedHTTPClient struct {
326
- client *client.HTTPClient
327
- tokenSource TokenSource
328
- mutex sync.RWMutex
329
- }
330
-
331
- type TokenSource interface {
332
- Token () (string , error )
333
- Refresh () error
334
- }
335
-
336
- func NewAuthenticatedHTTPClient (baseURL string , tokenSource TokenSource ) *AuthenticatedHTTPClient {
337
- return &AuthenticatedHTTPClient{
338
- client: client.NewHTTPClient (baseURL),
339
- tokenSource: tokenSource,
340
- }
341
- }
342
-
343
- func (ahc *AuthenticatedHTTPClient ) ensureValidToken () error {
344
- ahc.mutex .Lock ()
345
- defer ahc.mutex .Unlock ()
346
-
347
- token , err := ahc.tokenSource .Token ()
348
- if err != nil {
349
- // Try to refresh token
350
- if refreshErr := ahc.tokenSource .Refresh (); refreshErr != nil {
351
- return fmt.Errorf (" failed to refresh token: % w" , refreshErr)
352
- }
353
-
354
- token, err = ahc.tokenSource .Token ()
355
- if err != nil {
356
- return fmt.Errorf (" failed to get token after refresh: % w" , err)
357
- }
358
- }
359
-
360
- ahc.client .SetHeader (" Authorization" , " Bearer " +token)
361
- return nil
362
- }
363
-
364
- func (ahc *AuthenticatedHTTPClient ) CallTool (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
365
- if err := ahc.ensureValidToken (); err != nil {
366
- return nil , err
367
- }
368
-
369
- result , err := ahc.client .CallTool (ctx, req)
370
- if err != nil && isAuthError (err) {
371
- // Token might be expired, refresh and retry
372
- if refreshErr := ahc.tokenSource .Refresh (); refreshErr != nil {
373
- return nil , fmt.Errorf (" authentication failed: % w" , err)
374
- }
313
+ func createAuthenticatedStreamableHTTPClient () {
314
+ // Create StreamableHTTP client with OAuth
315
+ c := client.NewStreamableHttpClient (" http://localhost:8080/mcp" ,
316
+ transport.WithHTTPOAuth (transport.OAuthConfig {
317
+ ClientID: " your-client-id" ,
318
+ ClientSecret: " your-client-secret" ,
319
+ TokenURL: " https://auth.example.com/token" ,
320
+ Scopes: []string {" mcp:read" , " mcp:write" },
321
+ }),
322
+ )
323
+ defer c.Close ()
375
324
376
- if err := ahc.ensureValidToken (); err != nil {
377
- return nil , err
378
- }
325
+ ctx := context.Background ()
379
326
380
- return ahc.client .CallTool (ctx, req)
327
+ if err := c.Initialize (ctx); err != nil {
328
+ log.Fatal (err)
381
329
}
382
330
383
- return result, err
331
+ // Use client...
384
332
}
385
333
386
334
func isAuthError (err error ) bool {
@@ -389,21 +337,21 @@ func isAuthError(err error) bool {
389
337
}
390
338
```
391
339
392
- ### HTTP Connection Pooling
340
+ ### StreamableHTTP Connection Pooling
393
341
394
342
``` go
395
- type HTTPClientPool struct {
396
- clients chan *client.HTTPClient
397
- factory func () *client.HTTPClient
343
+ type StreamableHTTPClientPool struct {
344
+ clients chan *client.Client
345
+ factory func () *client.Client
398
346
maxSize int
399
347
}
400
348
401
- func NewHTTPClientPool (baseURL string , maxSize int ) *HTTPClientPool {
402
- pool := &HTTPClientPool {
403
- clients: make (chan *client.HTTPClient , maxSize),
349
+ func NewStreamableHTTPClientPool (baseURL string , maxSize int ) *StreamableHTTPClientPool {
350
+ pool := &StreamableHTTPClientPool {
351
+ clients: make (chan *client.Client , maxSize),
404
352
maxSize: maxSize,
405
- factory: func () *client.HTTPClient {
406
- return client.NewHTTPClient (baseURL)
353
+ factory: func () *client.Client {
354
+ return client.NewStreamableHttpClient (baseURL)
407
355
},
408
356
}
409
357
@@ -415,7 +363,7 @@ func NewHTTPClientPool(baseURL string, maxSize int) *HTTPClientPool {
415
363
return pool
416
364
}
417
365
418
- func (pool *HTTPClientPool ) Get () *client .HTTPClient {
366
+ func (pool *StreamableHTTPClientPool ) Get () *client .Client {
419
367
select {
420
368
case c := <- pool.clients :
421
369
return c
@@ -424,7 +372,7 @@ func (pool *HTTPClientPool) Get() *client.HTTPClient {
424
372
}
425
373
}
426
374
427
- func (pool *HTTPClientPool ) Put (c *client .HTTPClient ) {
375
+ func (pool *StreamableHTTPClientPool ) Put (c *client .Client ) {
428
376
select {
429
377
case pool.clients <- c:
430
378
default :
@@ -433,7 +381,7 @@ func (pool *HTTPClientPool) Put(c *client.HTTPClient) {
433
381
}
434
382
}
435
383
436
- func (pool *HTTPClientPool ) CallTool (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
384
+ func (pool *StreamableHTTPClientPool ) CallTool (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
437
385
c := pool.Get ()
438
386
defer pool.Put (c)
439
387
@@ -865,7 +813,7 @@ func SelectTransport(req TransportRequirements) string {
865
813
return " sse"
866
814
867
815
case req.NetworkRequired && req.MultiClient :
868
- return " http "
816
+ return " streamablehttp "
869
817
870
818
default :
871
819
return " stdio" // Default fallback
@@ -926,8 +874,8 @@ func (cf *ClientFactory) SetStdioConfig(command string, args ...string) {
926
874
}
927
875
}
928
876
929
- func (cf *ClientFactory ) SetHTTPConfig (baseURL string , headers map [string ]string ) {
930
- cf.configs [" http " ] = struct {
877
+ func (cf *ClientFactory ) SetStreamableHTTPConfig (baseURL string , headers map [string ]string ) {
878
+ cf.configs [" streamablehttp " ] = struct {
931
879
BaseURL string
932
880
Headers map [string ]string
933
881
}{
@@ -955,20 +903,21 @@ func (cf *ClientFactory) CreateClient(transport string) (client.Client, error) {
955
903
}
956
904
return client.NewStdioClientWithOptions (config)
957
905
958
- case " http " :
959
- config , ok := cf.configs [" http " ].(struct {
906
+ case " streamablehttp " :
907
+ config , ok := cf.configs [" streamablehttp " ].(struct {
960
908
BaseURL string
961
909
Headers map [string ]string
962
910
})
963
911
if !ok {
964
- return nil , fmt.Errorf (" http config not set" )
912
+ return nil , fmt.Errorf (" streamablehttp config not set" )
965
913
}
966
914
967
- c := client. NewHTTPClient (config. BaseURL )
968
- for key , value := range config.Headers {
969
- c. SetHeader (key, value )
915
+ options := []transport. StreamableHTTPCOption {}
916
+ if len ( config.Headers ) > 0 {
917
+ options = append (options, transport. WithHTTPHeaders (config. Headers ) )
970
918
}
971
- return c, nil
919
+
920
+ return client.NewStreamableHttpClient (config.BaseURL , options...), nil
972
921
973
922
case " sse" :
974
923
config , ok := cf.configs [" sse" ].(struct {
@@ -979,11 +928,12 @@ func (cf *ClientFactory) CreateClient(transport string) (client.Client, error) {
979
928
return nil , fmt.Errorf (" sse config not set" )
980
929
}
981
930
982
- c := client. NewSSEClient (config. BaseURL )
983
- for key , value := range config.Headers {
984
- c. SetHeader (key, value )
931
+ options := []transport. ClientOption {}
932
+ if len ( config.Headers ) > 0 {
933
+ options = append (options, transport. WithHeaders (config. Headers ) )
985
934
}
986
- return c, nil
935
+
936
+ return client.NewSSEMCPClient (config.BaseURL , options...)
987
937
988
938
default :
989
939
return nil , fmt.Errorf (" unknown transport: %s " , transport)
@@ -996,7 +946,7 @@ func demonstrateClientFactory() {
996
946
997
947
// Configure transports
998
948
factory.SetStdioConfig (" go" , " run" , " server.go" )
999
- factory.SetHTTPConfig (" http://localhost:8080/mcp" , map [string ]string {
949
+ factory.SetStreamableHTTPConfig (" http://localhost:8080/mcp" , map [string ]string {
1000
950
" Authorization" : " Bearer token" ,
1001
951
})
1002
952
factory.SetSSEConfig (" http://localhost:8080/mcp/sse" , map [string ]string {
0 commit comments