[
  {
    "function": {
      "description": "Collect structured multiple-choice answers from the user.\nProvide one or more questions with options, and set allow_multiple when multi-select is appropriate.\n\nUse this tool when you need to gather specific information from the user through a structured question format.\nEach question should have:\n- A unique id (used to match answers)\n- A clear prompt/question text\n- At least 2 options for the user to choose from\n- An optional allow_multiple flag (defaults to false for single-select)\nBy default, the tool will present the questions to the user and wait for their responses before continuing.",
      "name": "AskQuestion",
      "parameters": {
        "properties": {
          "questions": {
            "description": "Array of questions to present to the user (minimum 1 required)",
            "items": {
              "properties": {
                "allow_multiple": {
                  "description": "If true, user can select multiple options. Defaults to false.",
                  "type": "boolean"
                },
                "id": {
                  "description": "Unique identifier for this question",
                  "type": "string"
                },
                "options": {
                  "description": "Array of answer options (minimum 2 required)",
                  "items": {
                    "properties": {
                      "id": {
                        "description": "Unique identifier for this option",
                        "type": "string"
                      },
                      "label": {
                        "description": "Display text for this option",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "label"
                    ],
                    "type": "object"
                  },
                  "minItems": 2,
                  "type": "array"
                },
                "prompt": {
                  "description": "The question text to display to the user",
                  "type": "string"
                }
              },
              "required": [
                "id",
                "prompt",
                "options"
              ],
              "type": "object"
            },
            "minItems": 1,
            "type": "array"
          },
          "title": {
            "description": "Optional title for the questions form",
            "type": "string"
          }
        },
        "required": [
          "questions"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Call an MCP tool by server identifier and tool name with arbitrary JSON arguments. IMPORTANT: Always read the tool's schema/descriptor BEFORE calling to ensure correct parameters.\n\nExample:\n{\n  \"server\": \"my-mcp-server\",\n  \"toolName\": \"search\",\n  \"arguments\": { \"query\": \"example\", \"limit\": 10 }\n}",
      "name": "CallMcpTool",
      "parameters": {
        "properties": {
          "arguments": {
            "description": "Arguments to pass to the MCP tool, as described in the tool descriptor.",
            "type": "object"
          },
          "server": {
            "description": "Identifier of the MCP server hosting the tool.",
            "type": "string"
          },
          "toolName": {
            "description": "Name of the MCP tool to invoke.",
            "type": "string"
          }
        },
        "required": [
          "server",
          "toolName"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Deletes a file at the specified path. The operation will fail gracefully if:\n    - The file doesn't exist\n    - The operation is rejected for security reasons\n    - The file cannot be deleted",
      "name": "Delete",
      "parameters": {
        "properties": {
          "path": {
            "description": "The absolute path of the file to delete",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Reads a specific resource from an MCP server, identified by server name and resource URI. Optionally, set downloadPath (relative to the workspace) to save the resource to disk; when set, the resource will be downloaded and not returned to the model.",
      "name": "FetchMcpResource",
      "parameters": {
        "properties": {
          "downloadPath": {
            "description": "Optional relative path in the workspace to save the resource to. When set, the resource is written to disk and is not returned to the model.",
            "type": "string"
          },
          "server": {
            "description": "The MCP server identifier",
            "type": "string"
          },
          "uri": {
            "description": "The resource URI to read",
            "type": "string"
          }
        },
        "required": [
          "server",
          "uri"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "\nTool to search for files matching a glob pattern\n\n- Works fast with codebases of any size\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files by name patterns\n- You have the capability to call multiple tools in a single response. It is always better to speculatively perform multiple searches that are potentially useful as a batch.\n",
      "name": "Glob",
      "parameters": {
        "properties": {
          "glob_pattern": {
            "description": "The glob pattern to match files against.\nPatterns not starting with \"**/\" are automatically prepended with \"**/\" to enable recursive searching.\n\nExamples:\n\t- \"*.js\" (becomes \"**/*.js\") - find all .js files\n\t- \"**/node_modules/**\" - find all node_modules directories\n\t- \"**/test/**/test_*.ts\" - find all test_*.ts files in any test directory",
            "type": "string"
          },
          "target_directory": {
            "description": "Absolute path to directory to search for files in. If not provided, defaults to Cursor workspace root.",
            "type": "string"
          }
        },
        "required": [
          "glob_pattern"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "A powerful search tool built on ripgrep\nUsage:\n- Prefer using Grep for search tasks when you know the exact symbols or strings to search for. Whenever possible, use this tool instead of invoking grep or rg as a terminal command. The Grep tool has been optimized for speed and file restrictions inside Cursor.\n- Supports full regex syntax (e.g., \"log.*Error\", \"function\\s+\\w+\")\n- Filter files with glob parameter (e.g., \".js\", \"**/.tsx\") or type parameter (e.g., \"js\", \"py\", \"rust\")\n- Output modes: \"content\" shows matching lines (default), \"files_with_matches\" shows only file paths, \"count\" shows match counts\n- Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use interface\\{\\} to find interface{} in Go code)\n- Multiline matching: By default patterns match within single lines only. For cross-line patterns like struct \\{[\\s\\S]*?field, use multiline: true\n- Results are capped to several thousand output lines for responsiveness; when truncation occurs, the results report \"at least\" counts, but are otherwise accurate.\n- Content output formatting closely follows ripgrep output format: '-' for context lines, ':' for match lines, and all context/match lines below each file group.",
      "name": "Grep",
      "parameters": {
        "properties": {
          "-A": {
            "description": "Number of lines to show after each match (rg -A). Requires output_mode: \"content\", ignored otherwise.",
            "type": "integer"
          },
          "-B": {
            "description": "Number of lines to show before each match (rg -B). Requires output_mode: \"content\", ignored otherwise.",
            "type": "integer"
          },
          "-C": {
            "description": "Number of lines to show before and after each match (rg -C). Requires output_mode: \"content\", ignored otherwise.",
            "type": "integer"
          },
          "-i": {
            "description": "Case insensitive search (rg -i) Defaults to false",
            "type": "boolean"
          },
          "glob": {
            "description": "Glob pattern to filter files (e.g. \"*.js\", \"*.{ts,tsx}\") - maps to rg --glob",
            "type": "string"
          },
          "head_limit": {
            "description": "Limit output size. For \"content\" mode: limits total matches shown. For \"files_with_matches\" and \"count\" modes: limits number of files.",
            "minimum": 0,
            "type": "integer"
          },
          "multiline": {
            "description": "Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false.",
            "type": "boolean"
          },
          "offset": {
            "description": "Skip first N entries. For \"content\" mode: skips first N matches. For \"files_with_matches\" and \"count\" modes: skips first N files. Use with head_limit for pagination.",
            "minimum": 0,
            "type": "integer"
          },
          "output_mode": {
            "description": "Output mode: \"content\" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), \"files_with_matches\" shows file paths (supports head_limit), \"count\" shows match counts (supports head_limit). Defaults to \"content\".",
            "enum": [
              "content",
              "files_with_matches",
              "count"
            ],
            "type": "string"
          },
          "path": {
            "description": "File or directory to search in (rg pattern -- PATH). Defaults to Cursor workspace root.",
            "type": "string"
          },
          "pattern": {
            "description": "The regular expression pattern to search for in file contents",
            "type": "string"
          },
          "type": {
            "description": "File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types.",
            "type": "string"
          }
        },
        "required": [
          "pattern"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Reads a file from the local filesystem. You can access any file directly by using this tool.\nIf the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.\n\nUsage:\n- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters\n- Lines in the output are numbered starting at 1, using following format: LINE_NUMBER|LINE_CONTENT\n- You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful.\n- If you read a file that exists but has empty contents you will receive 'File is empty.'\n\nImage Support:\n- This tool can also read image files when called with the appropriate path.\n- Supported image formats: jpeg/jpg, png, gif, webp.\n\nPDF Support:\n- PDF files are converted into text content automatically (subject to the same character limits as other files).",
      "name": "Read",
      "parameters": {
        "properties": {
          "limit": {
            "description": "The number of lines to read. Only provide if the file is too large to read at once.",
            "type": "integer"
          },
          "offset": {
            "description": "The line number to start reading from. Positive values are 1-indexed from the start of the file. Negative values count backwards from the end (e.g. -1 is the last line). Only provide if the file is too large to read at once.",
            "type": "integer"
          },
          "path": {
            "description": "The absolute path of the file to read.",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Lists files and directories under a directory path.\n\nUse this tool when you need directory structure, especially top-level project layout or immediate children of a folder. Do not use Glob(\"*\") or recursive Glob patterns to list a directory; use Ls instead.\n\nYou may provide ignore globs for large or irrelevant directories such as .git, node_modules, dist, build, .cursor-local-assistant-v2/history, or logs.",
      "name": "Ls",
      "parameters": {
        "properties": {
          "ignore": {
            "description": "Optional ignore globs for directories or files that should be skipped while listing.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "path": {
            "description": "The absolute path of the directory to list.",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Read and display linter errors from the current workspace. You can provide paths to specific files or directories, or omit the argument to get diagnostics for all files.\n\n- If a file path is provided, returns diagnostics for that file only\n- If a directory path is provided, returns diagnostics for all files within that directory\n- If no path is provided, returns diagnostics for all files in the workspace\n- This tool can return linter errors that were already present before your edits, so avoid calling it with a very wide scope of files\n- NEVER call this tool on a file unless you've edited it or are about to edit it",
      "name": "ReadLints",
      "parameters": {
        "properties": {
          "paths": {
            "description": "Optional. An array of paths to files or directories to read linter errors for. You can use either relative paths in the workspace or absolute paths. If provided, returns diagnostics for the specified files/directories only. If not provided, returns diagnostics for all files in the workspace.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Executes a given command in a shell session with optional foreground timeout.\n\nIMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.\n\nBefore executing the command, please follow these steps:\n\n1. Check for Running Processes:\n   - Before starting dev servers or long-running processes that should not be duplicated, list the terminals folder to check if they are already running in existing terminals.\n   - You can use this information to determine which terminal, if any, matches the command you want to run, contains the output from the command you want to inspect, or has changed since you last read them.\n   - Since these are text files, you can read any terminal's contents simply by reading the file, search using Grep, etc.\n2. Directory Verification:\n   - If the command will create new directories or files, first run ls to verify the parent directory exists and is the correct location\n   - For example, before running \"mkdir foo/bar\", first run 'ls' to check that \"foo\" exists and is the intended parent directory\n3. Command Execution:\n   - Always quote file paths that contain spaces with double quotes (e.g., cd \"path with spaces/file.txt\")\n   - Examples of proper quoting:\n     - cd \"/Users/name/My Documents\" (correct)\n     - cd /Users/name/My Documents (incorrect - will fail)\n     - python \"/path/with spaces/script.py\" (correct)\n     - python /path/with spaces/script.py (incorrect - will fail)\n   - After ensuring proper quoting, execute the command.\n   - Capture the output of the command.\n\nUsage notes:\n\n- The command argument is required.\n- The shell starts in the workspace root and is stateful across sequential calls. Current working directory and environment variables persist between calls. Use the `working_directory` parameter to run commands in different directories. Example: to run `npm install` in the `frontend` folder, set `working_directory: \"frontend\"` rather than using `cd frontend && npm install`.\n- It is very helpful if you write a clear, concise description of what this command does in 5-10 words.\n- VERY IMPORTANT: You MUST avoid using search commands like `find` and `grep`.Instead use Grep, Glob to search.You MUST avoid read tools like `cat`, `head`, and `tail`, and use Read to read files.Avoid editing files with tools like `sed` and `awk`; use PatchEdit instead.\n- If you _still_ need to run `grep`, STOP. ALWAYS USE ripgrep at `rg` first, which all users have pre-installed.\n- When issuing multiple commands:\n  - If the commands are independent and can run in parallel, make multiple Shell tool calls in a single message. For example, if you need to run \"git status\" and \"git diff\", send a single message with two Shell tool calls in parallel.\n  - If the commands depend on each other and must run sequentially, use a single Shell call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`). For instance, if one operation must complete before another starts (like mkdir before cp,Write before Shell for git operations, or git add before git commit), run these operations sequentially instead.\n  - Use ';' only when you need to run commands sequentially but don't care if earlier commands fail\n  - DO NOT use newlines to separate commands (newlines are ok in quoted strings)\n\nDependencies:\n\nWhen adding new dependencies, prefer using the package manager (e.g. npm, pip) to add the latest version. Do not make up dependency versions.\n\n<managing-long-running-commands>\n- Commands that don't complete within `block_until_ms` (default 30s) are moved to background. The command keeps running and output streams to a terminal file. Set `block_until_ms: 0` to immediately background (use for dev servers, watchers, or any long-running process).\n- You do not need to use '&' at the end of commands.\n- Make sure to set `block_until_ms` to higher than the command's expected runtime. Add some buffer since block_until_ms includes shell startup time; increase buffer next time based on `elapsed_ms` if you chose too low. E.g. if you sleep for 40s, recommended `block_until_ms` is 45s.\n- Monitoring backgrounded commands:\n  - When command moves to background, check status immediately by reading the terminal file.\n  - Header has `pid` and `running_for_ms` (updated every 5000ms)\n  - When finished, footer with `exit_code` and `elapsed_ms` appears.\n  - Poll repeatedly to monitor by sleeping between checks. If the file gets large, read from the end of the file to capture the latest content.\n  - Pick your sleep intervals using best guess/judgment based on any knowledge you have about the command and its expected runtime, and any output from monitoring the command. When no new output, exponential backoff is a good strategy (e.g. sleep 2000ms, 4000ms, 8000ms, 16000ms...), using educated guess for min and max wait.\n  - If it's longer than expected and the command seems like it is hung, kill the process if safe to do so using the pid that appears in the header. If possible, try to fix the hang and proceed.\n  - Don't stop polling until: (a) `exit_code` footer appears (terminating command), (b) the command reaches a healthy steady state (only for non-terminating command, e.g. dev server/watcher), or (c) command is hung - follow guidance above.\n</managing-long-running-commands>\n\n<committing-changes-with-git>\nOnly create commits when requested by the user. If unclear, ask first. When the user asks you to create a new git commit, follow these steps carefully:\n\nGit Safety Protocol:\n\n- NEVER update the git config\n- NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them\n- NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it\n- NEVER run force push to main/master, warn the user if they request it\n- Avoid git commit --amend. ONLY use --amend when ALL conditions are met:\n  1. User explicitly requested amend, OR commit SUCCEEDED but pre-commit hook auto-modified files that need including\n  2. HEAD commit was created by you in this conversation (verify: git log -1 --format='%an %ae')\n  3. Commit has NOT been pushed to remote (verify: git status shows \"Your branch is ahead\")\n- CRITICAL: If commit FAILED or was REJECTED by hook, NEVER amend - fix the issue and create a NEW commit\n- CRITICAL: If you already pushed to remote, NEVER amend unless user explicitly requests it (requires force push)\n- NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.\n\n1. You can call multiple tools in a single response. When multiple independent pieces of information are requested, batch your tool calls together for optimal performance. ALWAYS run the following shell commands in parallel, each using the Shell tool:\n   - Run a git status command to see all untracked files.\n   - Run a git diff command to see both staged and unstaged changes that will be committed.\n   - Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.\n2. Analyze all staged changes (both previously staged and newly added) and draft a commit message:\n   - Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.). Ensure the message accurately reflects the changes and their purpose (i.e. \"add\" means a wholly new feature, \"update\" means an enhancement to an existing feature, \"fix\" means a bug fix, etc.).\n   - Do not commit files that likely contain secrets (.env, credentials.json, etc). Warn the user if they specifically request to commit those files\n   - Draft a concise (1-2 sentences) commit message that focuses on the \"why\" rather than the \"what\"\n   - Ensure it accurately reflects the changes and their purpose\n3. Run the following commands sequentially:\n   - Add relevant untracked files to the staging area.\n   - Commit the changes with the message.\n   - Run git status after the commit completes to verify success.\n4. If the commit fails due to pre-commit hook, fix the issue and create a NEW commit (see amend rules above)\n\nImportant notes:\n\n- NEVER update the git config\n- NEVER run additional commands to read or explore code, besides git shell commands\n- DO NOT push to the remote repository unless the user explicitly asks you to do so\n- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.\n- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit\n- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:\n\n<example>git commit -m \"$(cat <<'EOF'\nCommit message here.\n\nEOF\n)\"</example>\n</committing-changes-with-git>\n\n<creating-pull-requests>\nUse the gh command via the Shell tool for ALL GitHub-related tasks including working with issues, pull requests, checks, and releases. If given a Github URL use the gh command to get the information needed.\n\nIMPORTANT: When the user asks you to create a pull request, follow these steps carefully:\n\n1. You have the capability to call multiple tools in a single response. When multiple independent pieces of information are requested, batch your tool calls together for optimal performance. ALWAYS run the following shell commands in parallel using the Shell tool, in order to understand the current state of the branch since it diverged from the main branch:\n   - Run a git status command to see all untracked files\n   - Run a git diff command to see both staged and unstaged changes that will be committed\n   - Check if the current branch tracks a remote branch and is up to date with the remote, so you know if you need to push to the remote\n   - Run a git log command and `git diff [base-branch]...HEAD` to understand the full commit history for the current branch (from the time it diverged from the base branch)\n2. Analyze all changes that will be included in the pull request, making sure to look at all relevant commits (NOT just the latest commit, but ALL commits that will be included in the pull request!!!), and draft a pull request summary\n3. Run the following commands sequentially:\n   - Create new branch if needed\n   - Push to remote with -u flag if needed\n   - Create PR using gh pr create with the format below. Use a HEREDOC to pass the body to ensure correct formatting.\n\n<example># First, push the branch (with required_permissions: [\"all\"])\ngit push -u origin HEAD\n\n# Then create the PR (with required_permissions: [\"all\"])\ngh pr create --title \"the pr title\" --body \"$(cat <<'EOF'\n## Summary\n<1-3 bullet points>\n\n## Test plan\n[Checklist of TODOs for testing the pull request...]\n\nEOF\n)\"</example>\n\nImportant:\n\n- NEVER update the git config\n- DO NOT use the TodoWrite or Task tools\n- Return the PR URL when you're done, so the user can see it\n</creating-pull-requests>\n\n<other-common-operations>\n- View comments on a Github PR: gh api repos/foo/bar/pulls/123/comments\n</other-common-operations>",
      "name": "Shell",
      "parameters": {
        "properties": {
          "block_until_ms": {
            "description": "How long to block and wait for the command to complete before moving it to background (in milliseconds). Defaults to 30000ms (30 seconds). Set to 0 to immediately run the command in the background. The timer includes the shell startup time.",
            "type": "number"
          },
          "command": {
            "description": "The command to execute",
            "type": "string"
          },
          "description": {
            "description": "Clear, concise description of what this command does in 5-10 words",
            "type": "string"
          },
          "working_directory": {
            "description": "The absolute path to the working directory to execute the command in (defaults to current directory)",
            "type": "string"
          },
          "notify_on_output": {
            "description": "Optional watcher for backgrounded command output. You will be notified at the end of your turn whenever output matches the regex pattern. Use stable sentinel lines and simple anchored regexes; do not match all output. Completion notifications are separate and do not require this field.",
            "properties": {
              "pattern": {
                "description": "Regex pattern to match against command output.",
                "type": "string"
              },
              "reason": {
                "description": "Five or fewer words describing what you are watching for. The UI prefixes it as Monitored `reason`.",
                "type": "string"
              },
              "debounce_ms": {
                "description": "Minimum milliseconds between notifications. Values below 5000ms are treated as 5000ms.",
                "type": "number"
              },
              "notification_limit": {
                "description": "Optional maximum number of output-match notifications for this command.",
                "type": "number"
              }
            },
            "required": [
              "pattern",
              "reason"
            ],
            "type": "object"
          }
        },
        "required": [
          "command"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Writes literal characters to an existing background shell session. Use only when a previous Shell result returned a shell_id and the process is waiting for stdin. Include any needed newline in chars.",
      "name": "WriteShellStdin",
      "parameters": {
        "properties": {
          "chars": {
            "description": "Literal characters to write to stdin. Include \\n when submitting a line.",
            "type": "string"
          },
          "shell_id": {
            "description": "The shell_id returned by a backgrounded Shell command.",
            "type": "number"
          }
        },
        "required": [
          "shell_id",
          "chars"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Requests that a running Shell tool call move to the background so the current agent turn can continue. Pass the original Shell tool_call_id, not the shell_id.",
      "name": "ForceBackgroundShell",
      "parameters": {
        "properties": {
          "tool_call_id": {
            "description": "The original Shell tool call id to move to background.",
            "type": "string"
          }
        },
        "required": [
          "tool_call_id"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "type": "function",
    "function": {
      "name": "PatchEdit",
      "description": "Edit an existing text file by replacing exact text copied from the latest Read. Use this as the default tool for modifying existing source, markdown, JSON, YAML, config files, and short inline spans.\n\nUsage:\n- Read the relevant file first, then copy the exact current text into old_string.\n- path must be an absolute file path. Do not pass a relative path, workspace-relative path, or bare filename; this tool will not resolve or rewrite it.\n- old_string must exactly match the current file content; line endings are not normalized or treated equivalently during matching.\n- By default replace_all is false and old_string must match exactly one occurrence. If it matches multiple occurrences, the tool reports an error.\n- Set replace_all to true only when every exact occurrence should be replaced.\n- new_string may be empty to delete old_string.\n- Write is still only for creating new files or intentionally rewriting a whole file.",
      "parameters": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "Absolute path to the file to modify. Required forms include /abs/path on macOS/Linux, C:\\abs\\path or C:/abs/path on Windows, or //server/share/path for UNC paths. Relative paths are invalid."
          },
          "old_string": {
            "type": "string",
            "description": "Exact text to replace. Must match the current file content exactly and must not be empty."
          },
          "new_string": {
            "type": "string",
            "description": "Replacement text. May be empty to delete old_string."
          },
          "replace_all": {
            "type": "boolean",
            "description": "Whether to replace all exact occurrences. Defaults to false."
          }
        },
        "required": [
          "path",
          "old_string",
          "new_string"
        ]
      }
    }
  },
  {
    "function": {
      "description": "Launch a new agent to handle complex, multi-step tasks autonomously.\n\nThe Task tool launches specialized subagents (subprocesses) that autonomously handle complex tasks. Each subagent_type has specific capabilities and tools available to it.\n\nWhen using the Task tool, you must specify a subagent_type parameter to select which agent type to use.\n\nVERY IMPORTANT: When broadly exploring the codebase to gather context for a large task, it is recommended that you use the Task tool with subagent_type=\"explore\" instead of running search commands directly.\n\nIf the query is a narrow or specific question, you should NOT use the Task and instead address the query directly using the other tools available to you.\n\nExamples:\n- user: \"Where is the ClientError class defined?\" assistant: [Uses Grep directly - this is a needle query for a specific class]\n- user: \"Run this query using my database API\" assistant: [Calls the MCP directly - this is not a broad exploration task]\n- user: \"What is the codebase structure?\" assistant: [Uses the Task tool with subagent_type=\"explore\"]\n\nIf it is possible to explore different areas of the codebase in parallel, you should launch multiple agents concurrently.\n\nWhen NOT to use the Task tool:\n- Simple, single or few-step tasks that can be performed by a single agent (using parallel or sequential tool calls) -- just call the tools directly instead.\n- For example:\n  - If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly\n  - If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly\n  - If you are searching for a specific class definition like \"class Foo\", use the Glob tool instead, to find the match more quickly\n\nUsage notes:\n- Always include a short description (3-5 words) summarizing what the agent will do\n- Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses. IMPORTANT: DO NOT launch more than 4 agents concurrently.\n- When the agent is done, it will return a single message back to you. Specify exactly what information the agent should return back in its final response to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.\n- Agents can be resumed using the `resume` parameter by passing the agent ID from a previous invocation. This sends a follow-up message when the agent's turn is complete, preserving existing context. When NOT resuming, each invocation starts fresh and you should provide a detailed task description with all necessary context.\n- When using the Task tool, the subagent invocation does not have access to the user's message or prior assistant steps. Therefore, you should provide a highly detailed task description with all necessary context for the agent to perform its task autonomously.\n- The subagent's outputs should generally be trusted\n- Clearly tell the subagent which tasks you want it to perform, since it is not aware of the user's intent or your prior assistant steps (tool calls, thinking, or messages).\n- If the subagent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.\n- If the user specifies that they want you to run subagents \"in parallel\", you MUST send a single message with multiple Task tool use content blocks. For example, if you need to launch both a code-reviewer subagent and a test-runner subagent in parallel, send a single message with both tool calls.\n- Avoid delegating the full query to the Task tool and returning the result. In these cases, you should address the query using the other tools available to you.\n\nAvailable subagent_types and a quick description of what they do:\n- generalPurpose: General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. Use when searching for a keyword or file and not confident you'll find the match quickly.\n- explore: Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. \"src/components/**/*.tsx\"), search code for keywords (eg. \"API endpoints\"), or answer questions about the codebase (eg. \"how do API endpoints work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"very thorough\" for comprehensive analysis across multiple locations and naming conventions.\n- shell: Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.\n- browser-use: Perform browser-based testing and web automation. This subagent can navigate web pages, interact with elements, fill forms, and take screenshots. Use this for testing web applications, verifying UI changes, or any browser-based tasks. Use this browser subagent when you need to either: (1) parallelize browser tasks alongside other work, or (2) execute a longer sequence of browser actions that benefit from dedicated context. For simple, single browser actions, you may use the browser tools directly. This subagent_type is stateful; if a browserUse subagent already exists, the previously created subagent will be resumed if you reuse the Task tool with subagent_type set to browserUse. (Auto-resumes most recent agent of this type; `resume` arg is ignored)\n\nAvailable models:\n- fast (cost: 1/10, intelligence: 5/10): Extremely fast, moderately intelligent model that is effective for tightly scoped changes. Not well-suited for long-horizon tasks or deep investigations.\n\nWhen speaking to the USER about which model you selected for a Task/subagent, do NOT reveal these internal model alias names. Instead, use natural language such as \"a faster model\", \"a more capable model\", or \"the default model\".\n\nWhen choosing a model, prefer `fast` for quick, straightforward tasks to minimize cost and latency. Only choose a named alternative model when there is a specific reason — for example, the task requires deep multi-step reasoning, very high code quality, multimodal understanding, or the user explicitly requests a more capable model.",
      "name": "Task",
      "parameters": {
        "properties": {
          "attachments": {
            "description": "Optional array of file paths to videos to pass to video-review subagents. Files are read and attached to the subagent's context. Supports video formats (mp4, webm) for Gemini models.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": {
            "description": "A short (3-5 word) description of the task",
            "type": "string"
          },
          "model": {
            "description": "Optional model to use for this agent. If not specified, inherits from parent. Prefer fast for quick, straightforward tasks to minimize cost and latency. Only select a different model when the task specifically benefits from it (e.g., deep reasoning, high-quality code review, multimodal input)",
            "enum": [
              "fast"
            ],
            "type": "string"
          },
          "prompt": {
            "description": "The task for the agent to perform",
            "type": "string"
          },
          "readonly": {
            "description": "If true, the subagent will run in readonly mode (\"Ask mode\") with restricted write operations and no MCP access.",
            "type": "boolean"
          },
          "resume": {
            "description": "Optional agent ID to resume from. If provided, sends a follow-up message to the agent when its turn is complete.",
            "type": "string"
          },
          "subagent_type": {
            "description": "Subagent type to use for this task. Must be one of: generalPurpose, explore, shell, browser-use.",
            "enum": [
              "generalPurpose",
              "explore",
              "shell",
              "browser-use"
            ],
            "type": "string"
          }
        },
        "required": [
          "description",
          "prompt"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Use this tool to create and manage a structured task list for your current coding session. This helps track progress, organize complex tasks, and demonstrate thoroughness.\n\nNote: Other than when first creating todos, don't tell the user you're updating todos, just do it.\n\n### When to Use This Tool\n\nHard rule: Never create or maintain a todo list with only 1-2 tasks. If you cannot name at least 3 real, necessary, non-filler tasks, do not call TodoWrite. Do not split or invent placeholder tasks just to reach 3 items.\n\nUse proactively for:\n1. Complex multi-step tasks (3+ distinct steps)\n2. Non-trivial tasks requiring careful planning\n3. User explicitly requests a todo list and the list would contain at least 3 real tasks\n4. User provides multiple tasks (numbered/comma-separated)\n5. After receiving new instructions - capture requirements as todos (use merge=true to add or update them unless you are providing a complete replacement list)\n6. After completing tasks - mark complete with merge=true and add follow-ups\n7. When starting new tasks - mark as in_progress (ideally only one at a time)\n\n### When NOT to Use\n\nSkip for:\n1. Single, straightforward tasks\n2. Trivial tasks with no organizational benefit\n3. Tasks completable in < 3 real steps, or any task list that would contain only 1-2 items\n4. Purely conversational/informational requests\n5. Don't add a task to test the change unless asked, or you'll overfocus on testing\n\n### Examples\n\n<example>\n  User: Add dark mode toggle to settings\n  Assistant:\n    - *Creates todo list:*\n      1. Add state management [in_progress]\n      2. Implement styles\n      3. Create toggle component\n      4. Update components\n    - [Immediately begins working on todo 1 in the same tool call batch]\n<reasoning>\n  Multi-step feature with dependencies.\n</reasoning>\n</example>\n\n<example>\n  User: Rename getCwd to getCurrentWorkingDirectory across my project\n  Assistant: *Searches codebase, finds 15 instances across 8 files*\n  *Creates todo list with specific items for each file that needs updating*\n\n<reasoning>\n  Complex refactoring requiring systematic tracking across multiple files.\n</reasoning>\n</example>\n\n<example>\n  User: Implement user registration, product catalog, shopping cart, checkout flow.\n  Assistant: *Creates todo list breaking down each feature into specific tasks*\n\n<reasoning>\n  Multiple complex features provided as list requiring organized task management.\n</reasoning>\n</example>\n\n<example>\n  User: Optimize my React app - it's rendering slowly.\n  Assistant: *Analyzes codebase, identifies issues*\n  *Creates todo list: 1) Memoization, 2) Virtualization, 3) Image optimization, 4) Fix state loops, 5) Code splitting*\n\n<reasoning>\n  Performance optimization requires multiple steps across different components.\n</reasoning>\n</example>\n\n### Examples of When NOT to Use the Todo List\n\n<example>\n  User: What does git status do?\n  Assistant: Shows current state of working directory and staging area...\n\n<reasoning>\n  Informational request with no coding task to complete.\n</reasoning>\n</example>\n\n<example>\n  User: Add comment to calculateTotal function.\n  Assistant: *Uses edit tool to add comment*\n\n<reasoning>\n  Single straightforward task in one location.\n</reasoning>\n</example>\n\n<example>\n  User: Run npm install for me.\n  Assistant: *Executes npm install* Command completed successfully...\n\n<reasoning>\n  Single command execution with immediate results.\n</reasoning>\n</example>\n\n### Task States and Management\n\n1. **Task States:**\n  - pending: Not yet started\n  - in_progress: Currently working on\n  - completed: Finished successfully\n  - cancelled: No longer needed\n\n2. **Task Management:**\n  - Update status in real-time\n  - Mark complete IMMEDIATELY after finishing\n  - Only ONE task in_progress at a time\n  - Complete current tasks before starting new ones\n  - Use merge=true for incremental updates. Use merge=false only for the first todo list or when intentionally replacing the entire list and including every existing todo id.\n\n3. **Task Breakdown:**\n  - Create specific, actionable items\n  - Break complex tasks into manageable steps\n  - Use clear, descriptive names\n  - Never create 1-2 item todo lists; keep the work in your head unless there are at least 3 meaningful tasks\n\n4. **Parallel Todo Writes:**\n  - Prefer creating the first todo as in_progress\n  - Start working on todos by using tool calls in the same tool call batch as the todo write\n  - Batch todo updates with other tool calls for better latency and lower costs for the user\n\nWhen in doubt, do not use this tool unless the work clearly needs at least 3 meaningful tasks. Concise execution is better than a decorative todo list.",
      "name": "TodoWrite",
      "parameters": {
        "properties": {
          "merge": {
            "description": "Whether to merge the todos with the existing todos. If true, the todos will be merged into the existing todos based on the id field. Use true for normal incremental updates, marking items complete, adding follow-ups, or changing the current in-progress item. If false, the new todos replace the entire list and must include every existing todo id once a list already exists.",
            "type": "boolean"
          },
          "todos": {
            "description": "Array of TODO items to update or create",
            "items": {
              "properties": {
                "content": {
                  "description": "The description/content of the todo item. For merge=true updates, omit content when it is unchanged. New todos and merge=false replacements must include content.",
                  "type": "string"
                },
                "id": {
                  "description": "Unique identifier for the TODO item",
                  "type": "string"
                },
                "status": {
                  "description": "The current status of the TODO item. For merge=true updates, omit status when it is unchanged.",
                  "enum": [
                    "pending",
                    "in_progress",
                    "completed",
                    "cancelled"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            },
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "todos",
          "merge"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Fetch content from a specified URL and return its contents in a readable markdown format. Use this tool when you need to retrieve and analyze webpage content.\n\n- The URL must be a fully-formed, valid URL.\n- This tool is read-only and will not work for requests intended to have side effects.\n- This fetch tries to return live public web results.\n- Authentication is not supported, and an error will be returned if the URL requires authentication.\n- If the URL is returning a non-200 status code, e.g. 404, the tool will not return the content and will instead return an error message.\n- This fetch uses a public-web-only backend fetch policy. Localhost, private IPs, and link-local addresses will not work.\n- This tool does not support fetching binary content, e.g. media or PDFs.\n- For static assets and non-webpage URLs, use the `Shell` tool instead.\n",
      "name": "WebFetch",
      "parameters": {
        "properties": {
          "url": {
            "description": "The URL to fetch. The content will be converted to a readable markdown format.",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Search the web for real-time information about any topic. Returns summarized information from search results and relevant URLs.\n\nUse this tool when you need up-to-date information that might not be available or correct in your training data, or when you need to verify current facts.\nThis includes queries about:\n- Libraries, frameworks, and tools whose APIs, best practices, or usage instructions are frequently updated. (\"How do I run Postgres in a container?\")\n- Current events or technology news. (\"Which AI model is best for coding?\")\n- Informational queries similar to what you might Google (\"kubernetes operator for mysql\")\n\nIMPORTANT - Use the correct year in search queries:\n- Today's date is 2026-03-14. You MUST use this year when searching for recent information, documentation, or current events.\n- Example: If today is 2026-07-15 and the user asks for \"latest React docs\", search for \"React documentation 2026\", NOT \"React documentation 2025\"",
      "name": "WebSearch",
      "parameters": {
        "properties": {
          "explanation": {
            "description": "One sentence explanation as to why this tool is being used, and how it contributes to the goal.",
            "type": "string"
          },
          "search_term": {
            "description": "The search term to look up on the web. Be specific and include relevant keywords for better results. For technical queries, include version numbers or dates if relevant.",
            "type": "string"
          }
        },
        "required": [
          "search_term"
        ],
        "type": "object"
      }
    },
    "type": "function"
  },
  {
    "function": {
      "description": "Writes a file to the local filesystem.\n\nUsage:\n- path must be an absolute file path. Do not pass a relative path, workspace-relative path, or bare filename; this tool will not resolve or rewrite it.\n- This tool will overwrite the existing file if there is one at the provided path.\n- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.\n- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.",
      "name": "Write",
      "parameters": {
        "properties": {
          "contents": {
            "description": "The contents to write to the file",
            "type": "string"
          },
          "path": {
            "description": "Absolute path to the file to modify. Required forms include /abs/path on macOS/Linux, C:\\abs\\path or C:/abs/path on Windows, or //server/share/path for UNC paths. Relative paths are invalid.",
            "type": "string"
          }
        },
        "required": [
          "path",
          "contents"
        ],
        "type": "object"
      }
    },
    "type": "function"
  }
]
