Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Station Makefile
.PHONY: build clean install dev test lint kill-ports stop-station
.PHONY: build clean install dev test test-bundle test-bundle-watch lint kill-ports stop-station

# Build configuration
BINARY_NAME=stn
Expand Down Expand Up @@ -99,6 +99,21 @@ version:
@echo "Station Version: $(VERSION)"
@echo "Build Time: $(BUILD_TIME)"

# Bundle system development targets
test-bundle:
@echo "๐Ÿงช Running bundle system tests..."
@go test -v ./pkg/bundle/... -cover

test-bundle-watch:
@echo "๐Ÿ‘€ Starting bundle test watcher (Ctrl+C to stop)..."
@while true; do \
go test -v ./pkg/bundle/... -cover; \
echo ""; \
echo "โฐ Waiting for changes... Press Ctrl+C to stop"; \
inotifywait -r -e modify,create,delete ./pkg/bundle/ 2>/dev/null || sleep 2; \
clear; \
done

# Show usage help
help:
@echo "Station Build Commands:"
Expand All @@ -113,6 +128,10 @@ help:
@echo " make kill-ports - Kill processes on ports 2222, 3000, 8080"
@echo " make stop-station - Stop all Station processes and clear ports"
@echo ""
@echo "Bundle System Development:"
@echo " make test-bundle - Run bundle system tests"
@echo " make test-bundle-watch - Watch bundle tests (requires inotify-tools)"
@echo ""
@echo "Version Control:"
@echo " make build VERSION=v1.2.3 - Build with custom version"

Expand Down
193 changes: 193 additions & 0 deletions cmd/main/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"log"
"path/filepath"

tea "github.com/charmbracelet/bubbletea"
"github.com/spf13/cobra"
Expand All @@ -12,6 +13,8 @@ import (
"station/cmd/main/handlers/mcp"
"station/internal/db"
"station/internal/tui"
"station/pkg/bundle"
bundlecli "station/pkg/bundle/cli"
)

