Skip to main content
Glama
x0base

mcp-security-toolkit

wordlist_gen

Produce targeted wordlists for security assessments by combining brand, names, and keywords in password, username, or subdomain modes.

Instructions

Generate a wordlist tailored to the target surface.

Modes:

  • passwords: combine brand / keyword seeds with leet substitution, capitalization variants, common suffixes and year suffixes.

  • usernames: combine person names into common patterns (first, last, first.last, flast, firstl, …).

  • subdomains: combine brand + keywords with a curated list of common environment / service subdomain labels.

Pure function. No network.

Args: mode: One of passwords, usernames, subdomains. brand: Target organization brand (used in all modes). names: List of person names ("Jane Doe") for usernames mode. keywords: Additional seed words for passwords / subdomains. years: Year strings to append (passwords mode). max_size: Hard cap on returned entries.

Returns: GenReport with sample (the wordlist itself, up to max_size).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeYes
brandNo
namesNo
keywordsNo
yearsNo
max_sizeNo

Implementation Reference

  • Main tool function `wordlist_gen` that generates password/usernames/subdomain wordlists based on OSINT surface info. Orchestrates calls to _passwords, _usernames, _subdomains helpers and returns a GenReport.
    def wordlist_gen(
        mode: Literal["passwords", "usernames", "subdomains"],
        brand: str | None = None,
        names: list[str] | None = None,
        keywords: list[str] | None = None,
        years: list[str] | None = None,
        max_size: int = 5000,
    ) -> dict:
        """Generate a wordlist tailored to the target surface.
    
        Modes:
          - `passwords`: combine brand / keyword seeds with leet substitution,
            capitalization variants, common suffixes and year suffixes.
          - `usernames`: combine person names into common patterns
            (`first`, `last`, `first.last`, `flast`, `firstl`, …).
          - `subdomains`: combine brand + keywords with a curated list of
            common environment / service subdomain labels.
    
        Pure function. No network.
    
        Args:
            mode: One of `passwords`, `usernames`, `subdomains`.
            brand: Target organization brand (used in all modes).
            names: List of person names ("Jane Doe") for `usernames` mode.
            keywords: Additional seed words for `passwords` / `subdomains`.
            years: Year strings to append (passwords mode).
            max_size: Hard cap on returned entries.
    
        Returns:
            GenReport with `sample` (the wordlist itself, up to `max_size`).
        """
        if mode not in ("passwords", "usernames", "subdomains"):
            return {"error": f"mode must be passwords|usernames|subdomains, got {mode!r}"}
    
        seeds: list[str] = []
        if brand:
            seeds.append(brand)
        if keywords:
            seeds.extend(keywords)
    
        if mode == "passwords":
            out = _passwords(seeds, years or [])
        elif mode == "usernames":
            if not names:
                return {"error": "usernames mode requires `names`"}
            out = _usernames(names, brand)
        else:
            if not brand:
                return {"error": "subdomains mode requires `brand`"}
            out = _subdomains(brand, keywords or [])
    
        sorted_out = sorted({w for w in out if w})
        truncated = len(sorted_out) > max_size
        return GenReport(
            mode=mode,
            total=len(sorted_out),
            sample=sorted_out[:max_size],
            truncated=truncated,
        ).model_dump()
  • Tool registration via `mcp.tool()(wordlist_gen.wordlist_gen)` in the FastMCP server.
    mcp.tool()(wordlist_gen.wordlist_gen)
  • GenReport Pydantic model defining the return schema (mode, total, sample, truncated).
    class GenReport(BaseModel):
        mode: str
        total: int
        sample: list[str]
        truncated: bool
  • _passwords helper: generates password candidates from seeds with leet, capitalization, suffixes and years.
    def _passwords(seeds: list[str], years: list[str]) -> set[str]:
        out: set[str] = set()
        for s in seeds:
            if not s:
                continue
            base = s.lower()
            out.update(_capitalize_variants(base))
            out.add(_leet(base))
            out.add(_leet(base).capitalize())
            for suf in SUFFIXES + years:
                if not suf:
                    continue
                out.add(base + suf)
                out.add(base.capitalize() + suf)
                out.add(_leet(base) + suf)
        return out
  • _usernames helper: generates username patterns from person names (first.last, flast, etc.).
    def _usernames(names: list[str], brand: str | None) -> set[str]:
        out: set[str] = set()
        for n in names:
            n = n.strip().lower()
            if not n:
                continue
            parts = n.split()
            if len(parts) == 1:
                out.add(parts[0])
                continue
            first, *_, last = parts
            out.add(f"{first}")
            out.add(f"{last}")
            out.add(f"{first}.{last}")
            out.add(f"{first[0]}{last}")
            out.add(f"{first}{last[0]}")
            out.add(f"{first}_{last}")
            out.add(f"{last}.{first}")
            out.add(f"{last}{first[0]}")
            if brand:
                out.add(f"{first}.{last}@{brand.lower()}")
        return out
  • _subdomains helper: combines brand + keywords with common subdomain labels (dev, staging, api, etc.).
    def _subdomains(brand: str, keywords: list[str]) -> set[str]:
        out: set[str] = set()
        base = brand.lower()
        common = [
            "dev", "stage", "staging", "test", "qa", "uat", "preprod", "beta",
            "internal", "intranet", "vpn", "mail", "smtp", "imap", "owa", "exchange",
            "api", "admin", "portal", "auth", "sso", "git", "gitlab", "github",
            "jenkins", "ci", "cd", "k8s", "prom", "grafana", "kibana", "splunk",
            "old", "new", "backup", "bak", "legacy", "demo", "sandbox", "lab",
        ]
        out.update(common)
        for kw in keywords:
            kw = kw.strip().lower()
            if not kw:
                continue
            out.add(kw)
            for sep, suf in product(SEPARATORS, common):
                out.add(f"{kw}{sep}{suf}")
        for suf in common:
            out.add(f"{base}-{suf}")
            out.add(f"{suf}-{base}")
        return out
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It includes 'Pure function. No network.' which discloses critical behavioral traits. No contradictions or omissions of major side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured with bullet points for modes and parameter details. Every sentence adds value, and the format is easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description explains the return type (GenReport with sample). All parameters and modes are covered, and the context is complete for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description elaborates on each parameter: mode explains enum values, brand/names/keywords/years/max_size are described in context of modes. This adds significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Generate a wordlist tailored to the target surface.' It explains three modes (passwords, usernames, subdomains) with specific patterns, distinguishing it from sibling tools that are audit/inspection-focused.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance by detailing each mode and its parameters. It doesn't explicitly state when not to use or alternatives, but the sibling list shows no similar tools, and the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/x0base/mcp-security-toolkit'

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