Skip to main content
Glama
mcp_export_test.go5.92 kB
package cmd import ( "encoding/json" "os" "path/filepath" "strings" "testing" "github.com/babelcloud/gbox/packages/cli/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestDirExists(t *testing.T) { // Create a temporary directory for testing tempDir, err := os.MkdirTemp("", "gbox-test-*") require.NoError(t, err) defer os.RemoveAll(tempDir) // Test existing directory assert.True(t, dirExists(tempDir)) // Test non-existent directory nonExistentDir := filepath.Join(tempDir, "non-existent") assert.False(t, dirExists(nonExistentDir)) // Test file instead of directory tempFile := filepath.Join(tempDir, "test-file") err = os.WriteFile(tempFile, []byte("test"), 0644) require.NoError(t, err) assert.False(t, dirExists(tempFile)) } func TestGetPackagesRootPath(t *testing.T) { // This test is limited since it depends on the environment // Just verify the function runs without errors rootPath, err := getPackagesRootPath() // In a real environment, we should find a packages path // In test environment, it might fail depending on where tests are run if err == nil { // If successful, verify path contains "packages" and directory exists assert.Contains(t, rootPath, "packages") assert.True(t, dirExists(rootPath)) assert.True(t, dirExists(filepath.Join(rootPath, "mcp-server"))) } } func TestMergeAndMarshalConfigs(t *testing.T) { // Create a temporary directory tempDir, err := os.MkdirTemp("", "gbox-test-*") require.NoError(t, err) defer os.RemoveAll(tempDir) // Get the expected URL with /sse appended expectedURL := strings.TrimSuffix(config.GetMcpServerUrl(), "/") + "/sse" // Define the new config structure to be merged (using Command/Args) newConfig := McpConfig{ McpServers: map[string]McpServerEntry{ "gbox": { Command: "npx", Args: []string{"mcp-remote", expectedURL}, }, }, } newConfigRawJSON, err := json.Marshal(newConfig.McpServers["gbox"]) // Marshal just the entry for later use require.NoError(t, err) newConfigFullJSON, err := json.MarshalIndent(newConfig, "", " ") // Marshal the full structure require.NoError(t, err) // --- Test Case 1: Target file does not exist --- nonExistentPath := filepath.Join(tempDir, "non-existent.json") mergedJSON, err := mergeAndMarshalConfigs(nonExistentPath, newConfig) require.NoError(t, err) assert.JSONEq(t, string(newConfigFullJSON), string(mergedJSON), "Merge into non-existent file") // --- Test Case 2: Target file exists but is empty --- emptyPath := filepath.Join(tempDir, "empty.json") err = os.WriteFile(emptyPath, []byte{}, 0644) require.NoError(t, err) mergedJSON, err = mergeAndMarshalConfigs(emptyPath, newConfig) require.NoError(t, err) assert.JSONEq(t, string(newConfigFullJSON), string(mergedJSON), "Merge into empty file") // --- Test Case 3: Target file exists with other entries --- // Note: Test data uses Command/Args format for existing entries now otherEntriesPath := filepath.Join(tempDir, "other.json") existingData := `{ "mcpServers": { "other": { "command": "other-cmd", "args": ["other-arg", "http://some.url"] } } }` err = os.WriteFile(otherEntriesPath, []byte(existingData), 0644) require.NoError(t, err) mergedJSON, err = mergeAndMarshalConfigs(otherEntriesPath, newConfig) require.NoError(t, err) // Expected result combines old and new entries expectedCombined := GenericMcpConfig{ McpServers: map[string]json.RawMessage{ "other": json.RawMessage(`{"command":"other-cmd","args":["other-arg","http://some.url"]}`), "gbox": json.RawMessage(newConfigRawJSON), // Use the marshalled new entry }, } expectedCombinedJSON, _ := json.MarshalIndent(expectedCombined, "", " ") assert.JSONEq(t, string(expectedCombinedJSON), string(mergedJSON), "Merge with existing entry") // --- Test Case 4: Target file exists with the *same* entry key ("gbox") --- sameEntryPath := filepath.Join(tempDir, "same_entry.json") existingSameKeyData := `{ "mcpServers": { "gbox": { "command": "old-npx", "args": ["old-arg", "http://old-gbox-url:9999/sse"] }, "other": { "command": "other-cmd", "args": ["arg"] } } }` err = os.WriteFile(sameEntryPath, []byte(existingSameKeyData), 0644) require.NoError(t, err) mergedJSON, err = mergeAndMarshalConfigs(sameEntryPath, newConfig) require.NoError(t, err) // Expected result updates "gbox" and keeps "other" expectedUpdated := GenericMcpConfig{ McpServers: map[string]json.RawMessage{ "other": json.RawMessage(`{"command":"other-cmd","args":["arg"]}`), "gbox": json.RawMessage(newConfigRawJSON), // Use the marshalled new entry (which overwrites) }, } expectedUpdatedJSON, _ := json.MarshalIndent(expectedUpdated, "", " ") assert.JSONEq(t, string(expectedUpdatedJSON), string(mergedJSON), "Merge should update existing gbox entry") // --- Test Case 5: Target file contains invalid JSON --- invalidJSONPath := filepath.Join(tempDir, "invalid.json") err = os.WriteFile(invalidJSONPath, []byte(`{ "mcpServers": { "key": "value }`), 0644) // Missing closing brace require.NoError(t, err) _, err = mergeAndMarshalConfigs(invalidJSONPath, newConfig) require.Error(t, err) // Expect an error because merging cannot be done safely assert.Contains(t, err.Error(), "invalid JSON", "Error message should indicate invalid JSON") } func TestNewMcpExportCommand(t *testing.T) { cmd := NewMcpExportCommand() // Verify command basic properties assert.Equal(t, "export", cmd.Use) assert.Equal(t, "Export MCP configuration for Claude Desktop/Cursor (Android only)", cmd.Short) // Verify flag options mergeTo, err := cmd.Flags().GetString("merge-to") require.NoError(t, err) assert.Equal(t, "", mergeTo) dryRun, err := cmd.Flags().GetBool("dry-run") require.NoError(t, err) assert.Equal(t, false, dryRun) // The 'type' flag is removed, so we do not test it }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/babelcloud/gru-sandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server