1
+ package catalog
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "fmt"
7
+ "os"
8
+ "path/filepath"
9
+
10
+ "gopkg.in/yaml.v3"
11
+
12
+ "github.com/docker/mcp-gateway/cmd/docker-mcp/internal/catalog"
13
+ "github.com/docker/mcp-gateway/cmd/docker-mcp/internal/user"
14
+ )
15
+
16
+ // Export exports a configured catalog to a file
17
+ // This function only allows exporting user-managed catalogs, not the Docker catalog
18
+ func Export (ctx context.Context , catalogName , outputPath string ) error {
19
+ // Validate that we're not trying to export the Docker catalog
20
+ if catalogName == "docker-mcp" || catalogName == "docker-mcp.yaml" {
21
+ return fmt .Errorf ("cannot export the Docker MCP catalog as it is managed by Docker" )
22
+ }
23
+
24
+ // Get configured catalogs to verify the catalog exists
25
+ configuredCatalogs , err := getConfiguredCatalogs ()
26
+ if err != nil {
27
+ return fmt .Errorf ("failed to read configured catalogs: %w" , err )
28
+ }
29
+
30
+ // Check if the catalog exists in the configured catalogs
31
+ catalogFileName := catalogName + ".yaml"
32
+ found := false
33
+ for _ , configuredCatalog := range configuredCatalogs {
34
+ if configuredCatalog == catalogFileName {
35
+ found = true
36
+ break
37
+ }
38
+ }
39
+
40
+ if ! found {
41
+ return fmt .Errorf ("catalog '%s' not found in configured catalogs" , catalogName )
42
+ }
43
+
44
+ // Read the catalog file
45
+ homeDir , err := user .HomeDir ()
46
+ if err != nil {
47
+ return fmt .Errorf ("failed to get home directory: %w" , err )
48
+ }
49
+
50
+ catalogPath := filepath .Join (homeDir , ".docker" , "mcp" , "catalogs" , catalogFileName )
51
+ catalogData , err := os .ReadFile (catalogPath )
52
+ if err != nil {
53
+ return fmt .Errorf ("failed to read catalog file: %w" , err )
54
+ }
55
+
56
+ // Parse the catalog to validate it
57
+ var catalogContent catalog.Catalog
58
+ if err := yaml .Unmarshal (catalogData , & catalogContent ); err != nil {
59
+ return fmt .Errorf ("failed to parse catalog: %w" , err )
60
+ }
61
+
62
+ // Create output directory if it doesn't exist
63
+ outputDir := filepath .Dir (outputPath )
64
+ if err := os .MkdirAll (outputDir , 0755 ); err != nil {
65
+ return fmt .Errorf ("failed to create output directory: %w" , err )
66
+ }
67
+
68
+ // Write the catalog to the output file
69
+ if err := os .WriteFile (outputPath , catalogData , 0644 ); err != nil {
70
+ return fmt .Errorf ("failed to write export file: %w" , err )
71
+ }
72
+
73
+ fmt .Printf ("Catalog '%s' exported to '%s'\n " , catalogName , outputPath )
74
+ return nil
75
+ }
76
+
77
+ // Helper function to get configured catalogs (same logic as in internal/catalog)
78
+ func getConfiguredCatalogs () ([]string , error ) {
79
+ homeDir , err := user .HomeDir ()
80
+ if err != nil {
81
+ return nil , fmt .Errorf ("failed to get home directory: %w" , err )
82
+ }
83
+
84
+ catalogRegistryPath := filepath .Join (homeDir , ".docker" , "mcp" , "catalog.json" )
85
+
86
+ // Read the catalog registry file
87
+ data , err := os .ReadFile (catalogRegistryPath )
88
+ if err != nil {
89
+ if os .IsNotExist (err ) {
90
+ return []string {}, nil // No configured catalogs, return empty list
91
+ }
92
+ return nil , fmt .Errorf ("failed to read catalog registry: %w" , err )
93
+ }
94
+
95
+ // Parse the registry
96
+ var registry struct {
97
+ Catalogs map [string ]struct {
98
+ DisplayName string `json:"displayName"`
99
+ URL string `json:"url"`
100
+ LastUpdate string `json:"lastUpdate"`
101
+ } `json:"catalogs"`
102
+ }
103
+
104
+ if err := json .Unmarshal (data , & registry ); err != nil {
105
+ return nil , fmt .Errorf ("failed to parse catalog registry: %w" , err )
106
+ }
107
+
108
+ // Convert catalog names to file paths
109
+ var catalogFiles []string
110
+ for catalogName := range registry .Catalogs {
111
+ catalogFiles = append (catalogFiles , catalogName + ".yaml" )
112
+ }
113
+
114
+ return catalogFiles , nil
115
+ }
0 commit comments