// runMCPList implements the "station mcp list" command
Expand Down Expand Up @@ -188,4 +191,194 @@ func runMCPSync(cmd *cobra.Command, args []string) error {
func runMCPStatus(cmd *cobra.Command, args []string) error {
mcpHandler := mcp.NewMCPHandler(themeManager)
return mcpHandler.RunMCPStatus(cmd, args)
}

// runTemplateCreate implements the "station template create" command
func runTemplateCreate(cmd *cobra.Command, args []string) error {
// Get flags
name, _ := cmd.Flags().GetString("name")
author, _ := cmd.Flags().GetString("author")
description, _ := cmd.Flags().GetString("description")

// Use bundle path from args
bundlePath := args[0]

// If name not provided, use directory name
if name == "" {
name = filepath.Base(bundlePath)
}

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“ฆ Create Template Bundle")
fmt.Println(banner)

// Create bundle CLI
bundleCLI := bundlecli.NewBundleCLI(nil)
opts := bundle.CreateOptions{
Name: name,
Author: author,
Description: description,
}

return bundleCLI.CreateBundle(bundlePath, opts)
}

// runTemplateValidate implements the "station template validate" command
func runTemplateValidate(cmd *cobra.Command, args []string) error {
bundlePath := args[0]

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ” Validate Template Bundle")
fmt.Println(banner)

// Create bundle CLI and validate
bundleCLI := bundlecli.NewBundleCLI(nil)
summary, err := bundleCLI.ValidateBundle(bundlePath)
if err != nil {
return err
}

// Print validation results
bundleCLI.PrintValidationSummary(summary)
return nil
}

// runTemplateBundle implements the "station template bundle" command
func runTemplateBundle(cmd *cobra.Command, args []string) error {
bundlePath := args[0]
outputPath, _ := cmd.Flags().GetString("output")
validateFirst, _ := cmd.Flags().GetBool("validate")

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“ฆ Package Template Bundle")
fmt.Println(banner)

// Create bundle CLI and package
bundleCLI := bundlecli.NewBundleCLI(nil)
summary, err := bundleCLI.PackageBundle(bundlePath, outputPath, validateFirst)
if err != nil {
return err
}

// Print packaging results
bundleCLI.PrintPackageSummary(summary)
return nil
}

// runTemplatePublish implements the "station template publish" command
func runTemplatePublish(cmd *cobra.Command, args []string) error {
bundlePath := args[0]
registry, _ := cmd.Flags().GetString("registry")
skipValidation, _ := cmd.Flags().GetBool("skip-validation")

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“ค Publish Template Bundle")
fmt.Println(banner)

// TODO: Implement publishing logic
fmt.Printf("Publishing %s to registry '%s'...\n", bundlePath, registry)
if skipValidation {
fmt.Println("โš ๏ธ Skipping validation")
}

// For now, just package the bundle
bundleCLI := bundlecli.NewBundleCLI(nil)
summary, err := bundleCLI.PackageBundle(bundlePath, "", !skipValidation)
if err != nil {
return err
}

if !summary.Success {
return fmt.Errorf("bundle packaging failed")
}

fmt.Printf("โœ… Bundle packaged successfully: %s\n", summary.OutputPath)
fmt.Printf("๐Ÿš€ Publishing to registry '%s' (feature coming soon)\n", registry)

return nil
}

// runTemplateInstall implements the "station template install" command
func runTemplateInstall(cmd *cobra.Command, args []string) error {
bundleRef := args[0]
registry, _ := cmd.Flags().GetString("registry")
force, _ := cmd.Flags().GetBool("force")

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“ฅ Install Template Bundle")
fmt.Println(banner)

fmt.Printf("Installing '%s'", bundleRef)
if registry != "" {
fmt.Printf(" from registry '%s'", registry)
}
if force {
fmt.Printf(" (force reinstall)")
}
fmt.Println("...")

// TODO: Implement installation logic
fmt.Printf("๐Ÿš€ Installation from registries (feature coming soon)\n")
fmt.Printf("๐Ÿ“ฆ Bundle reference: %s\n", bundleRef)

return nil
}

// runTemplateList implements the "station template list" command
func runTemplateList(cmd *cobra.Command, args []string) error {
registry, _ := cmd.Flags().GetString("registry")
search, _ := cmd.Flags().GetString("search")

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“‹ Available Template Bundles")
fmt.Println(banner)

if registry != "" {
fmt.Printf("Registry: %s\n", registry)
}
if search != "" {
fmt.Printf("Search: %s\n", search)
}

// TODO: Implement registry listing
fmt.Printf("๐Ÿš€ Registry discovery (feature coming soon)\n")

return nil
}

// runTemplateRegistryAdd implements the "station template registry add" command
func runTemplateRegistryAdd(cmd *cobra.Command, args []string) error {
name := args[0]
url := args[1]

// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("โž• Add Template Registry")
fmt.Println(banner)

fmt.Printf("Adding registry '%s' at %s\n", name, url)

// TODO: Implement registry configuration
fmt.Printf("๐Ÿš€ Registry management (feature coming soon)\n")

return nil
}

// runTemplateRegistryList implements the "station template registry list" command
func runTemplateRegistryList(cmd *cobra.Command, args []string) error {
// Show banner
styles := getCLIStyles(themeManager)
banner := styles.Banner.Render("๐Ÿ“‹ Configured Registries")
fmt.Println(banner)

// TODO: Implement registry listing
fmt.Printf("๐Ÿš€ Registry management (feature coming soon)\n")

return nil
}
75 changes: 75 additions & 0 deletions cmd/main/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,81 @@ Examples:
RunE: runMCPStatus,
}

// Template bundle commands
templateCmd = &cobra.Command{
Use: "template",
Short: "Template bundle management commands",
Long: "Manage template bundles for quick MCP server configuration deployment",
}

templateCreateCmd = &cobra.Command{
Use: "create <path>",
Short: "Create a new template bundle",
Long: "Create a new template bundle with scaffolding for MCP server configurations",
Args: cobra.ExactArgs(1),
RunE: runTemplateCreate,
}

templateValidateCmd = &cobra.Command{
Use: "validate <path>",
Short: "Validate a template bundle",
Long: "Validate template bundle structure and check variable consistency between template and schema",
Args: cobra.ExactArgs(1),
RunE: runTemplateValidate,
}

templateBundleCmd = &cobra.Command{
Use: "bundle <path>",
Short: "Package a template bundle for distribution",
Long: "Create a distributable .tar.gz package from a validated template bundle",
Args: cobra.ExactArgs(1),
RunE: runTemplateBundle,
}

