Skip to content

feature: Add prompt filter and handler middleware support (parity with tools) #750

@ronan-zelta

Description

@ronan-zelta

Problem Statement

Tools support pre-list filtering via WithToolFilter and handler middleware via WithToolHandlerMiddleware. Resources recently gained WithResourceHandlerMiddleware (#569). Prompts have no equivalent for either.

This means servers that need to conditionally show/hide prompts (e.g. based on session, permissions, or feature flags) cannot filter them from prompts/list responses, and have no middleware hook for prompts/get handlers.

Proposed Solution

Add prompt equivalents following the existing tool/resource patterns:

New types:

  • PromptFilterFunc func(ctx context.Context, prompts []mcp.Prompt) []mcp.Prompt
  • PromptHandlerMiddleware func(PromptHandlerFunc) PromptHandlerFunc

New server options:

  • WithPromptFilter(PromptFilterFunc) ServerOption
  • WithPromptHandlerMiddleware(PromptHandlerMiddleware) ServerOption

Apply filters in handleListPrompts (before pagination) and the middleware chain in handleGetPrompt (before calling the handler), matching how handleListTools and handleToolCall work today.

Example Usage

s := server.NewMCPServer(
	"My Server",
	"1.0.0",
	server.WithPromptFilter(func(ctx context.Context, prompts []mcp.Prompt) []mcp.Prompt {
		session := server.ClientSessionFromContext(ctx)
		if session == nil {
			return prompts
		}
		// Filter prompts based on session
		var filtered []mcp.Prompt
		for _, p := range prompts {
			if isPromptAllowed(session, p) {
				filtered = append(filtered, p)
			}
		}
		return filtered
	}),
	server.WithPromptHandlerMiddleware(func(next server.PromptHandlerFunc) server.PromptHandlerFunc {
		return func(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
			log.Printf("prompt requested: %s", req.Params.Name)
			return next(ctx, req)
		}
	}),
)

Alternatives/Workarounds Considered

Currently we wrap each prompt handler individually at registration time to gate prompts/get. This works for handler-level checks but cannot filter prompts/list — ineligible prompts are still visible to clients. A server-level filter and middleware would solve both cases cleanly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions