generate_password
Generate a random password of specified length between 8 and 64 characters, with optional inclusion of special characters for enhanced security.
Instructions
Generate a random password with specified length, optionally including special characters.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| length | No | The length of the password to generate (between 8 and 64 characters). | |
| use_special_chars | No | Include special characters in the password. |
Implementation Reference
- src/pymcp/server.py:125-179 (handler)The 'generate_password' async method that implements password generation: generates a random password with configurable length (8-64) and optional special characters, ensuring complexity requirements (lowercase, uppercase, >=2 digits, and optionally special chars) via iterative generation.
async def generate_password( self, ctx: Context, length: Annotated[ int, Field( default=12, ge=8, le=64, description="The length of the password to generate (between 8 and 64 characters).", ), ] = 12, use_special_chars: Annotated[ bool, Field( default=False, description="Include special characters in the password.", ), ] = False, ) -> ToolResult: """Generate a random password with specified length, optionally including special characters.""" """The password will meet the complexity requirements of at least one lowercase letter, one uppercase letter, and two digits. If special characters are included, it will also contain at least one such character. Until the password meets these requirements, it will keep regenerating. This is a simple example of a tool that can be used to generate passwords. It is not intended for production use.""" characters = string.ascii_letters + string.digits if use_special_chars: characters += string.punctuation password_generation_attempts = 0 while True: password = "".join(secrets.choice(characters) for _ in range(length)) password_generation_attempts += 1 if ( any(c.islower() for c in password) and any(c.isupper() for c in password) and sum(c.isdigit() for c in password) >= 2 and (not use_special_chars or any(c in string.punctuation for c in password)) ): await ctx.info("Generated password meets complexity requirements.") break else: # Exclude from coverage because this may not always happen in tests await ctx.warning( # pragma: no cover f"Re-generating since the generated password did not meet complexity requirements: {password}" ) return self.get_tool_result( result=password, metadata={ "generate_password": { "length_satisfied": len(password) == length, "character_set": characters, "generation_attempts": password_generation_attempts, } }, ) - src/pymcp/server.py:125-144 (schema)Input schema for generate_password: 'length' (int, 8-64, default 12) and 'use_special_chars' (bool, default False) using Pydantic Field annotations.
async def generate_password( self, ctx: Context, length: Annotated[ int, Field( default=12, ge=8, le=64, description="The length of the password to generate (between 8 and 64 characters).", ), ] = 12, use_special_chars: Annotated[ bool, Field( default=False, description="Include special characters in the password.", ), ] = False, ) -> ToolResult: - src/pymcp/server.py:58-62 (registration)Tool registration entry listing 'generate_password' with tags and annotations in the PyMCP class tools list.
{ "fn": "generate_password", "tags": ["password-generation", "example"], "annotations": {"readOnlyHint": True}, }, - src/pymcp/mixin.py:33-39 (registration)Generic tool registration logic in MCPMixin.register_features: iterates over self.tools, extracts 'fn' name, and registers the corresponding method with FastMCP using mcp.tool().
# Register tools for tool in self.tools: assert "fn" in tool, "Tool metadata must include the 'fn' key." tool_copy = copy.deepcopy(tool) fn_name = tool_copy.pop("fn") fn = getattr(self, fn_name) mcp.tool(**tool_copy)(fn) # pass remaining metadata as kwargs - src/pymcp/mixin.py:58-71 (helper)get_tool_result helper used by generate_password to create a ToolResult with structured_content and metadata.
def get_tool_result(self, result: Any, metadata: dict[str, Any] | None = None) -> ToolResult: # pragma: no cover """Create a ToolResult object with the given result and metadata, including package metadata. Args: result (Any): The result to include in the ToolResult. metadata (Dict[str, Any] | None, optional): Additional metadata to include. Defaults to None. Returns: ToolResult: The ToolResult object containing the result and metadata. """ return ToolResult( structured_content={"result": result} if not isinstance(result, dict) else result, meta=metadata if metadata is not None else None, )