Skip to content

Commit 4ffef57

Browse files
authored
Merge branch 'main' into custom-helm-chart-values-README-update
2 parents b7636da + 16972b2 commit 4ffef57

File tree

9 files changed

+91
-37
lines changed

9 files changed

+91
-37
lines changed

.github/workflows/verify-docgen.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ jobs:
1515
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
1616
with:
1717
go-version-file: go.mod
18+
- name: Install swag
19+
run: go install github.com/swaggo/swag/v2/cmd/swag@latest
1820
- run: ./cmd/help/verify.sh

cmd/help/verify.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
#!/usr/bin/env bash
22
set -e
33

4-
# Verify that generated Markdown docs are up-to-date.
4+
# Verify that generated CLI docs are up-to-date.
55
tmpdir=$(mktemp -d)
66
go run cmd/help/main.go --dir "$tmpdir"
77
diff -Naur -I "^ date:" "$tmpdir" docs/cli/
8+
9+
# Generate API docs in temp directory that mimics the final structure
10+
api_tmpdir=$(mktemp -d)
11+
mkdir -p "$api_tmpdir/server"
12+
swag init -g pkg/api/server.go --v3.1 -o "$api_tmpdir/server"
13+
# Exclude README.md from diff as it's manually maintained
14+
diff -Naur --exclude="README.md" "$api_tmpdir/server" docs/server/
15+
816
echo "######################################################################################"
917
echo "If diffs are found, please run: \`task docs\` to regenerate the docs."
1018
echo "######################################################################################"

cmd/thv/app/mcp.go

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/stacklok/toolhive/pkg/transport/streamable"
2020
"github.com/stacklok/toolhive/pkg/transport/types"
2121
"github.com/stacklok/toolhive/pkg/versions"
22+
"github.com/stacklok/toolhive/pkg/workloads"
2223
)
2324

