Skip to main content
Glama

ask_grok

Delegate thinking, planning, and real-time web or Twitter/X search tasks to Grok by providing relevant context, files, and prompts for accurate responses.

Instructions

Ask Grok a question. Grok is great for thinking, planning, architecture, and real-time search via web and X/Twitter. Use web_search for current information from the internet. Use x_search to find and analyze posts on X/Twitter. IMPORTANT: Grok has no context about your conversation or codebase. Always include all relevant context directly in the prompt — file contents, error messages, architecture details, constraints, and goals. The more context you provide, the better Grok's response will be. Do not assume Grok knows anything about the current project. Use the files parameter to automatically include file contents with line numbers — this is preferred over pasting code into the prompt. File paths are resolved relative to the server working directory: /app. Responses include a response_id — pass it back as previous_response_id to continue a conversation without resending context.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYesThe question or task for Grok. Include all relevant context — constraints, background, and goals — since Grok has no access to your conversation or files. Use the files parameter to attach source code rather than pasting it inline
previous_response_idNoResponse ID from a previous ask_grok call. Continues the conversation — Grok remembers all prior context so you don't need to resend files or repeat background. Not supported by multi-agent model (beta limitation)
filesNoFiles to include in context. Compact syntax: "path/to/file" (whole file), "path/to/file:10-30" (lines 10-30), "path/to/file:10" (just line 10), "src/**/*.ts" (glob pattern), "large-file.ts:force" (bypass per-file size limit). Paths resolve relative to server cwd.
max_filesNoOverride max file count (default 50). Useful when a glob legitimately matches many files
max_file_sizeNoOverride max per-file size in KB (default 32). Applies to all files without :force suffix
system_promptNoCustom system prompt to guide Grok's behavior
modelNoModel to use. Defaults to grok-4.20-multi-agent. Options: grok-4.20-multi-agent, grok-4.20-reasoning, grok-4.20-non-reasoning, grok-4.1-fast-reasoning, grok-4.1-fast-non-reasoning
web_searchNoWeb search is enabled by default. Set to false to disable
x_searchNoEnable X/Twitter search to find and analyze posts

