Skip to main content
Glama
prompt_manager.py4.37 kB
from __future__ import annotations as _annotations import warnings from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, Any from mcp import GetPromptResult from fastmcp import settings from fastmcp.exceptions import NotFoundError, PromptError from fastmcp.prompts.prompt import FunctionPrompt, Prompt, PromptResult from fastmcp.settings import DuplicateBehavior from fastmcp.utilities.logging import get_logger if TYPE_CHECKING: pass logger = get_logger(__name__) class PromptManager: """Manages FastMCP prompts.""" def __init__( self, duplicate_behavior: DuplicateBehavior | None = None, mask_error_details: bool | None = None, ): self._prompts: dict[str, Prompt] = {} self.mask_error_details = mask_error_details or settings.mask_error_details # Default to "warn" if None is provided if duplicate_behavior is None: duplicate_behavior = "warn" if duplicate_behavior not in DuplicateBehavior.__args__: raise ValueError( f"Invalid duplicate_behavior: {duplicate_behavior}. " f"Must be one of: {', '.join(DuplicateBehavior.__args__)}" ) self.duplicate_behavior = duplicate_behavior def get_prompt(self, key: str) -> Prompt: """Get prompt by key.""" if key in self._prompts: return self._prompts[key] raise NotFoundError(f"Unknown prompt: {key}") def get_prompts(self) -> dict[str, Prompt]: """Get all registered prompts, indexed by registered key.""" return self._prompts def add_prompt_from_fn( self, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, description: str | None = None, tags: set[str] | None = None, ) -> FunctionPrompt: """Create a prompt from a function.""" # deprecated in 2.7.0 if settings.deprecation_warnings: warnings.warn( "PromptManager.add_prompt_from_fn() is deprecated. Use Prompt.from_function() and call add_prompt() instead.", DeprecationWarning, stacklevel=2, ) prompt = FunctionPrompt.from_function( fn, name=name, description=description, tags=tags ) return self.add_prompt(prompt) # type: ignore def add_prompt(self, prompt: Prompt, key: str | None = None) -> Prompt: """Add a prompt to the manager.""" key = key or prompt.name # Check for duplicates existing = self._prompts.get(key) if existing: if self.duplicate_behavior == "warn": logger.warning(f"Prompt already exists: {key}") self._prompts[key] = prompt elif self.duplicate_behavior == "replace": self._prompts[key] = prompt elif self.duplicate_behavior == "error": raise ValueError(f"Prompt already exists: {key}") elif self.duplicate_behavior == "ignore": return existing else: self._prompts[key] = prompt return prompt async def render_prompt( self, name: str, arguments: dict[str, Any] | None = None, ) -> GetPromptResult: """Render a prompt by name with arguments.""" prompt = self.get_prompt(name) if not prompt: raise NotFoundError(f"Unknown prompt: {name}") try: messages = await prompt.render(arguments) return GetPromptResult(description=prompt.description, messages=messages) # Pass through PromptErrors as-is except PromptError as e: logger.exception(f"Error rendering prompt {name!r}: {e}") raise e # Handle other exceptions except Exception as e: logger.exception(f"Error rendering prompt {name!r}: {e}") if self.mask_error_details: # Mask internal details raise PromptError(f"Error rendering prompt {name!r}") else: # Include original error details raise PromptError(f"Error rendering prompt {name!r}: {e}") def has_prompt(self, key: str) -> bool: """Check if a prompt exists.""" return key in self._prompts

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Lillard01/chatExcel-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server