Skip to main content
Glama
Aaryan-Kapoor

MCP Character Tools

Count Substring

count_substring
Read-onlyIdempotent

Count how many times a specific pattern appears in text, with options for case sensitivity and overlapping matches. Returns the total count and positions of each occurrence.

Instructions

Count occurrences of a substring or pattern in text.

Can count overlapping or non-overlapping matches.

Args:

  • text (string): The text to search in

  • substring (string): The pattern to find

  • case_sensitive (boolean): Match case exactly (default: false)

  • overlapping (boolean): Count overlapping matches (default: false)

Returns: count and positions of each match.

Example: count_substring("banana", "ana", overlapping=true) → count: 2, positions: [1, 3]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
textYesThe text to search in
substringYesThe pattern to find
case_sensitiveNoMatch case exactly
overlappingNoCount overlapping matches

Implementation Reference

  • Core implementation of the count_substring tool logic: counts occurrences of a substring in text, handling case sensitivity and optional overlapping matches using indexOf in a loop.
    export function countSubstring(input: CountSubstringInput): CountSubstringOutput {
      const { text, substring, case_sensitive, overlapping } = input;
      
      if (substring.length === 0) {
        return {
          text,
          substring,
          count: 0,
          case_sensitive,
          overlapping,
          positions: [],
        };
      }
    
      const searchText = case_sensitive ? text : text.toLowerCase();
      const searchSubstring = case_sensitive ? substring : substring.toLowerCase();
      
      const positions: number[] = [];
      let startIndex = 0;
      
      while (startIndex < searchText.length) {
        const foundIndex = searchText.indexOf(searchSubstring, startIndex);
        if (foundIndex === -1) break;
        
        positions.push(foundIndex);
        startIndex = overlapping ? foundIndex + 1 : foundIndex + searchSubstring.length;
      }
    
      return {
        text,
        substring,
        count: positions.length,
        case_sensitive,
        overlapping,
        positions,
      };
    }
  • TypeScript interfaces defining the input and output structure for the countSubstring function.
    export interface CountSubstringInput {
      text: string;
      substring: string;
      case_sensitive: boolean;
      overlapping: boolean;
    }
    
    export interface CountSubstringOutput {
      text: string;
      substring: string;
      count: number;
      case_sensitive: boolean;
      overlapping: boolean;
      positions: number[];
    }
  • src/index.ts:128-164 (registration)
    MCP server registration for the 'count_substring' tool, including description, Zod input schema validation, and wrapper handler that invokes the core countSubstring function and formats the response.
    server.registerTool(
      "count_substring",
      {
        title: "Count Substring",
        description: `Count occurrences of a substring or pattern in text.
    
    Can count overlapping or non-overlapping matches.
    
    Args:
      - text (string): The text to search in
      - substring (string): The pattern to find
      - case_sensitive (boolean): Match case exactly (default: false)
      - overlapping (boolean): Count overlapping matches (default: false)
    
    Returns: count and positions of each match.
    
    Example: count_substring("banana", "ana", overlapping=true) → count: 2, positions: [1, 3]`,
        inputSchema: z.object({
          text: z.string().min(1).describe("The text to search in"),
          substring: z.string().min(1).describe("The pattern to find"),
          case_sensitive: z.boolean().default(false).describe("Match case exactly"),
          overlapping: z.boolean().default(false).describe("Count overlapping matches"),
        }).strict(),
        annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
      },
      async (params) => {
        const result = countSubstring({
          text: params.text,
          substring: params.substring,
          case_sensitive: params.case_sensitive,
          overlapping: params.overlapping,
        });
        return {
          content: [{ type: "text" as const, text: `Found "${result.substring}" ${result.count} time(s) in "${result.text}" at positions: [${result.positions.join(', ')}]` }],
        };
      }
    );
  • Zod schema for input validation used in the tool registration.
    inputSchema: z.object({
      text: z.string().min(1).describe("The text to search in"),
      substring: z.string().min(1).describe("The pattern to find"),
      case_sensitive: z.boolean().default(false).describe("Match case exactly"),
      overlapping: z.boolean().default(false).describe("Count overlapping matches"),
    }).strict(),
Behavior4/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=false, covering safety and idempotency. The description adds valuable behavioral context beyond annotations by explaining overlapping vs non-overlapping match behavior and providing a concrete example with return format (count and positions), which helps the agent understand the tool's operational characteristics.

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 well-structured and appropriately sized. It starts with a clear purpose statement, explains key behavioral aspects, lists parameters with brief descriptions, specifies return values, and provides a concrete example. Every sentence adds value with zero wasted content.

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?

For a text processing tool with comprehensive annotations and full schema coverage, the description provides complete context. It explains the tool's purpose, key behavioral traits (overlapping matches), parameters, return format, and includes an illustrative example. No output schema exists, but the description adequately describes return values.

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 fully documents all parameters. The description repeats parameter names and brief descriptions in the Args section but doesn't add significant meaning beyond what's in the schema. The example illustrates parameter usage but doesn't enhance semantic understanding of individual parameters.

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 with specific verbs ('count occurrences of a substring or pattern in text') and distinguishes it from siblings like 'count_letter' or 'count_letters' by focusing on substring/pattern matching rather than individual characters. It specifies both what it does and what it returns.

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 substrings/patterns in text) but doesn't explicitly mention when not to use it or name specific alternatives among siblings. It implies usage through the example and parameter descriptions but lacks explicit exclusion guidance.

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/Aaryan-Kapoor/mcp-character-tools'

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