2425
var (
@@ -86,7 +87,7 @@ func newMCPCommand() *cobra.Command {
8687
}
8788

8889
func addMCPFlags(cmd *cobra.Command) {
89-
cmd.Flags().StringVar(&mcpServerURL, "server", "", "MCP server URL (required)")
90+
cmd.Flags().StringVar(&mcpServerURL, "server", "", "MCP server URL or name from ToolHive registry (required)")
9091
cmd.Flags().StringVar(&mcpFormat, "format", FormatText, "Output format (json or text)")
9192
cmd.Flags().DurationVar(&mcpTimeout, "timeout", 30*time.Second, "Connection timeout")
9293
cmd.Flags().StringVar(&mcpTransport, "transport", "auto", "Transport type (auto, sse, streamable-http)")
@@ -98,7 +99,13 @@ func mcpListCmdFunc(cmd *cobra.Command, _ []string) error {
9899
ctx, cancel := context.WithTimeout(cmd.Context(), mcpTimeout)
99100
defer cancel()
100101

101-
mcpClient, err := createMCPClient()
102+
// Resolve server URL if it's a name
103+
serverURL, err := resolveServerURL(ctx, mcpServerURL)
104+
if err != nil {
105+
return err
106+
}
107+
108+
mcpClient, err := createMCPClient(serverURL)
102109
if err != nil {
103110
return err
104111
}
@@ -143,7 +150,13 @@ func mcpListToolsCmdFunc(cmd *cobra.Command, _ []string) error {
143150
ctx, cancel := context.WithTimeout(cmd.Context(), mcpTimeout)
144151
defer cancel()
145152

146-
mcpClient, err := createMCPClient()
153+
// Resolve server URL if it's a name
154+
serverURL, err := resolveServerURL(ctx, mcpServerURL)
155+
if err != nil {
156+
return err
157+
}
158+
159+
mcpClient, err := createMCPClient(serverURL)
147160
if err != nil {
148161
return err
149162
}
@@ -166,7 +179,13 @@ func mcpListResourcesCmdFunc(cmd *cobra.Command, _ []string) error {
166179
ctx, cancel := context.WithTimeout(cmd.Context(), mcpTimeout)
167180
defer cancel()
168181

169-
mcpClient, err := createMCPClient()
182+
// Resolve server URL if it's a name
183+
serverURL, err := resolveServerURL(ctx, mcpServerURL)
184+
if err != nil {
185+
return err
186+
}
187+
188+
mcpClient, err := createMCPClient(serverURL)
170189
if err != nil {
171190
return err
172191
}
@@ -189,7 +208,13 @@ func mcpListPromptsCmdFunc(cmd *cobra.Command, _ []string) error {
189208
ctx, cancel := context.WithTimeout(cmd.Context(), mcpTimeout)
190209
defer cancel()
191210

192-
mcpClient, err := createMCPClient()
211+
// Resolve server URL if it's a name
212+
serverURL, err := resolveServerURL(ctx, mcpServerURL)
213+
if err != nil {
214+
return err
215+
}
216+
217+
mcpClient, err := createMCPClient(serverURL)
193218
if err != nil {
194219
return err
195220
}
@@ -207,19 +232,48 @@ func mcpListPromptsCmdFunc(cmd *cobra.Command, _ []string) error {
207232
return outputMCPData(map[string]interface{}{"prompts": result.Prompts}, mcpFormat)
208233
}
209234

235+
// resolveServerURL resolves a server name to a URL or returns the URL if it's already a URL
236+
func resolveServerURL(ctx context.Context, serverInput string) (string, error) {
237+
// Check if it's already a URL
238+
if strings.HasPrefix(serverInput, "http://") || strings.HasPrefix(serverInput, "https://") {
239+
return serverInput, nil
240+
}
241+
242+
// Try to get the workload by name
243+
manager, err := workloads.NewManager(ctx)
244+
if err != nil {
245+
return "", fmt.Errorf("failed to create workload manager: %w", err)
246+
}
247+
248+
workload, err := manager.GetWorkload(ctx, serverInput)
249+
if err != nil {
250+
return "", fmt.Errorf(
251+
"server '%s' not found in running workloads. "+
252+
"Please ensure the server is running or provide a valid URL", serverInput)
253+
}
254+
255+
// Check if the workload is running
256+
if workload.Status != "running" {
257+
return "", fmt.Errorf("server '%s' is not running (status: %s). "+
258+
"Please start it first using 'thv run %s'", serverInput, workload.Status, serverInput)
259+
}
260+
261+
return workload.URL, nil
262+
}
263+
210264
// createMCPClient creates an MCP client based on the server URL and transport type
211-
func createMCPClient() (*client.Client, error) {
212-
transportType := determineTransportType(mcpServerURL, mcpTransport)
265+
func createMCPClient(serverURL string) (*client.Client, error) {
266+
transportType := determineTransportType(serverURL, mcpTransport)
213267

214268
switch transportType {
215269
case types.TransportTypeSSE:
216-
mcpClient, err := client.NewSSEMCPClient(mcpServerURL)
270+
mcpClient, err := client.NewSSEMCPClient(serverURL)
217271
if err != nil {
218272
return nil, fmt.Errorf("failed to create SSE MCP client: %w", err)
219273
}
220274
return mcpClient, nil
221275
case types.TransportTypeStreamableHTTP:
222-
mcpClient, err := client.NewStreamableHttpClient(mcpServerURL)
276+
mcpClient, err := client.NewStreamableHttpClient(serverURL)
223277
if err != nil {
224278
return nil, fmt.Errorf("failed to create Streamable HTTP MCP client: %w", err)
225279
}

docs/cli/thv_mcp_list.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/cli/thv_mcp_list_prompts.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/cli/thv_mcp_list_resources.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/cli/thv_mcp_list_tools.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/migration/default_group.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,25 @@ func (m *DefaultGroupMigrator) Migrate(ctx context.Context) error {
2222
return fmt.Errorf("failed to initialize managers: %w", err)
2323
}
2424

25-
// Create default group
26-
if err := m.createDefaultGroup(ctx); err != nil {
27-
return fmt.Errorf("failed to create default group: %w", err)
25+
// Create default group if it doesn't exist
26+
defaultGroupExists, err := m.groupManager.Exists(ctx, groups.DefaultGroupName)
27+
if err != nil {
28+
return fmt.Errorf("failed to check if default group exists: %w", err)
29+
}
30+
if !defaultGroupExists {
31+
if err := m.createDefaultGroup(ctx); err != nil {
32+
return fmt.Errorf("failed to create default group: %w", err)
33+
}
2834
}
2935

30-
// Migrate workloads to default group
36+
// Migrate workloads to default group if they don't have a group assigned
3137
migratedCount, err := m.migrateWorkloadsToDefaultGroup(ctx)
3238
if err != nil {
3339
return fmt.Errorf("failed to migrate workloads: %w", err)
3440
}
3541

3642
if migratedCount > 0 {
3743
fmt.Printf("\nSuccessfully migrated %d workloads to default group '%s'\n", migratedCount, groups.DefaultGroupName)
38-
} else {
39-
fmt.Println("No workloads needed migration to default group")
4044
}
4145

4246
// Migrate client configurations from global config to default group
@@ -108,12 +112,10 @@ func (m *DefaultGroupMigrator) migrateClientConfigs(ctx context.Context) error {
108112

109113
// If there are no registered clients, nothing to migrate
110114
if len(appConfig.Clients.RegisteredClients) == 0 {
111-
logger.Infof("No client configurations to migrate")
115+
logger.Debugf("No client configurations to migrate")
112116
return nil
113117
}
114118

115-
fmt.Printf("Migrating %d client configurations to default group...\n", len(appConfig.Clients.RegisteredClients))
116-
117119
// Get the default group
118120
defaultGroup, err := m.groupManager.Get(ctx, groups.DefaultGroupName)
119121
if err != nil {
@@ -151,10 +153,10 @@ func (m *DefaultGroupMigrator) migrateClientConfigs(ctx context.Context) error {
151153
if err != nil {
152154
logger.Warnf("Failed to clear global client configurations after migration: %v", err)
153155
} else {
154-
logger.Infof("Cleared global client configurations")
156+
logger.Debugf("Cleared global client configurations")
155157
}
156158
} else {
157-
logger.Infof("No client configurations needed migration")
159+
logger.Debugf("No client configurations needed migration")
158160
}
159161

160162
return nil

pkg/migration/migration.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ package migration
33

44
import (
55
"context"
6-
"fmt"
76
"sync"
87

9-
"github.com/stacklok/toolhive/pkg/config"
108
"github.com/stacklok/toolhive/pkg/logger"
119
)
1210

@@ -17,13 +15,6 @@ var migrationOnce sync.Once
1715
// This is called once at application startup
1816
func CheckAndPerformDefaultGroupMigration() {
1917
migrationOnce.Do(func() {
20-
appConfig := config.GetConfig()
21-
22-
// Check if default group migration has already been performed
23-
if appConfig.DefaultGroupMigration {
24-
return
25-
}
26-
2718
if err := performDefaultGroupMigration(); err != nil {
2819
logger.Errorf("Failed to perform default group migration: %v", err)
2920
return
@@ -33,9 +24,6 @@ func CheckAndPerformDefaultGroupMigration() {
3324

3425
// performDefaultGroupMigration migrates all existing workloads to the default group
3526
func performDefaultGroupMigration() error {
36-
fmt.Println("Migrating existing workloads to default group...")
37-
fmt.Println()
38-
3927
migrator := &DefaultGroupMigrator{}
4028
return migrator.Migrate(context.Background())
4129
}

0 commit comments

Comments
 (0)