-
Notifications
You must be signed in to change notification settings - Fork 191
Description
Description
As a toolset implementer, I want to be able to define MCP prompts as part of my toolset definition, so that I can provide workflow templates that are bundled with the toolset's functionality.
Background
The Toolset interface in pkg/api/toolsets.go currently allows implementers to define tools via GetTools(). This issue extends the interface to also support defining prompts via a new GetPrompts() method.
This builds on the infrastructure established in #226, which adds MCP prompt support to the configuration module. The Prompt struct defined there will be extended to support both static and dynamic message generation.
Expected Behavior
Toolset implementers can define prompts by implementing the GetPrompts() method on their toolset:
type Toolset interface {
GetName() string
GetDescription() string
GetTools(o internalk8s.Openshift) []ServerTool
// GetPrompts returns the prompts provided by this toolset.
// Returns nil or empty slice if the toolset doesn't provide any prompts.
GetPrompts() []Prompt
}Static vs Dynamic Messages
The Prompt struct supports two approaches for generating messages:
type Prompt struct {
Name string `json:"name" toml:"name"`
Title string `json:"title,omitempty" toml:"title,omitempty"`
Description string `json:"description,omitempty" toml:"description,omitempty"`
Arguments []PromptArgument `json:"arguments,omitempty" toml:"arguments,omitempty"`
// Static messages - used for config-defined prompts with {{argument}} substitution
Messages []PromptMessage `json:"messages,omitempty" toml:"messages,omitempty"`
// Dynamic messages - used for toolset-defined prompts that need programmatic control
// If set, takes precedence over Messages
GetMessages func(arguments map[string]string) []PromptMessage `json:"-" toml:"-"`
}When prompts/get is called:
- If
GetMessagesis set, call it with the arguments - Otherwise, use
Messageswith{{argument}}substitution
Static Messages Example
For simple prompts with template substitution:
func (t *MyToolset) GetPrompts() []api.Prompt {
return []api.Prompt{
{
Name: "simple-workflow",
Title: "Simple Workflow",
Description: "A simple workflow with template substitution",
Arguments: []api.PromptArgument{
{Name: "resource_name", Description: "Name of the resource", Required: true},
},
Messages: []api.PromptMessage{
{Role: "user", Content: "Help me with {{resource_name}}"},
},
},
}
}Dynamic Messages Example
For complex prompts that need programmatic control (conditional sections, formatted output, etc.):
func (t *MyToolset) GetPrompts() []api.Prompt {
return []api.Prompt{
{
Name: "cluster-health-check",
Title: "Cluster Health Check",
Description: "Comprehensive cluster health diagnostics",
Arguments: []api.PromptArgument{
{Name: "verbose", Description: "Enable detailed output", Required: false},
{Name: "namespace", Description: "Limit to specific namespace", Required: false},
{Name: "output_format", Description: "Output format: text or json", Required: false},
},
GetMessages: func(arguments map[string]string) []api.PromptMessage {
verbose := arguments["verbose"] == "true"
namespace := arguments["namespace"]
outputFormat := arguments["output_format"]
if outputFormat == "" {
outputFormat = "text"
}
// Build messages dynamically based on arguments
content := buildHealthCheckInstructions(verbose, namespace, outputFormat)
return []api.PromptMessage{
{Role: "user", Content: content},
}
},
},
}
}The MCP server collects prompts from all enabled toolsets and exposes them via prompts/list and prompts/get.
Disabling Toolset Prompts
Administrators can disable all toolset-defined prompts via configuration, using only config-defined prompts:
disable_toolset_prompts = trueScope
In scope:
- Add
GetPrompts() []Promptto theToolsetinterface - Extend
Promptstruct to support bothMessages(static) andGetMessages(dynamic) - Update existing toolsets to return
nilor empty slice fromGetPrompts() - Update MCP server to collect and register prompts from enabled toolsets
- Merge toolset prompts with config-defined prompts (config takes precedence for same name)
- Add
disable_toolset_promptsconfiguration option
Out of scope:
- Built-in/embedded prompts shipped with the server (separate issue)
- System prompts support
Related
- Blocked by: [CONFIG] Configurable prompt templates #226 (config-defined prompts - provides base
Promptstruct) - PR prompt(core): add cluster health check #434 (health check prompts - demonstrates dynamic message generation use case)
- PR feat: add MCP prompts support #510 (implements this and additional features - should be broken down)
Acceptance Criteria
-
Toolsetinterface includesGetPrompts() []Promptmethod -
Promptstruct supports bothMessagesandGetMessages -
GetMessagestakes precedence overMessageswhen both are set - Existing toolsets are updated to implement
GetPrompts()(returning nil or empty) - MCP server collects prompts from all enabled toolsets
- Config-defined prompts override toolset prompts with the same name
- Prompts from disabled toolsets are not exposed
-
disable_toolset_promptsconfiguration option disables all toolset-defined prompts
Tests
- Test toolset returning prompts with static messages
- Test toolset returning prompts with dynamic messages (GetMessages)
- Test GetMessages takes precedence over Messages
- Test toolset returning nil/empty prompts
- Test prompt collection from multiple toolsets
- Test config prompts overriding toolset prompts with same name
- Test prompts not exposed when toolset is disabled
- Test
disable_toolset_promptsconfiguration option