Skip to content

Commit 81e1ac7

Browse files
Implement tiger mcp list command (#120)
1 parent 1035645 commit 81e1ac7

7 files changed

Lines changed: 418 additions & 12 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ Tiger CLI is a Go-based command-line interface for managing Tiger, the modern da
270270
- `service.go` - Service management commands (list, create, get, fork, start, stop, delete, update-password)
271271
- `db.go` - Database operation commands (connection-string, connect, test-connection)
272272
- `config.go` - Configuration management commands (show, set, unset, reset)
273-
- `mcp.go` - MCP server commands (install, start)
273+
- `mcp.go` - MCP server commands (install, start, list)
274274
- `version.go` - Version command
275275
- **Configuration**: `internal/tiger/config/config.go` - Centralized config with Viper integration
276276
- **Logging**: `internal/tiger/logging/logging.go` - Structured logging with zap
@@ -280,6 +280,7 @@ Tiger CLI is a Go-based command-line interface for managing Tiger, the modern da
280280
- `service_tools.go` - Service management tools (list, get, create, fork, start, stop, update-password)
281281
- `db_tools.go` - Database operation tools (execute-query)
282282
- `proxy.go` - Proxy client that forwards tools/resources/prompts from remote docs MCP server
283+
- `capabilities.go` - Lists all available MCP capabilities (tools, prompts, resources, resource templates)
283284
- **Common Package**: `internal/tiger/common/` - Shared business logic used by both CLI and MCP
284285
- Password storage utilities (keyring, pgpass, validation)
285286
- Wait operations and polling logic (WaitForService)

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Tiger CLI provides the following commands:
104104
- `tiger mcp` - MCP server setup and management
105105
- `install` - Install and configure MCP server for an AI assistant
106106
- `start` - Start the MCP server
107+
- `list` - List available MCP tools, prompts, and resources
107108
- `tiger version` - Show version information
108109

109110
Use `tiger <command> --help` for detailed information about each command.
@@ -182,8 +183,8 @@ The MCP server automatically uses your CLI authentication and configuration, so
182183

183184
In addition to the service management tools listed above, the Tiger MCP server also proxies tools from a remote documentation MCP server. This feature provides AI assistants with semantic search capabilities for PostgreSQL, TimescaleDB, and Tiger Cloud documentation, as well as prompts/guides for various Tiger Cloud features.
184185

185-
The proxied documentation server ([tiger-docs-mcp-server](https://github.com/timescale/tiger-docs-mcp-server)) currently provides the following tools:
186-
- `get_guide` - Retrieve comprehensive guides for TimescaleDB features and best practices
186+
The proxied documentation server ([pg-aiguide](https://github.com/timescale/pg-aiguide)) currently provides the following tools:
187+
- `view_skill` - Retrieve comprehensive guides for TimescaleDB features and best practices
187188
- `semantic_search_postgres_docs` - Search PostgreSQL documentation using natural language queries
188189
- `semantic_search_tiger_docs` - Search Tiger Cloud and TimescaleDB documentation using natural language queries
189190

internal/tiger/cmd/mcp.go

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"io"
78
"net"
89
"net/http"
910

11+
"github.com/olekukonko/tablewriter"
1012
"github.com/spf13/cobra"
1113
"go.uber.org/zap"
1214

15+
"github.com/timescale/tiger-cli/internal/tiger/config"
1316
"github.com/timescale/tiger-cli/internal/tiger/logging"
1417
"github.com/timescale/tiger-cli/internal/tiger/mcp"
18+
"github.com/timescale/tiger-cli/internal/tiger/util"
1519
)
1620

1721
// buildMCPCmd creates the MCP server command with subcommands
@@ -40,6 +44,7 @@ Use 'tiger mcp start' to launch the MCP server.`,
4044
// Add subcommands
4145
cmd.AddCommand(buildMCPInstallCmd())
4246
cmd.AddCommand(buildMCPStartCmd())
47+
cmd.AddCommand(buildMCPListCmd())
4348

4449
return cmd
4550
}
@@ -91,7 +96,7 @@ Examples:
9196
if len(args) == 0 {
9297
// No client specified, prompt user to select one
9398
var err error
94-
clientName, err = selectClientInteractively(cmd.OutOrStdout())
99+
clientName, err = selectClientInteractively(cmd.ErrOrStderr())
95100
if err != nil {
96101
return fmt.Errorf("failed to select client: %w", err)
97102
}
@@ -206,6 +211,74 @@ Examples:
206211
return cmd
207212
}
208213

214+
// buildMCPListCmd creates the list subcommand for displaying available MCP capabilities
215+
func buildMCPListCmd() *cobra.Command {
216+
var outputFormat string
217+
218+
cmd := &cobra.Command{
219+
Use: "list",
220+
Short: "List available MCP tools, prompts, and resources",
221+
Long: `List all MCP tools, prompts, and resources exposed via the Tiger MCP server.
222+
223+
The output can be formatted as a table, JSON, or YAML.
224+
225+
Examples:
226+
# List all capabilities in table format (default)
227+
tiger mcp list
228+
229+
# List as JSON
230+
tiger mcp list -o json
231+
232+
# List as YAML
233+
tiger mcp list -o yaml`,
234+
Args: cobra.NoArgs,
235+
ValidArgsFunction: cobra.NoFileCompletions,
236+
PreRunE: bindFlags("output"),
237+
RunE: func(cmd *cobra.Command, args []string) error {
238+
cmd.SilenceUsage = true
239+
240+
// Get config
241+
cfg, err := config.Load()
242+
if err != nil {
243+
return fmt.Errorf("failed to load config: %w", err)
244+
}
245+
246+
// Create MCP server
247+
server, err := mcp.NewServer(cmd.Context())
248+
if err != nil {
249+
return fmt.Errorf("failed to create MCP server: %w", err)
250+
}
251+
defer server.Close()
252+
253+
// List capabilities
254+
capabilities, err := server.ListCapabilities(cmd.Context())
255+
if err != nil {
256+
return fmt.Errorf("failed to list capabilities: %w", err)
257+
}
258+
259+
// Close the MCP server when finished
260+
if err := server.Close(); err != nil {
261+
return fmt.Errorf("failed to close MCP server: %w", err)
262+
}
263+
264+
// Format output
265+
output := cmd.OutOrStdout()
266+
switch cfg.Output {
267+
case "json":
268+
return util.SerializeToJSON(output, capabilities)
269+
case "yaml":
270+
return util.SerializeToYAML(output, capabilities, true)
271+
default:
272+
return outputCapabilitiesTable(output, capabilities)
273+
}
274+
},
275+
}
276+
277+
cmd.Flags().VarP((*outputFlag)(&outputFormat), "output", "o", "output format (json, yaml, table)")
278+
279+
return cmd
280+
}
281+
209282
// startStdioServer starts the MCP server with stdio transport
210283
func startStdioServer(ctx context.Context) error {
211284
logging.Info("Starting Tiger MCP server", zap.String("transport", "stdio"))
@@ -215,10 +288,10 @@ func startStdioServer(ctx context.Context) error {
215288
if err != nil {
216289
return fmt.Errorf("failed to create MCP server: %w", err)
217290
}
291+
defer server.Close()
218292

219293
// Start the stdio transport
220-
err = server.StartStdio(ctx)
221-
if err != nil && !errors.Is(err, context.Canceled) {
294+
if err := server.StartStdio(ctx); err != nil && !errors.Is(err, context.Canceled) {
222295
return fmt.Errorf("failed to start MCP server: %w", err)
223296
}
224297

@@ -238,6 +311,7 @@ func startHTTPServer(ctx context.Context, host string, port int) error {
238311
if err != nil {
239312
return fmt.Errorf("failed to create MCP server: %w", err)
240313
}
314+
defer server.Close()
241315

242316
// Find available port and get the listener
243317
listener, actualPort, err := getListener(host, port)
@@ -302,3 +376,32 @@ func getListener(host string, startPort int) (net.Listener, int, error) {
302376
}
303377
return nil, 0, fmt.Errorf("no available port found in range %d-%d", startPort, startPort+99)
304378
}
379+
380+
// outputCapabilitiesTable outputs capabilities in table format. Results are
381+
// ordered alphabetically by type, then name.
382+
func outputCapabilitiesTable(output io.Writer, capabilities *mcp.Capabilities) error {
383+
table := tablewriter.NewWriter(output)
384+
table.Header("TYPE", "NAME")
385+
386+
// Add prompts
387+
for _, prompt := range capabilities.Prompts {
388+
table.Append("prompt", prompt.Name)
389+
}
390+
391+
// Add resources
392+
for _, resource := range capabilities.Resources {
393+
table.Append("resource", resource.Name)
394+
}
395+
396+
// Add resource templates
397+
for _, template := range capabilities.ResourceTemplates {
398+
table.Append("resource_template", template.Name)
399+
}
400+
401+
// Add tools
402+
for _, tool := range capabilities.Tools {
403+
table.Append("tool", tool.Name)
404+
}
405+
406+
return table.Render()
407+
}

0 commit comments

Comments
 (0)