# How Auth0 MCP Server Glob Pattern Tool Filtering Works Internally

> Discover how Auth0 MCP Server's glob pattern filtering works internally. Learn how patterns like auth0_list_* compile to regex, match tools, and enforce read-only rules. Explore the three-step pipeline now.

- Repository: [Auth0/auth0-mcp-server](https://github.com/auth0/auth0-mcp-server)
- Tags: internals
- Published: 2026-02-25

---

**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`](https://github.com/auth0/auth0-mcp-server/blob/main/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`](https://github.com/auth0/auth0-mcp-server/blob/main/src/utils/tools.ts), where the system prepares matchers before touching the tool registry.

```typescript
// 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.

```typescript
// 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`](https://github.com/auth0/auth0-mcp-server/blob/main/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`.

```typescript
// 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`:

```typescript
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:

```typescript
// 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:

```typescript
// 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:

```typescript
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`](https://github.com/auth0/auth0-mcp-server/blob/main/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`](https://github.com/auth0/auth0-mcp-server/blob/main/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`](https://github.com/auth0/auth0-mcp-server/blob/main/src/utils/glob.ts) at line 71 within the `matches(str: string)` method. This method is called by `filterToolsByPatterns` in [`src/utils/tools.ts`](https://github.com/auth0/auth0-mcp-server/blob/main/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.