Skip to main content
Glama

grep

Search file contents for specific text patterns using regex and glob filtering to find relevant lines across your filesystem.

Instructions

Search file contents for text (grep-like). Returns matching lines. Scope with filePattern (e.g. **/*.ts) to reduce noise. includeHidden=true for dotfiles.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathNoBase directory (default: root). Absolute path required if multiple roots.
patternYesSearch text. RE2 regex when `isRegex=true`.
isRegexNoTreat pattern as RE2 regex (no lookahead/lookbehind/backrefs).
caseSensitiveNoCase-sensitive matching. Default: case-insensitive.
wholeWordNoMatch whole words only
contextLinesNoInclude N lines of context before/after matches
maxResultsNoMaximum match rows to return. Default: 500
filePatternNoGlob for candidate files (e.g. "**/*.ts")**/*
includeHiddenNoInclude hidden items (starting with .)
includeIgnoredNoInclude ignored items (node_modules, etc).

Implementation Reference

  • The primary logic for the "grep" tool, which handles path resolution, file searching, result normalization, preview creation, and externalizing results if necessary.
    async function handleSearchContent(
      args: SearchInput,
      signal?: AbortSignal,
      resourceStore?: ToolRegistrationOptions['resourceStore'],
      onProgress?: (progress: { total?: number; current: number }) => void
    ): Promise<ToolResponse<SearchOutput>> {
      const basePath = resolvePathOrRoot(args.path);
      const regexMatcher = createSearchMatcher(args);
    
      const result = await executeSearch(args, basePath, signal, onProgress);
    
      const normalizedMatches = normalizeMatches(result);
      const searchContext = createSearchContext(args, regexMatcher);
    
      const matchPayloads = buildMatchPayloads(normalizedMatches, searchContext);
    
      const fullStructured = buildSearchStructured(result.summary, matchPayloads);
    
      const preview = buildSearchPreviewState(normalizedMatches, matchPayloads);
    
      if (resourceStore && preview.needsExternalize) {
        const previewStructured: SearchOutput = {
          ...fullStructured,
          matches: preview.visiblePayloads,
          truncated: true,
        };
    
        const entry = resourceStore.putText({
          name: 'grep:matches',
          mimeType: 'application/json',
          text: JSON.stringify(fullStructured),
        });
    
        previewStructured.resourceUri = entry.uri;
        const text = buildSearchText(preview.heading, preview.visibleMatches);
    
        return buildToolResponse(text, previewStructured, [
          buildResourceLink({
            uri: entry.uri,
            name: entry.name,
            mimeType: entry.mimeType,
            description: 'Full grep results as JSON (structuredContent)',
            expiresAt: entry.expiresAt,
          }),
        ]);
      }
    
      const text = buildSearchText(
        preview.heading,
        preview.visibleMatches,
        result.summary
      );
    
      return buildToolResponse(text, fullStructured);
    }
  • The tool contract definition for "grep", including its input/output schema and metadata.
    export const SEARCH_CONTENT_TOOL: ToolContract = {
      name: 'grep',
      title: 'Search Content',
      description:
        'Search file contents for text (grep-like). Returns matching lines. ' +
        'Scope with `filePattern` (e.g. `**/*.ts`) to reduce noise. ' +
        '`includeHidden=true` for dotfiles.',
      inputSchema: SearchContentInputSchema,
      outputSchema: SearchContentOutputSchema,
      annotations: READ_ONLY_TOOL_ANNOTATIONS,
      nuances: [
        'Inline results capped at 50 matches; full results via `resourceUri`.',
      ],
      gotchas: [
        'Skips binary/oversized files silently — verify with `stat` if no matches.',
      ],
      taskSupport: 'optional',
    } as const;
  • Registration function for the "grep" tool on the MCP server.
    export function registerSearchContentTool(
      server: McpServer,
      options: ToolRegistrationOptions = {}
    ): void {
      const handler = (
        args: SearchInput,
        extra: ToolExtra
      ): Promise<ToolResult<SearchOutput>> =>
        executeToolWithDiagnostics({
          toolName: 'grep',
          extra,
          outputSchema: SearchContentOutputSchema,
          context: { path: args.path ?? '.' },
          run: async (signal) => {
            const { pattern, filePattern: scope } = args;
            const progressLabel = `🔎︎ grep: ${truncateProgressPattern(pattern)}`;
            const progress = createToolProgressSession(extra, progressLabel);
    
            const progressWithMessage = ({
              current,
              total,
            }: {
              total?: number;
              current: number;
            }): void => {
              progress.update({
                current,
                ...(total !== undefined ? { total } : {}),
                message: `${progressLabel} [${current} files]`,
              });
            };
    
            try {
              const result = await handleSearchContent(
                args,
                signal,
                options.resourceStore,
                progressWithMessage
              );
    
              const sc = result.structuredContent;
              const { totalMatches = 0, filesMatched = 0, stoppedReason } = sc;
              const suffix = buildCompletionSuffix(
                totalMatches,
                filesMatched,
                scope,
                stoppedReason
              );
    
              const finalCurrent = resolveFinalProgressCurrent(
                progress,
                (sc.filesScanned ?? 0) + 1
              );
    
              progress.complete(`${progressLabel} • ${suffix}`, finalCurrent);
              return result;
            } catch (error) {
              progress.fail(`${progressLabel} • failed`);
              throw error;
            }
          },
          onError: (error) =>
            buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.path ?? '.'),
        });
    
      const { isInitialized } = options;
      const wrappedHandler = wrapToolHandler(handler, {
        guard: isInitialized,
      });
    
      const validatedHandler = withValidatedArgs(
        SearchContentInputSchema,
        wrappedHandler
      );
    
      if (
        registerToolTaskIfAvailable(
          server,
          'grep',
          SEARCH_CONTENT_TOOL,
          validatedHandler,
          options.iconInfo,
          isInitialized
        )
      )
        return;
      server.registerTool(
        'grep',
        withDefaultIcons({ ...SEARCH_CONTENT_TOOL }, options.iconInfo),
        validatedHandler
      );
    }

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/j0hanz/filesystem-mcp'

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