Skip to content
WebMCP Agents
Esc
↑↓navigate↵open⌘Jpreview
On this page

Install in a Vite app

Six steps, from an empty folder to a tool the agent cursor runs, in a Vite single-page app with React.

Six steps, from an empty folder to a tool the agent cursor runs. This is how the repository’s Vite apps (Playground, Field Store, Skyline) are set up.

Create a project

Skip this if you already have a Vite app with React. In the prompts, choose React and TypeScript.

npm create vite@latest
pnpm create vite@latest
yarn create vite@latest
bun create vite@latest
nub create vite@latest
aube create vite@latest

Install the packages

The agent cursor and the React bindings. Nothing else: the provider loads a WebMCP polyfill where the browser has none, and the devtools panel in development.

npm install @webmcp-agents/core @webmcp-agents/react
pnpm add @webmcp-agents/core @webmcp-agents/react
yarn add @webmcp-agents/core @webmcp-agents/react
bun add @webmcp-agents/core @webmcp-agents/react
nub add @webmcp-agents/core @webmcp-agents/react
aube add @webmcp-agents/core @webmcp-agents/react

Add the styles

Import the cursor’s stylesheet in your entry file, next to your own.

import "./index.css";
import "@webmcp-agents/core/cursor.css"; 

Add the provider

<WebAgentsProvider> installs the cursor and registers your tools. In a browser without WebMCP it loads a polyfill first, by itself; your app renders meanwhile. In development it also installs the devtools panel. The highlighted lines are the ones you add.

import { WebAgentsProvider } from "@webmcp-agents/react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import "./index.css";
import "@webmcp-agents/core/cursor.css";
import { App } from "./App";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <WebAgentsProvider>
      <App />
    </WebAgentsProvider>
  </StrictMode>,
);

Add your first tool

The action is one function with two callers: a person clicks the button, an agent calls the tool. useWebTool registers the tool while the component is on the page. A plain <button> is enough: the cursor finds it by its role and name.

import { useWebTool } from "@webmcp-agents/react";
import { useState } from "react";

export function ClearCart() {
  const [items, setItems] = useState(["Ocean Tee", "Canvas Tote"]);

  const clear = () => {
    setItems([]);
    return "The cart is empty.";
  };

  // An agent calls this.
  useWebTool({
    id: "clear_cart",
    title: "Clear cart",
    description:
      "Empty the cart. Use when the user asks to start over. " +
      "The user confirms on the page.",
    destructive: true,
    requireConfirmation: true,
    execute: clear,
  });

  // A person clicks this.
  return (
    <div>
      <p>
        {items.length > 0 ? items.join(", ") : "The cart is empty."}
      </p>

      <button type="button" onClick={clear}>
        Clear cart
      </button>
    </div>
  );
}

Render it in your app.

import { ClearCart } from "./components/clear-cart";

export function App() {
  return (
    <main>
      <ClearCart />
    </main>
  );
}

Run it

Start the app and open it.

npm run dev
pnpm run dev
yarn run dev
bun run dev
nub run dev
aube run dev

Open the devtools panel (bottom right, or Alt+Shift+A), expand clear_cart and press Run. The cursor flies to Clear cart and waits there. Click the button yourself: the cart empties, and the tool answers “The cart is empty.”

Next

Define a tool

What you just wrote, line by line: execute, the title the cursor looks for, and target for when the name is not enough.

Was this page helpful?