@mcptrail/use-model-tool
v0.1.0
Published
React hooks that register/unregister WebMCP tools with component lifecycle — the agent only sees tools for what's currently on screen.
Maintainers
Readme
@mcptrail/use-model-tool
React hooks that bind WebMCP tool registration to component lifecycle. A tool is registered when its component mounts and unregistered when it unmounts — so the AI agent only ever sees the tools for what's currently on screen.
No context provider, no global tool registry to keep in sync with your UI. Register a tool where it makes sense, and React's lifecycle keeps the agent's view honest.
Install
npm install @mcptrail/use-model-toolreact (^18.2.0 || ^19.0.0) is a peer dependency.
Usage
import { useModelTool } from "@mcptrail/use-model-tool";
function CheckoutPanel({ cartId }: { cartId: string }) {
useModelTool({
name: "apply_coupon",
description: "Apply a discount coupon to the current cart",
inputSchema: {
type: "object",
properties: { code: { type: "string" } },
required: ["code"],
},
execute: async (args) => {
const { code } = args as { code: string };
return applyCoupon(cartId, code);
},
});
return <div>/* ...checkout UI... */</div>;
}When CheckoutPanel is mounted, the agent can call apply_coupon. Navigate away and the tool is gone — the agent can no longer call it.
Register several tools from one component with useModelTools:
import { useModelTools } from "@mcptrail/use-model-tool";
function TableTools({ rows }: { rows: Row[] }) {
useModelTools([
{ name: "sort_table", description: "Sort the visible table", execute: sort },
{ name: "filter_table", description: "Filter the visible table", execute: filter },
]);
return <Table rows={rows} />;
}API
useModelTool(tool, deps?)
Registers a single tool on mount and unregisters it on unmount. Pass deps to re-register when they change (defaults to [] — register once).
useModelTools(tools, deps?)
Registers every tool on mount and cleans them all up on unmount. Pass deps to re-register the set when they change (defaults to []).
registerModelTool(tool, target?): () => void
The pure, framework-free core the hooks are built on. Resolves the ambient modelContext (prefers target, then navigator, then document), calls registerTool(tool), and returns a cleanup fn:
- if
registerToolreturned a disposer, cleanup calls its.unregister(); - else if the
modelContextexposesunregisterTool(name), cleanup calls that; - else cleanup is a no-op.
If no modelContext is available, registerModelTool is a no-op and returns a no-op cleanup — safe to call during SSR or in non-WebMCP browsers.
WebMcpTool
interface WebMcpTool {
name: string;
description?: string;
inputSchema?: JSONSchema;
annotations?: { readOnlyHint?: boolean; [k: string]: unknown };
execute: (args: unknown) => unknown;
}Development
npm install
npm run typecheck
npm test # Vitest + jsdom
npm run build # tsup → dist (ESM + CJS + d.ts)License
MIT © Zied Guetari
