Skip to main content
Glama
yfmeii

WeChat Mini Program Dev MCP

by yfmeii

element_tap

Simulate a tap on a WeChat Mini Program page element using CSS selectors. Supports selecting the nth element with [index=N] and targeting inner components via innerSelector.

Instructions

通过 CSS 选择器模拟点击 WXML 元素。支持 [index=N] 语法选择第 N 个元素。如需点击自定义组件内部的元素,请使用 innerSelector 参数:selector 设为组件 ID 选择器(如 #my-component)或标签选择器,innerSelector 设为组件内部元素的选择器。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
connectionNo
selectorYes
innerSelectorNo
waitMsNo

Implementation Reference

  • The `createTapElementTool` function returns the tool definition including the `execute` handler that resolves an element by selector (with optional innerSelector and [index=N] syntax), calls `.tap()` on it, optionally waits, and returns a result text. This is the main handler logic for the 'element_tap' tool.
    function createTapElementTool(manager: WeappAutomatorManager): AnyTool {
      return {
        name: "element_tap",
        description: "通过 CSS 选择器模拟点击 WXML 元素。支持 [index=N] 语法选择第 N 个元素。如需点击自定义组件内部的元素,请使用 innerSelector 参数:selector 设为组件 ID 选择器(如 #my-component)或标签选择器,innerSelector 设为组件内部元素的选择器。",
        parameters: tapElementParameters,
        execute: async (rawArgs, context: ToolContext) =>
          withUserErrorResult(async () => {
          const args = tapElementParameters.parse(rawArgs ?? {});
          const waitMs = args.waitMs;
    
          return manager.withPage(
            context.log,
            { overrides: args.connection },
            async (page) => {
              let selector = args.selector;
              let indexHint: number | undefined;
    
              const parsed = parseSelectorWithIndex(selector);
              if (parsed) {
                selector = parsed.baseSelector;
                indexHint = parsed.index;
              }
    
              let element;
              if (indexHint === undefined) {
                element = await resolveElement(
                  page,
                  args.selector,
                  args.innerSelector
                );
              } else {
                if (typeof page.$$ !== "function") {
                  throw new UserError("当前页面不支持查询元素数组。");
                }
    
                let elements = await page.$$(selector);
                if (!Array.isArray(elements) || elements.length === 0) {
                  throw new UserError(`未找到元素: "${selector}"`);
                }
    
                if (indexHint < 0 || indexHint >= elements.length) {
                  throw new UserError(`索引 ${indexHint} 超出范围 (0-${elements.length - 1})。`);
                }
    
                element = elements[indexHint];
    
                if (args.innerSelector) {
                  if (typeof element.$ !== "function") {
                    throw new UserError(`元素 "${args.selector}" 不支持查询内部元素。`);
                  }
                  const inner = await element.$(args.innerSelector);
                  if (!inner) {
                    throw new UserError(
                      `在元素 "${args.selector}" 内未找到选择器 "${args.innerSelector}" 对应的元素。`
                    );
                  }
                  element = inner;
                }
              }
    
              try {
                await element.tap();
              } catch (error) {
                const message = error instanceof Error ? error.message : String(error);
                throw new UserError(
                  `点击元素 "${args.selector}"${args.innerSelector ? ` -> "${args.innerSelector}"` : ""} 失败: ${message}`
                );
              }
    
              if (waitMs) {
                await waitOnPage(page, waitMs);
              }
    
              return toTextResult(
                `已点击元素 "${args.selector}"${args.innerSelector ? ` -> "${args.innerSelector}"` : ""}${waitMs ? ` 并等待 ${waitMs}ms` : ""}。`
              );
            }
          );
          }),
      };
  • The `tapElementParameters` Zod schema defines the input parameters for the element_tap tool: selector (required), innerSelector (optional), waitMs (optional), and connection (optional via spread of connectionContainerSchema).
    const tapElementParameters = connectionContainerSchema.extend({
      selector: z.string().trim().min(1),
      innerSelector: z.string().trim().min(1).optional(),
      waitMs: z.coerce.number().int().nonnegative().optional(),
    });
  • src/tools.ts:7-13 (registration)
    The `createTools` function in src/tools.ts aggregates all tools, including `createElementTools(manager)` which creates the 'element_tap' tool.
    export function createTools(manager: WeappAutomatorManager): AnyTool[] {
      return [
        ...createApplicationTools(manager),
        ...createPageTools(manager),
        ...createElementTools(manager),
      ];
    }
  • The `createElementTools` function returns an array of tool creators including `createTapElementTool(manager)`, which registers 'element_tap' in the tool list.
    export function createElementTools(
      manager: WeappAutomatorManager
    ): AnyTool[] {
      return [
        createTapElementTool(manager),
        createInputTextTool(manager),
        createCallElementMethodTool(manager),
        createGetElementDataTool(manager),
        createSetElementDataTool(manager),
        createGetInnerElementTool(manager),
        createGetInnerElementsTool(manager),
        createGetElementWxmlTool(manager),
        createGetElementStylesTool(manager),
        createScrollToTool(manager),
        createGetAttributesTool(manager),
        createGetBoundingClientRectTool(manager),
      ];
    }
  • The `parseSelectorWithIndex` helper parses the [index=N] syntax from the selector string, used by the element_tap handler to support index-based element selection.
    export function parseSelectorWithIndex(selector: string): { baseSelector: string; index: number } | null {
      // 匹配 selector[index=N] 语法
      const match = selector.match(/^(.+?)\[index=(\d+)\]$/);
      if (match) {
        return {
          baseSelector: match[1],
          index: parseInt(match[2], 10),
        };
      }
      return null;
    }
Behavior2/5

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

No annotations are provided, so the description must fully describe behavior. It mentions simulating a click but does not specify whether it waits for visibility, the type of click (tap/long press), or any side effects. The waitMs parameter's role is unclear. This leaves significant behavioral gaps for an agent.

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 composed of two concise sentences in Chinese, front-loading the main purpose and then adding details about index syntax and innerSelector. Every sentence adds value without redundancy.

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

Completeness2/5

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

Given no annotations, no output schema, and a complex nested connection parameter, the description lacks details on waitMs behavior, connection requirements, and return values. It covers selector usage well but omits prerequisites and behavioral context, leaving the tool incompletely specified for autonomous use.

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 coverage is 0%, so the description must compensate. It adds meaning for selector (CSS selector with index syntax) and innerSelector (component-inside-element), explaining their relationship. However, it does not explain connection or waitMs, leaving those parameters unclear. It partially offsets the low 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 it simulates clicking a WXML element via CSS selector, distinguishing it from other element_* tools like element_input. It also details the [index=N] syntax and innerSelector for custom components, which clarifies its specific functionality.

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 explicitly explains when to use innerSelector (for custom components) and how to set parameters. However, it does not compare to alternatives like element_callMethod or page_getElement, nor does it state when not to use this tool. Still, it provides good contextual guidance for its primary use case.

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/yfmeii/weapp-dev-mcp'

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