Skip to main content
Glama
rajnaveen344

LSP Tools MCP Server

by rajnaveen344

find_regex_position

Locate regex pattern matches in files by returning line and column positions for each occurrence, enabling precise text analysis and pattern identification.

Instructions

Find the positions (line and column) of regex pattern matches in a file. Returns an array of matches with their positions. Line and column numbers are 0-indexed (first line is 0). Each match includes: match (matched text), line (starting line), column (starting column), endLine (ending line), and endColumn (ending column, exclusive). IMPORTANT: The path parameter must be an absolute path. Relative paths are not supported.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to the file to search in. Relative paths are not supported.
regexYesRegular expression pattern to search for

Implementation Reference

  • The handler case block for the 'find_regex_position' tool. It parses input arguments, validates the file path against allowed directories, calls the helper function to find regex positions, and returns the JSON-stringified results or an error.
    case "find_regex_position": {
      try {
        // Validate input
        const parsed = FindRegexPositionArgsSchema.parse(args);
    
        // Validate path for security
        const validatedPath = await validatePath(parsed.path, allowedDirectories);
    
        // Find regex positions
        const positions = await findRegexPositionsInFile(validatedPath, parsed.regex);
    
        return {
          content: [{
            type: 'text',
            text: JSON.stringify(positions),
          }]
        };
      } catch (error) {
        return {
          error: error instanceof Error ? error.message : String(error),
        };
      }
    }
  • Zod schema defining the input arguments for the 'find_regex_position' tool: path (absolute file path) and regex (pattern string). Used for validation and JSON schema generation.
    // Schema definitions for the find_regex_position tool
    const FindRegexPositionArgsSchema = z.object({
      path: z.string().describe("Absolute path to the file to search in. Relative paths are not supported."),
      regex: z.string().describe("Regular expression pattern to search for"),
    });
  • src/index.ts:68-78 (registration)
    Tool registration in the ListToolsRequest handler, including name, detailed description, and input schema reference.
    {
      name: "find_regex_position",
      description:
        "Find the positions (line and column) of regex pattern matches in a file. " +
        "Returns an array of matches with their positions. " +
        "Line and column numbers are 0-indexed (first line is 0). " +
        "Each match includes: match (matched text), line (starting line), column (starting column), " +
        "endLine (ending line), and endColumn (ending column, exclusive). " +
        "IMPORTANT: The path parameter must be an absolute path. Relative paths are not supported.",
      inputSchema: zodToJsonSchema(FindRegexPositionArgsSchema),
    },
  • Helper function that reads the file content and delegates to findRegexPositionsInContent for processing. This is the entry point called by the handler.
    export async function findRegexPositionsInFile(filePath: string, regexStr: string): Promise<RegexMatchPosition[]> {
      const content = await fs.readFile(filePath, "utf-8");
      return findRegexPositionsInContent(content, regexStr);
    }
  • Core helper function that executes the regex search on content, calculates precise 0-indexed line/column positions for start and end of each match, and returns an array of RegexMatchPosition objects.
    export function findRegexPositionsInContent(content: string, regexStr: string): RegexMatchPosition[] {
      // Split content into lines for position calculation
      const lines = content.split("\n");
    
      try {
        // Create regex with global flag to find all matches
        const regex = new RegExp(regexStr, "g");
    
        const matches: RegexMatchPosition[] = [];
        let match: RegExpExecArray | null;
    
        // Process each match
        while ((match = regex.exec(content)) !== null) {
          const matchText = match[0];
          const matchStartIndex = match.index;
    
          // Calculate line and column for start position
          let currentIndex = 0;
          let startLine = 0;
          let startColumn = 0;
    
          for (let i = 0; i < lines.length; i++) {
            const lineLength = lines[i].length + 1; // +1 for the newline character
    
            if (currentIndex + lineLength > matchStartIndex) {
              startLine = i;
              startColumn = matchStartIndex - currentIndex;
              break;
            }
    
            currentIndex += lineLength;
          }
    
          // Calculate line and column for end position
          let endLine = startLine;
          let endColumn = startColumn;
          let charsRemaining = matchText.length;
    
          while (charsRemaining > 0 && endLine < lines.length) {
            const lineRemainder = lines[endLine].length - endColumn + 1; // +1 for newline
    
            if (charsRemaining <= lineRemainder) {
              endColumn += charsRemaining;
              charsRemaining = 0;
            } else {
              charsRemaining -= lineRemainder;
              endLine++;
              endColumn = 0;
            }
          }
    
          // Adjust end column to be exclusive (pointing to the character after the match)
          if (endColumn > 0 && lines[endLine] && endColumn <= lines[endLine].length) {
            // No adjustment needed, end column already points to the character after the match
          } else {
            // End of line or beyond, set to 0 and increment line
            endColumn = 0;
            endLine++;
          }
    
          matches.push({
            match: matchText,
            line: startLine,
            column: startColumn,
            endLine: endLine,
            endColumn: endColumn
          });
        }
    
        return matches;
      } catch (error) {
        throw new Error(`Error processing regex: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the return format (array structure with specific fields), indexing convention (0-indexed), and path requirement (absolute only). It doesn't mention error handling, performance characteristics, or permission requirements, but provides substantial behavioral context.

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 efficiently structured with zero wasted sentences. It front-loads the core purpose, details the return format, and ends with the critical constraint. Every sentence adds essential information for tool understanding and usage.

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

Completeness4/5

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

For a tool with 2 parameters, 100% schema coverage, and no output schema, the description provides excellent context about the return format and behavioral constraints. It could potentially mention error cases or performance considerations, but covers the essential information needed to use the tool effectively.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters thoroughly. The description reinforces the 'absolute path' requirement for the path parameter but doesn't add meaningful semantic context beyond what's in the schema. This meets the baseline for high schema coverage.

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 specific action ('Find the positions of regex pattern matches'), resource ('in a file'), and output format ('Returns an array of matches with their positions'). It distinguishes itself from the sibling tool 'list_allowed_directories' by focusing on regex matching rather than directory listing.

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 clear context for when to use this tool (searching for regex matches in files) and includes an important constraint ('path parameter must be an absolute path'). However, it doesn't explicitly state when NOT to use it or mention alternatives to regex-based searching.

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/rajnaveen344/lsp-tools-mcp'

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