@@ -2,42 +2,36 @@ package gateway
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
6- "io"
77 "net/http"
88 "strings"
99
10- "github.com/goccy/go-yaml "
10+ "github.com/docker/cagent/pkg/sync "
1111)
1212
1313const DockerCatalogURL = "https://desktop.docker.com/mcp/catalog/v3/catalog.yaml"
1414
15- func ParseServerRef (ref string ) string {
16- return strings .TrimPrefix (ref , "docker:" )
17- }
18-
19- func RequiredEnvVars (ctx context.Context , serverName , catalogURL string ) ([]Secret , error ) {
20- catalog , err := readCatalog (ctx , catalogURL )
15+ func RequiredEnvVars (ctx context.Context , serverName string ) ([]Secret , error ) {
16+ catalog , err := readCatalogOnce ()
2117 if err != nil {
22- return nil , err
18+ return nil , fmt . Errorf ( "failed to fetch MCP catalog: %w" , err )
2319 }
2420
2521 server , ok := catalog [serverName ]
2622 if ! ok {
27- return nil , fmt .Errorf ("MCP server %q not found in catalog %q " , serverName , catalogURL )
23+ return nil , fmt .Errorf ("MCP server %q not found in MCP catalog " , serverName )
2824 }
2925
3026 return server .Secrets , nil
3127}
3228
33- // TODO(dga): cache the catalog.
34- func readCatalog (ctx context.Context , url string ) (Catalog , error ) {
35- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , http .NoBody )
36- if err != nil {
37- return nil , err
38- }
29+ // Read the MCP Catalog only once and cache the result.
30+ var readCatalogOnce = sync .OnceErr (func () (Catalog , error ) {
31+ // Use the JSON version because it's 3x time faster to parse than YAML.
32+ url := strings .Replace (DockerCatalogURL , ".yaml" , ".json" , 1 )
3933
40- resp , err := http .DefaultClient . Do ( req )
34+ resp , err := http .Get ( url )
4135 if err != nil {
4236 return nil , err
4337 }
@@ -47,15 +41,10 @@ func readCatalog(ctx context.Context, url string) (Catalog, error) {
4741 return nil , fmt .Errorf ("failed to fetch URL: %s, status: %s" , url , resp .Status )
4842 }
4943
50- buf , err := io .ReadAll (resp .Body )
51- if err != nil {
52- return nil , err
53- }
54-
5544 var topLevel topLevel
56- if err := yaml . Unmarshal ( buf , & topLevel ); err != nil {
45+ if err := json . NewDecoder ( resp . Body ). Decode ( & topLevel ); err != nil {
5746 return nil , err
5847 }
5948
6049 return topLevel .Catalog , nil
61- }
50+ })
0 commit comments