Skip to content

Commit c28c02e

Browse files
authored
feat(api)!: add toolset prompts infrastructure (#581)
* add toolset prompts infrastructure Enable toolset implementers to define MCP prompts programmatically as part of their toolset definition. - Add GetPrompts() method to Toolset interface - Collect prompts from all enabled toolsets - Merge config and toolset prompts (config takes precedence) - Add disable_toolset_prompts configuration option - Update all existing toolsets to implement GetPrompts() Signed-off-by: Nader Ziada <[email protected]> * remove disable_toolset_prompts flag and openshift flag Signed-off-by: Nader Ziada <[email protected]> --------- Signed-off-by: Nader Ziada <[email protected]>
1 parent adfd02e commit c28c02e

File tree

11 files changed

+497
-5
lines changed

11 files changed

+497
-5
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ pkill -HUP kubernetes-mcp-server
294294

295295
### MCP Prompts
296296

297-
The server supports MCP prompts for workflow templates. Define custom prompts in `config.toml`:
297+
1. The server supports MCP prompts for workflow templates. Define custom prompts in `config.toml`:
298298

299299
```toml
300300
[[prompts]]
@@ -311,6 +311,8 @@ role = "user"
311311
content = "Help me with {{resource_name}}"
312312
```
313313

314+
2. Toolset prompts implemented by toolset developers
315+
314316
See docs/PROMPTS.md for detailed documentation.
315317

316318
## 🛠️ Tools and Functionalities <a id="tools-and-functionalities"></a>

docs/PROMPTS.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,54 @@ Use `{{argument_name}}` placeholders in message content. The template engine rep
5959

6060
## Configuration File Location
6161

62-
Place your prompts in the `config.toml` file used by the MCP server. Specify the config file path using the `--config` flag when starting the server.
62+
Place your prompts in the `config.toml` file used by the MCP server. Specify the config file path using the `--config` flag when starting the server.
63+
64+
## Toolset Prompts
65+
66+
Toolsets can provide built-in prompts by implementing the `GetPrompts()` method. This allows toolset developers to ship workflow templates alongside their tools.
67+
68+
### Implementing Toolset Prompts
69+
70+
```go
71+
func (t *MyToolset) GetPrompts() []api.ServerPrompt {
72+
return []api.ServerPrompt{
73+
{
74+
Prompt: api.Prompt{
75+
Name: "my-workflow",
76+
Description: "Custom workflow for my toolset",
77+
Arguments: []api.PromptArgument{
78+
{
79+
Name: "namespace",
80+
Description: "Target namespace",
81+
Required: true,
82+
},
83+
},
84+
},
85+
Handler: func(params api.PromptHandlerParams) (*api.PromptCallResult, error) {
86+
args := params.GetArguments()
87+
namespace := args["namespace"]
88+
89+
// Build messages dynamically based on arguments
90+
messages := []api.PromptMessage{
91+
{
92+
Role: "user",
93+
Content: api.PromptContent{
94+
Type: "text",
95+
Text: fmt.Sprintf("Help me with namespace: %s", namespace),
96+
},
97+
},
98+
}
99+
100+
return api.NewPromptCallResult("Workflow description", messages, nil), nil
101+
},
102+
},
103+
}
104+
}
105+
```
106+
107+
### Prompt Merging
108+
109+
When both toolset and config prompts exist:
110+
- Config-defined prompts **override** toolset prompts with the same name
111+
- This allows administrators to customize built-in workflows
112+
- Prompts with unique names from both sources are available

pkg/api/toolsets.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ type Toolset interface {
4343
// Will be used to generate documentation and help text.
4444
GetDescription() string
4545
GetTools(o Openshift) []ServerTool
46+
// GetPrompts returns the prompts provided by this toolset.
47+
// Returns nil if the toolset doesn't provide any prompts.
48+
GetPrompts() []ServerPrompt
4649
}
4750

4851
type ToolCallRequest interface {

pkg/mcp/mcp.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ func (s *Server) reloadToolsets() error {
167167
// Track previously enabled prompts
168168
previousPrompts := s.enabledPrompts
169169

170+
// Build and register prompts from all toolsets
171+
applicablePrompts := make([]api.ServerPrompt, 0)
172+
s.enabledPrompts = make([]string, 0)
173+
174+
// Load embedded toolset prompts
175+
for _, toolset := range s.configuration.Toolsets() {
176+
prompts := toolset.GetPrompts()
177+
if prompts == nil {
178+
continue
179+
}
180+
for _, prompt := range prompts {
181+
applicablePrompts = append(applicablePrompts, prompt)
182+
s.enabledPrompts = append(s.enabledPrompts, prompt.Prompt.Name)
183+
}
184+
}
185+
170186
// Load config prompts into registry
171187
prompts.Clear()
172188
if s.configuration.HasPrompts() {
@@ -180,9 +196,12 @@ func (s *Server) reloadToolsets() error {
180196
// Get prompts from registry
181197
configPrompts := prompts.ConfigPrompts()
182198

199+
// Merge: config prompts override embedded prompts with same name
200+
applicablePrompts = mergePrompts(applicablePrompts, configPrompts)
201+
183202
// Update enabled prompts list
184203
s.enabledPrompts = make([]string, 0)
185-
for _, prompt := range configPrompts {
204+
for _, prompt := range applicablePrompts {
186205
s.enabledPrompts = append(s.enabledPrompts, prompt.Prompt.Name)
187206
}
188207

@@ -195,8 +214,8 @@ func (s *Server) reloadToolsets() error {
195214
}
196215
s.server.RemovePrompts(promptsToRemove...)
197216

198-
// Register all config prompts
199-
for _, prompt := range configPrompts {
217+
// Register all applicable prompts
218+
for _, prompt := range applicablePrompts {
200219
mcpPrompt, promptHandler, err := ServerPromptToGoSdkPrompt(s, prompt)
201220
if err != nil {
202221
return fmt.Errorf("failed to convert prompt %s: %v", prompt.Prompt.Name, err)

0 commit comments

Comments
 (0)