mcpField
C
create-client-tool

create-client-tool

github.com/cognitedataDevelopment340 installs
Repository

About create-client-tool

A skill for adding a typed `AtlasTool` to an app using `useAtlasChat`. It guides codebase inspection, schema definition with TypeBox, tool registration, and optional rendering of structured tool results.

Key features

  1. 01Inspects existing tool patterns
  2. 02Defines schemas with TypeBox
  3. 03Registers tools in `useAtlasChat`
  4. 04Supports structured result rendering

Use cases

  1. 01Adding browser-side agent actions
  2. 02Exposing local state queries to an agent
  3. 03Rendering structured tool-call details

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/cognitedata/dune-skills --skill create-client-tool

After installing, type/create-client-toolin Claude Code to confirm it loaded.

Details

From the project README

Create a Client Tool

Scaffold a new AtlasTool named $ARGUMENTS and wire it into the app.

Background

Client tools let the Atlas Agent invoke logic that runs in the browser — rendering charts, querying local state, showing UI panels, triggering navigation, etc. The agent decides when to call the tool; the app executes it and returns a result.

The flow is:

  1. Agent responds with a clientTool action
  2. The library validates the arguments against the TypeBox schema
  3. execute() runs in the browser and returns { output, details }
  4. output (string) is sent back to the agent as the tool result
  5. details (any shape) is available on message.toolCalls for the UI to render

Step 1 — Understand the codebase

Before writing anything, read:

  • The file where useAtlasChat is called (likely src/App.tsx) to find where tools is passed
  • Any existing tool definitions to match the file/naming conventions

Step 2 — Define the tool

Create the tool as a typed constant. Use Type from @cognite/dune-industrial-components/atlas-agent to define the parameters schema — this gives both compile-time types and runtime validation.

import { Type } from "@cognite/dune-industrial-components/atlas-agent";
import type { AtlasTool } from "@cognite/dune-industrial-components/atlas-agent";

export const myTool: AtlasTool = {
  name: "my_tool",            // snake_case — this is what the agent uses to invoke it
  description:
    "One sentence describing what this tool does and when the agent should call it.",
  parameters: Type.Object({
    exampleParam: Type.String({ description: "What this param is for" }),
    optionalNum: Type.Optional(Type.Number({ description: "..." })),
  }),
  execute: async (args) => {
    // args is fully typed from the schema above
    // Do the work here — call APIs, update state, render UI, etc.
    return {
      output: "Plain text summary sent back to the agent",
      details: {
        // Any structured data you want available in the UI via message.toolCalls
      },
    };
  },
};
TypeBox quick reference
SchemaUsage
Type.String()string
Type.Number()number
Type.Boolean()boolean
Type.Literal("foo")exact value
Type.Union([Type.Literal("a"), Type.Literal("b")])enum
Type.Array(Type.String())string[]
Type.Object({ ... })object
Type.Optional(...)mark any field optional

Always add a description to each field — the agent uses these to understand what to pass.


Step 3 — Wire into useAtlasChat

Find the useAtlasChat call and add the tool to the tools array:

const { messages, send, ... } = useAtlasChat({
  client: isLoading ? null : sdk,
  agentExternalId: AGENT_EXTERNAL_ID,
  tools: [myTool],   // add here
});

Step 4 — Render tool results (if needed)

If the tool returns structured details, render them in the message list. message.toolCalls is a ToolCall[] — one entry per tool call (client-side and server-side) in call order.

{msg.toolCalls?.map((tc, i) => (
  // tc.name    — tool name
  // tc.output  — the string sent back to the agent
  // tc.details — your structured data (cast to your known shape)
  <MyToolOutput key={i} data={tc.details as MyToolDetails} />
))}

Done

The agent can now invoke $ARGUMENTS. Describe what it does clearly in the description field — the agent relies on that string to decide when and how to call the tool.

Comments

Markdown supported