How Auth0 MCP Server Glob Pattern Tool Filtering Works Internally

The Auth0 MCP Server filters tools using a three-step pipeline that compiles glob patterns (like auth0_list_* or auth0_*_application*) into regular expressions, matches them against registered tool names, and optionally enforces read-only constraints.

The auth0/auth0-mcp-server repository implements a lightweight but robust glob matching system to let users selectively expose tools to AI models. Instead of loading the entire tool catalog, you can pass patterns such as auth0* or *application* to surface only specific capabilities. This article breaks down the internal mechanics of this filtering system based on the source code implementation.

The Three-Step Filtering Pipeline

The entry point getAvailableTools in src/utils/tools.ts orchestrates a pipeline that transforms raw glob strings into executable tool subsets.

Step 1: Pattern Compilation

When you provide a patterns array, each string is immediately wrapped in a new Glob(pattern) constructor. This happens at lines 71–73 of src/utils/tools.ts, where the system prepares matchers before touching the tool registry.

// From src/utils/tools.ts (lines 71-73)
const globPatterns = patterns.map(pattern => new Glob(pattern));

Step 2: Name Matching

The filterToolsByPatterns function iterates over every registered tool and tests glob.matches(tool.name). Matches are collected into a Set called enabledToolNames (lines 78–89). The system also tracks how many tools each pattern matched for diagnostic purposes.

// Conceptual flow from src/utils/tools.ts (lines 78-89)
for (const tool of tools) {
  for (const glob of globPatterns) {
    if (glob.matches(tool.name)) {
      enabledToolNames.add(tool.name);
      matchCounts.set(glob.pattern, (matchCounts.get(glob.pattern) || 0) + 1);
    }
  }
}

Step 3: Read-Only Enforcement

If the readOnly flag is true, a secondary pass via filterToolsByReadOnly (lines 57–59) strips out any non-read-only tools after pattern matching completes. This guarantees that security-critical read-only filtering always takes precedence over pattern selection.

Inside the Glob Implementation

The core matching logic lives in src/utils/glob.ts. The Glob class converts shell-style wildcards into anchored regular expressions through the following algorithm:

  1. Trim whitespace: this.pattern = pattern.trim() (line 22)
  2. Fast-path optimization: Empty patterns, global *, or literal strings without wildcards bypass regex compilation (lines 49–58)
  3. Regex construction:
    • Escape regex metacharacters except * and ? (line 63)
    • Replace * with .* and ? with . (lines 65–66)
    • Wrap with ^ and $ to enforce full-string matching (line 70)

Thus, a pattern like auth0_*_application becomes the regex /^auth0_.*_application$/, matching tool names such as auth0_list_application or auth0_get_application, but not auth0_application_list.

// Simplified logic from src/utils/glob.ts (lines 63-71)
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
const regexPattern = escaped
  .replace(/\*/g, '.*')
  .replace(/\?/g, '.');
this.regex = new RegExp(`^${regexPattern}$`);
return this.regex.test(str); // line 71

Practical Implementation Examples

Filtering by Prefix Pattern

To return only tools whose names start with auth0:

import { getAvailableTools } from './utils/tools.js';
import { loadAllTools } from './utils/config.js';

const allTools = await loadAllTools();
const authTools = getAvailableTools(allTools, ['auth0*']);
// Glob('auth0*') compiles to /^auth0.*$/
console.log(authTools.map(t => t.name));

Combining Multiple Patterns

The system supports disjunctive matching—tools matching any provided pattern are included:

// Match JWT-related tools OR the exact management tool
const selected = getAvailableTools(allTools, ['jwt-*', 'auth0-management']);

Enforcing Read-Only Mode

Pattern filtering executes before security constraints, ensuring logical consistency:

// Returns only read-only tools matching the application pattern
const readOnlyAppTools = getAvailableTools(
  allTools, 
  ['auth0_*_application'], 
  true  // readOnly flag
);
// Internally calls filterToolsByReadOnly (src/utils/tools.ts lines 12-15)

Pattern Validation

Before execution, validate that patterns actually match registered tools to prevent silent empty results:

import { validatePatterns } from './utils/tools.js';

// Throws if either pattern matches zero tools
validatePatterns(['auth0*', 'jwt-*'], allTools);
// Uses Glob.matches() internally (lines 62-65)

Error Handling and Edge Cases

The implementation includes defensive guards for common edge cases:

  • No patterns provided: getAvailableTools returns the full unfiltered list (lines 45–48)
  • Single * pattern: Short-circuits to return all tools without regex overhead (lines 66–68)
  • Invalid patterns: Malformed expressions are caught by the try...catch block in filterToolsByPatterns, which falls back to returning the original tool list rather than crashing (lines 100–108)

Debug logging at lines 93–96 records how many tools each pattern matched, helping diagnose overly broad or narrow filters during development.

Summary

  • Pattern compilation: Each glob string instantiates a Glob object in src/utils/tools.ts (lines 71–73) that compiles wildcards to anchored regexes.
  • Matching strategy: filterToolsByPatterns iterates tools and tests names against compiled patterns, collecting matches in a Set (lines 78–89).
  • Security layering: Read-only filtering occurs after pattern matching via filterToolsByReadOnly (lines 57–59), ensuring safety flags dominate selection logic.
  • Implementation detail: The Glob class in src/utils/glob.ts translates * to .* and ? to ., enforcing full-string matches with ^ and $ anchors.
  • Resilience: Empty patterns return all tools, invalid patterns return the original list, and single * bypasses regex for performance.

Frequently Asked Questions

How does the Auth0 MCP Server handle invalid glob patterns?

If a pattern contains malformed syntax that causes regex compilation to fail, the try...catch block in filterToolsByPatterns (lines 100–108) catches the error and returns the original unfiltered tool list. This prevents the server from crashing due to user input errors while maintaining availability.

What is the difference between auth0_list_* and auth0_*_application patterns?

auth0_list_* compiles to /^auth0_list_.*$/ and matches tools like auth0_list_users or auth0_list_clients, requiring the name to start with auth0_list_. auth0_*_application compiles to /^auth0_.*_application$/ and matches tools like auth0_get_application or auth0_update_application, requiring the name to end with _application.

Can I combine glob patterns with read-only mode restrictions?

Yes. The getAvailableTools function accepts a third boolean parameter for readOnly. When set to true, the system first applies glob filtering via filterToolsByPatterns, then runs filterToolsByReadOnly (lines 12–15) to remove any tools where _meta.readOnly !== true. This ensures you cannot accidentally expose write operations even with broad glob patterns.

Where is the actual regex matching performed in the source code?

The regex test occurs in src/utils/glob.ts at line 71 within the matches(str: string) method. This method is called by filterToolsByPatterns in src/utils/tools.ts during the iteration loop at lines 78–89. The regex itself is constructed earlier in the Glob constructor (lines 63–70) by escaping metacharacters and replacing wildcards with their regex equivalents.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →