@@ -3,6 +3,7 @@ package mcp
7 "github.com/charmbracelet/crush/internal/csync"
8 "github.com/charmbracelet/crush/internal/csync"
8 "github.com/modelcontextprotocol/go-sdk/mcp"
9 "github.com/modelcontextprotocol/go-sdk/mcp"
@@ -11,25 +12,15 @@ import (
11type Prompt = mcp.Prompt
12type Prompt = mcp.Prompt
14− allPrompts = csync.NewMap[string, *Prompt]()
15+ allPrompts = csync.NewMap[string, *Prompt]()
15− client2Prompts = csync.NewMap[string, []*Prompt]()
16+ clientPrompts = csync.NewMap[string, []*Prompt]()
18−// GetPrompts returns all available MCP prompts.
19+// Prompts returns all available MCP prompts.
19−func GetPrompts() iter.Seq2[string, *Prompt] {
20+func Prompts() iter.Seq2[string, *Prompt] {
20 return allPrompts.Seq2()
21 return allPrompts.Seq2()
23−// GetPrompt returns a specific MCP prompt by name.
24−func GetPrompt(name string) (*Prompt, bool) {
25− return allPrompts.Get(name)
28−// GetPromptsByClient returns all prompts for a specific MCP client.
29−func GetPromptsByClient(clientName string) ([]*Prompt, bool) {
30− return client2Prompts.Get(clientName)
33// GetPromptMessages retrieves the content of an MCP prompt with the given arguments.
24// GetPromptMessages retrieves the content of an MCP prompt with the given arguments.
34func GetPromptMessages(ctx context.Context, clientName, promptName string, args map[string]string) ([]string, error) {
25func GetPromptMessages(ctx context.Context, clientName, promptName string, args map[string]string) ([]string, error) {
35 c, err := getOrRenewClient(ctx, clientName)
26 c, err := getOrRenewClient(ctx, clientName)
@@ -56,6 +47,30 @@ func GetPromptMessages(ctx context.Context, clientName, promptName string, args
56 return messages, nil
47 return messages, nil
50+// RefreshPrompts gets the updated list of prompts from the MCP and updates the
52+func RefreshPrompts(ctx context.Context, name string) {
53+ session, ok := sessions.Get(name)
55+ slog.Warn("refresh prompts: no session", "name", name)
59+ prompts, err := getPrompts(ctx, session)
61+ updateState(name, StateError, err, nil, Counts{})
65+ updatePrompts(name, prompts)
67+ prev, _ := states.Get(name)
68+ updateState(name, StateConnected, nil, session, Counts{
69+ Prompts: len(prompts),
70+ Tools: prev.Counts.Tools,
59func getPrompts(ctx context.Context, c *mcp.ClientSession) ([]*Prompt, error) {
74func getPrompts(ctx context.Context, c *mcp.ClientSession) ([]*Prompt, error) {
60 if c.InitializeResult().Capabilities.Prompts == nil {
75 if c.InitializeResult().Capabilities.Prompts == nil {
61 return nil, nil
76 return nil, nil
@@ -70,11 +85,11 @@ func getPrompts(ctx context.Context, c *mcp.ClientSession) ([]*Prompt, error) {
70// updatePrompts updates the global mcpPrompts and mcpClient2Prompts maps
85// updatePrompts updates the global mcpPrompts and mcpClient2Prompts maps
71func updatePrompts(mcpName string, prompts []*Prompt) {
86func updatePrompts(mcpName string, prompts []*Prompt) {
72 if len(prompts) == 0 {
87 if len(prompts) == 0 {
73− client2Prompts.Del(mcpName)
88+ clientPrompts.Del(mcpName)
75− client2Prompts.Set(mcpName, prompts)
90+ clientPrompts.Set(mcpName, prompts)
77− for mcpName, prompts := range client2Prompts.Seq2() {
92+ for mcpName, prompts := range clientPrompts.Seq2() {
78 for _, p := range prompts {
93 for _, p := range prompts {
79 key := mcpName + ":" + p.Name
94 key := mcpName + ":" + p.Name
80 allPrompts.Set(key, p)
95 allPrompts.Set(key, p)