templatePublishCmd = &cobra.Command{
Use: "publish <bundle-path>",
Short: "Publish a template bundle to a registry",
Long: "Package and publish a template bundle to a specified registry",
Args: cobra.ExactArgs(1),
RunE: runTemplatePublish,
}

templateInstallCmd = &cobra.Command{
Use: "install <bundle-name>[@version]",
Short: "Install a template bundle from a registry",
Long: "Download and install a template bundle from a configured registry",
Args: cobra.ExactArgs(1),
RunE: runTemplateInstall,
}

templateListCmd = &cobra.Command{
Use: "list",
Short: "List available template bundles",
Long: "List template bundles from configured registries",
RunE: runTemplateList,
}

templateRegistryCmd = &cobra.Command{
Use: "registry",
Short: "Manage template registries",
Long: "Add, remove, and list configured template registries",
}

templateRegistryAddCmd = &cobra.Command{
Use: "add <name> <url>",
Short: "Add a new template registry",
Long: "Add a new template registry endpoint",
Args: cobra.ExactArgs(2),
RunE: runTemplateRegistryAdd,
}

templateRegistryListCmd = &cobra.Command{
Use: "list",
Short: "List configured registries",
Long: "List all configured template registries",
RunE: runTemplateRegistryList,
}

// Webhook commands
webhookCmd = &cobra.Command{
Use: "webhook",
Expand Down
11 changes: 6 additions & 5 deletions cmd/main/handlers/file_config/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (
// discoverCommand discovers tools for file configs
func (h *FileConfigHandler) discoverCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "discover <config-name-or-id> [environment-name]",
Short: "Discover tools for a file-based configuration",
Long: "Load, render, and discover MCP tools for a file-based configuration by name or ID.",
Args: cobra.RangeArgs(1, 2),
RunE: h.discoverTools,
Use: "discover <config-name-or-id> [environment-name]",
Short: "[DEPRECATED] Discover tools for a file-based configuration",
Long: "[DEPRECATED] This command is deprecated. Use 'stn mcp sync <environment>' instead for automatic tool discovery and template management.",
Args: cobra.RangeArgs(1, 2),
RunE: h.discoverTools,
Deprecated: "Use 'stn mcp sync <environment>' instead, which automatically discovers tools and handles template bundles.",
}

cmd.Flags().Bool("verbose", false, "Verbose output during discovery")
Expand Down
8 changes: 4 additions & 4 deletions cmd/main/handlers/load/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (h *LoadHandler) createFileBasedConfig(envID int64, configName string, mcpC
fmt.Printf("โœ… Created file-based config with ID: %d\n", configID)

// Next step: Discover tools from the loaded configuration
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp discover %d %s' to discover available tools\n", configID, env.Name)
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp sync %s' to sync configs and discover tools\n", env.Name)

return nil
}
Expand Down Expand Up @@ -219,7 +219,7 @@ func (h *LoadHandler) createFileBasedConfigFromData(envID int64, configData *mod
fmt.Printf("โœ… Created file-based config with ID: %d\n", configID)

// Next step: Discover tools from the loaded configuration
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp discover %d %s' to discover available tools\n", configID, env.Name)
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp sync %s' to sync configs and discover tools\n", env.Name)

return nil
}
Expand Down Expand Up @@ -433,7 +433,7 @@ func (h *LoadHandler) createFileBasedConfigTemplate(envID int64, configName stri
fmt.Printf("โœ… Created file-based config with ID: %d\n", configID)

// Next step: Discover tools from the loaded configuration
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp discover %d %s' to discover available tools\n", configID, env.Name)
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp sync %s' to sync configs and discover tools\n", env.Name)

return nil
}
Expand Down Expand Up @@ -512,7 +512,7 @@ func (h *LoadHandler) createFileBasedConfigTemplateWithVariables(envID int64, co
fmt.Printf("โœ… Created file-based config with ID: %d\n", configID)

// Next step: Discover tools from the loaded configuration
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp discover %d %s' to discover available tools\n", configID, env.Name)
fmt.Printf("๐Ÿ”ง Next: Run 'stn mcp sync %s' to sync configs and discover tools\n", env.Name)

return nil
}
Expand Down
Loading
Loading