Implementation Reference

  • src/index.ts:239-332 (registration)
    Registers the 'ask_grok' tool with the MCP server via server.tool(), including its description, schema, and handler callback.
    server.tool(
      "ask_grok",
      `Ask Grok a question. Grok is great for thinking, planning, architecture, and real-time search via web and X/Twitter. Use web_search for current information from the internet. Use x_search to find and analyze posts on X/Twitter. IMPORTANT: Grok has no context about your conversation or codebase. Always include all relevant context directly in the prompt — file contents, error messages, architecture details, constraints, and goals. The more context you provide, the better Grok's response will be. Do not assume Grok knows anything about the current project. Use the files parameter to automatically include file contents with line numbers — this is preferred over pasting code into the prompt. File paths are resolved relative to the server working directory: ${process.cwd()}. Responses include a response_id — pass it back as previous_response_id to continue a conversation without resending context.`,
      {
        prompt: z.string().describe("The question or task for Grok. Include all relevant context — constraints, background, and goals — since Grok has no access to your conversation or files. Use the files parameter to attach source code rather than pasting it inline"),
        previous_response_id: z
          .string()
          .optional()
          .describe("Response ID from a previous ask_grok call. Continues the conversation — Grok remembers all prior context so you don't need to resend files or repeat background. Not supported by multi-agent model (beta limitation)"),
        files: z
          .array(z.string())
          .optional()
          .describe('Files to include in context. Compact syntax: "path/to/file" (whole file), "path/to/file:10-30" (lines 10-30), "path/to/file:10" (just line 10), "src/**/*.ts" (glob pattern), "large-file.ts:force" (bypass per-file size limit). Paths resolve relative to server cwd.'),
        max_files: z
          .number()
          .optional()
          .describe("Override max file count (default 50). Useful when a glob legitimately matches many files"),
        max_file_size: z
          .number()
          .optional()
          .describe("Override max per-file size in KB (default 32). Applies to all files without :force suffix"),
        system_prompt: z
          .string()
          .optional()
          .describe("Custom system prompt to guide Grok's behavior"),
        model: z
          .string()
          .optional()
          .describe(
            "Model to use. Defaults to grok-4.20-multi-agent. Options: grok-4.20-multi-agent, grok-4.20-reasoning, grok-4.20-non-reasoning, grok-4.1-fast-reasoning, grok-4.1-fast-non-reasoning"
          ),
        web_search: z
          .boolean()
          .optional()
          .default(true)
          .describe("Web search is enabled by default. Set to false to disable"),
        x_search: z
          .boolean()
          .optional()
          .describe("Enable X/Twitter search to find and analyze posts"),
      },
      async ({ prompt, previous_response_id, files, max_files, max_file_size, system_prompt, model, web_search, x_search }) => {
        const messages: GrokMessage[] = [];
    
        // On continuations, Grok already has prior context — only send the new prompt
        if (previous_response_id) {
          messages.push({ role: "user", content: prompt });
        } else {
          if (system_prompt) {
            messages.push({ role: "system", content: system_prompt });
          }
    
          let userContent = prompt;
    
          if (files && files.length > 0) {
            const result = resolveFiles(files, { maxFiles: max_files, maxFileSize: max_file_size });
            if (!result.ok) {
              return { isError: true, content: [{ type: "text" as const, text: result.error }] };
            }
            const cwd = process.cwd();
            const fileBlocks = [`Working directory: ${cwd}\n`];
            for (const f of result.files) {
              fileBlocks.push(`--- ${f.path}${f.range} ---\n${f.content}\n---`);
            }
            userContent = `${fileBlocks.join("\n\n")}\n\n${prompt}`;
          }
    
          messages.push({ role: "user", content: userContent });
        }
    
        const tools: GrokTool[] = [];
        if (web_search !== false) {
          tools.push({ type: "web_search" });
        }
        if (x_search) {
          tools.push({ type: "x_search" });
        }
    
        const result = await callGrok({
          messages,
          model,
          tools: tools.length > 0 ? tools : undefined,
          previousResponseId: previous_response_id,
        });
    
        const text = result.responseId
          ? `${result.text}\n\n---\nresponse_id: ${result.responseId}`
          : result.text;
    
        return {
          content: [{ type: "text" as const, text }],
        };
      }
    );
  • Zod schema definitions for the ask_grok tool parameters: prompt, previous_response_id, files, max_files, max_file_size, system_prompt, model, web_search, x_search.
    {
      prompt: z.string().describe("The question or task for Grok. Include all relevant context — constraints, background, and goals — since Grok has no access to your conversation or files. Use the files parameter to attach source code rather than pasting it inline"),
      previous_response_id: z
        .string()
        .optional()
        .describe("Response ID from a previous ask_grok call. Continues the conversation — Grok remembers all prior context so you don't need to resend files or repeat background. Not supported by multi-agent model (beta limitation)"),
      files: z
        .array(z.string())
        .optional()
        .describe('Files to include in context. Compact syntax: "path/to/file" (whole file), "path/to/file:10-30" (lines 10-30), "path/to/file:10" (just line 10), "src/**/*.ts" (glob pattern), "large-file.ts:force" (bypass per-file size limit). Paths resolve relative to server cwd.'),
      max_files: z
        .number()
        .optional()
        .describe("Override max file count (default 50). Useful when a glob legitimately matches many files"),
      max_file_size: z
        .number()
        .optional()
        .describe("Override max per-file size in KB (default 32). Applies to all files without :force suffix"),
      system_prompt: z
        .string()
        .optional()
        .describe("Custom system prompt to guide Grok's behavior"),
      model: z
        .string()
        .optional()
        .describe(
          "Model to use. Defaults to grok-4.20-multi-agent. Options: grok-4.20-multi-agent, grok-4.20-reasoning, grok-4.20-non-reasoning, grok-4.1-fast-reasoning, grok-4.1-fast-non-reasoning"
        ),
      web_search: z
        .boolean()
        .optional()
        .default(true)
        .describe("Web search is enabled by default. Set to false to disable"),
      x_search: z
        .boolean()
        .optional()
        .describe("Enable X/Twitter search to find and analyze posts"),
    },
  • The async handler function for ask_grok that builds messages (including file context), configures web/x_search tools, calls the Grok API, and returns the response text with response_id.
    async ({ prompt, previous_response_id, files, max_files, max_file_size, system_prompt, model, web_search, x_search }) => {
      const messages: GrokMessage[] = [];
    
      // On continuations, Grok already has prior context — only send the new prompt
      if (previous_response_id) {
        messages.push({ role: "user", content: prompt });
      } else {
        if (system_prompt) {
          messages.push({ role: "system", content: system_prompt });
        }
    
        let userContent = prompt;
    
        if (files && files.length > 0) {
          const result = resolveFiles(files, { maxFiles: max_files, maxFileSize: max_file_size });
          if (!result.ok) {
            return { isError: true, content: [{ type: "text" as const, text: result.error }] };
          }
          const cwd = process.cwd();
          const fileBlocks = [`Working directory: ${cwd}\n`];
          for (const f of result.files) {
            fileBlocks.push(`--- ${f.path}${f.range} ---\n${f.content}\n---`);
          }
          userContent = `${fileBlocks.join("\n\n")}\n\n${prompt}`;
        }
    
        messages.push({ role: "user", content: userContent });
      }
    
      const tools: GrokTool[] = [];
      if (web_search !== false) {
        tools.push({ type: "web_search" });
      }
      if (x_search) {
        tools.push({ type: "x_search" });
      }
    
      const result = await callGrok({
        messages,
        model,
        tools: tools.length > 0 ? tools : undefined,
        previousResponseId: previous_response_id,
      });
    
      const text = result.responseId
        ? `${result.text}\n\n---\nresponse_id: ${result.responseId}`
        : result.text;
    
      return {
        content: [{ type: "text" as const, text }],
      };
    }
  • callGrok helper function that sends the request to the x.ai Responses API (POST /v1/responses) and extracts the output_text from the response.
    async function callGrok(options: {
      messages: GrokMessage[];
      model?: string;
      tools?: GrokTool[];
      previousResponseId?: string;
    }): Promise<GrokResult> {
      const model = options.model ?? "grok-4.20-multi-agent";
    
      const body: Record<string, unknown> = {
        model,
        input: options.messages.map((m) => ({
          role: m.role,
          content: m.content,
        })),
        store: true,
        include: ["reasoning.encrypted_content"],
      };
    
      if (options.previousResponseId) {
        body.previous_response_id = options.previousResponseId;
      }
    
      if (options.tools && options.tools.length > 0) {
        body.tools = options.tools;
      }
    
      const response = await fetch("https://api.x.ai/v1/responses", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${apiKey}`,
        },
        body: JSON.stringify(body),
      });
    
      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`Grok API error (${response.status}): ${errorText}`);
      }
    
      const data = (await response.json()) as ResponsesApiResponse;
    
      for (const item of data.output) {
        if (item.type === "message" && item.content) {
          for (const block of item.content) {
            if (block.type === "output_text" && block.text) {
              return { text: block.text, responseId: data.id ?? undefined };
            }
          }
        }
      }
    
      throw new Error("No text content in Grok response");
    }
  • parseFileArg helper used by resolveFiles to parse file argument syntax (paths, line ranges, globs, :force flag).
    function parseFileArg(arg: string): FileSpec[] {
      // Strip :force suffix first
      let force = false;
      let input = arg;
      if (input.endsWith(":force")) {
        force = true;
        input = input.slice(0, -6);
      }
    
      // "path/to/file:10-30" or "path/to/file:10" or "path/to/file" or "src/**/*.ts"
      const match = input.match(/^(.+?):(\d+)(?:-(\d+))?$/);
      let pattern: string;
      let startLine: number | undefined;
      let endLine: number | undefined;
    
      if (match) {
        pattern = match[1];
        startLine = parseInt(match[2], 10);
        endLine = match[3] ? parseInt(match[3], 10) : startLine;
      } else {
        pattern = input;
      }
    
      const resolved = resolve(pattern);
    
      if (/[*?[\]]/.test(pattern)) {
        const paths = globSync(pattern).sort();
        if (paths.length === 0) {
          return [{ path: pattern, force }]; // will fail at read time with a clear error
        }
        return paths.map((p) => ({ path: resolve(p as string), startLine, endLine, force }));
      }
    
      return [{ path: resolved, startLine, endLine, force }];
    }
Behavior5/5

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

Despite no annotations, the description fully discloses behavioral traits: Grok has no context about conversation or codebase, responses include a response_id for continuation, file inclusion syntax, model options, and search defaults. The limitation of previous_response_id in multi-agent mode is also noted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is fairly long but well-organized, using bold for emphasis and clear sections. Every sentence contributes essential information. Could be slightly more concise, but overall efficient for the complexity covered.

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 tool with 9 parameters and no output schema, the description is comprehensive: covers all input aspects, explains the output (response_id), gives continuation guidance, and addresses the critical context limitation. Complete and actionable.

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

Parameters5/5

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

Schema coverage is 100%, but the description adds substantial value: explains the rationale for using files, provides detailed file path syntax, clarifies the purpose of previous_response_id, and describes model options and search behavior. It enriches the parameter meanings significantly beyond the schema.

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 'Ask Grok a question' and outlines what Grok excels at (thinking, planning, architecture, real-time search). It distinguishes from related tools like web_search and x_search, though they are not listed as siblings on this server. The purpose is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides when to use this tool vs alternatives: 'Use web_search for current information... Use x_search to find and analyze posts.' Also gives critical usage guidance: include full context, use files parameter, how to continue conversations with previous_response_id. No ambiguity.

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/PKWadsy/grok-mcp'

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