Skip to content
Merged

skill #220

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions .claude/commands/mcp-tool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# Developing monday.com API Tools (Agent Toolkit)

Guide for developing monday.com platform API tools in the agent-toolkit package. Use when creating, modifying, or debugging tools in packages/agent-toolkit/src/core/tools/platform-api-tools/, working with GraphQL queries, or adding new MCP tools to the toolkit.

## Package Location

`packages/agent-toolkit` — published as `@mondaydotcomorg/agent-toolkit`.

## Architecture Overview

All platform API tools live under `src/core/tools/platform-api-tools/`. Each tool extends `BaseMondayApiTool<InputSchema, Output>` from `base-monday-api-tool.ts`, which itself implements the `Tool` interface from `src/core/tool.ts`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type parameter name InputSchema here doesn't match the actual class definition, which uses Input extends ZodRawShape | undefined. Minor, but since this is a reference doc it'd be cleaner to match the real signature.


### Tool interface

```typescript
// From src/core/tool.ts
interface Tool<Input, Output> {
name: string; // snake_case identifier (e.g. "create_update")
type: ToolType; // READ, WRITE, or ALL_API
annotations: ToolAnnotations; // MCP annotations
enabledByDefault?: boolean;
getDescription(): string;
getInputSchema(): Input;
}
```

### BaseMondayApiTool

```typescript
abstract class BaseMondayApiTool<Input, Output> {
constructor(mondayApi: ApiClient, apiToken?: string, context?: MondayApiToolContext);
abstract name: string;
abstract type: ToolType;
abstract annotations: ToolAnnotations;
abstract getDescription(): string;
abstract getInputSchema(): Input;
protected abstract executeInternal(input): Promise<ToolOutputType<Output>>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real executeInternal signature has input? (optional), not input. Matches the base class: protected abstract executeInternal(input?: ToolInputType<Input>).

}
```

The public `execute()` method wraps `executeInternal()` with tracking. Always implement `executeInternal()`, never override `execute()`.

## Creating a New Tool

### 1. File structure

Simple tools can be a single file. Tools with GraphQL operations, tests, or helpers should use a folder:

```
tool-name/
├── tool-name.ts # Tool class
├── tool-name.graphql.ts # GraphQL query/mutation
├── tool-name.test.ts # Tests
└── tool-name.utils.ts # Helpers
```

### 2. Define GraphQL operations

Create a `.graphql.ts` file using `gql` from `graphql-request`:

```typescript
import { gql } from 'graphql-request';

export const myOperation = gql`
mutation myMutation($id: ID!, $value: String!) {
my_mutation(id: $id, value: $value) {
id
}
}
`;
```

### 3. Run codegen (CRITICAL)

**After any change to `.graphql.ts` files, you MUST run codegen** to regenerate TypeScript types:

```bash
cd packages/agent-toolkit

# Fetch latest schema + run codegen (recommended)
npm run fetch:generate

# Or run codegen only (if schema hasn't changed)
npm run codegen
```

This generates typed operations in `src/monday-graphql/generated/graphql/` (default) and `src/monday-graphql/generated/graphql.dev/` (dev).

- `codegen.yml` controls which files are picked up — default project uses `src/**/*.graphql.ts` excluding `*.graphql.dev.ts`.
- The dev project uses only `src/**/*.graphql.dev.ts`.
- Schema is fetched from monday.com API based on the `API_VERSION` in `src/utils/version.utils.ts`.

### 4. Define the Zod input schema

Use Zod to define inputs. Each field needs a `.describe()` for MCP tool documentation:

```typescript
import { z } from 'zod';

export const myToolSchema = {
itemId: z.number().describe('The id of the item'),
value: z.string().describe('The value to set'),
};
```

### 5. Implement the tool class

```typescript
import { ToolType, ToolInputType, ToolOutputType } from '../../../tool';
import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool';
import { MyMutation, MyMutationVariables } from '../../../../monday-graphql/generated/graphql/graphql';
import { myOperation } from './my-tool.graphql';

export const myToolSchema = { /* ... */ };

export class MyTool extends BaseMondayApiTool<typeof myToolSchema> {
name = 'my_tool';
type = ToolType.WRITE; // or READ, ALL_API
annotations = createMondayApiAnnotations({
title: 'My Tool',
readOnlyHint: false,
destructiveHint: false,
idempotentHint: false,
});

getDescription(): string {
return 'Description shown to LLMs when selecting tools.';
}

getInputSchema(): typeof myToolSchema {
return myToolSchema;
}

protected async executeInternal(
input: ToolInputType<typeof myToolSchema>
): Promise<ToolOutputType<never>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ToolOutputType<never> works fine since never is the default for the Output type parameter, but it reads as a bit cryptic to someone unfamiliar with the type. Worth adding a short comment like // 'never' = no typed metadata or just using ToolOutputType<Record<string, never>>.

const variables: MyMutationVariables = {
itemId: input.itemId.toString(),
value: input.value,
};

const res = await this.mondayApi.request<MyMutation>(myOperation, variables);

return {
content: `Operation succeeded: ${JSON.stringify(res)}`,
};
}
}
```

### 6. Register the tool

In `src/core/tools/platform-api-tools/index.ts`:

1. Import the tool class.
2. Add it to the `allGraphqlApiTools` array.
3. Add a re-export (`export * from './my-tool'`).

### 7. ToolType and annotations

| ToolType | Use case |
|----------|----------|
| `READ` | Fetches data without side effects |
| `WRITE` | Creates, updates, or deletes data |
| `ALL_API` | Dynamic tools that accept raw GraphQL |

Annotations use `createMondayApiAnnotations()` which sets `openWorldHint: true` by default. Key fields:

- `title` — human-readable name
- `readOnlyHint` — `true` for READ tools
- `destructiveHint` — `true` if the operation deletes data
- `idempotentHint` — `true` if repeated calls produce the same result

## GraphQL Codegen Pipeline

| Command | What it does |
|---------|-------------|
| `npm run fetch:schema` | Downloads `.graphql` schemas from monday.com API |
| `npm run codegen` | Runs `graphql-codegen` to generate TS types from `.graphql.ts` files |
| `npm run fetch:generate` | Both of the above in sequence |

Config files: `codegen.yml`, `graphql.config.yml`, `fetch-schema.sh`, `codegen.sh`.

The API version used for schema fetching is defined in `src/utils/version.utils.ts`.

## Updating Existing Tools

When modifying an existing tool's behavior, review and update `getDescription()` to reflect the new capabilities. The description is what LLMs see when selecting tools — stale descriptions lead to incorrect tool usage. Also update `annotations` if the tool's read/write/destructive characteristics changed.

## Version Bumping

**The package version must be manually bumped** in `packages/agent-toolkit/package.json` before publishing. There is no automatic versioning — update the `"version"` field directly.

## Tool Discovery and Filtering

Tools are instantiated and filtered in `src/utils/tools/`:

- `initializing.utils.ts` — `toolFactory()` instantiates tools based on their base class.
- `tools-filtering.utils.ts` — `getFilteredToolInstances()` filters by `include`/`exclude` lists, `readOnlyMode`, and `enableDynamicApiTools`.

Both `src/mcp/toolkit.ts` and `src/openai/toolkit.ts` use this pipeline to expose tools to their respective runtimes.

## Testing

Tests use Jest (`jest -c`). Place test files next to their tool as `tool-name.test.ts`.

```bash
cd packages/agent-toolkit
npm test # Run all tests
npx jest path/to/file # Run a single test file
```

## Quick Checklist for New Tools

- [ ] Create `.graphql.ts` with GQL operation
- [ ] Run `npm run codegen` (or `fetch:generate`) to generate types
- [ ] Define Zod input schema with `.describe()` on every field
- [ ] Implement tool class extending `BaseMondayApiTool`
- [ ] Set correct `ToolType` and `annotations`
- [ ] Register in `platform-api-tools/index.ts` (import, array, re-export)
- [ ] Add tests
- [ ] Bump version in `package.json`
- [ ] Build with `npm run build` to verify
6 changes: 6 additions & 0 deletions .cursor/skills/agent-toolkit-api-tools/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: agent-toolkit-api-tools
description: Guide for developing monday.com platform API tools in the agent-toolkit package. Use when creating, modifying, or debugging tools in packages/agent-toolkit/src/core/tools/platform-api-tools/, working with GraphQL queries, or adding new MCP tools to the toolkit.
---

@file .claude/commands/mcp-tool.md
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,7 @@ dist
.idea/
.qodo

#claude
.claude
claude.md

# macOS
.DS_Store
.DS_Store?
.omc/
90 changes: 90 additions & 0 deletions packages/agent-toolkit/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
npm run build # Build with Rollup (outputs CJS + ESM to dist/)
npm test # Run all tests with Jest
npx jest path/to/file # Run a single test file
npm run lint # ESLint with auto-fix
npm run prettier # Format with Prettier

# GraphQL codegen pipeline (fetches monday.com schema + generates TS types)
npm run fetch:generate # Fetch schema + codegen (both default and dev)
npm run fetch:generate default # Fetch + codegen for default schema only
npm run fetch:generate dev # Fetch + codegen for dev schema only
npm run fetch:schema # Fetch schema only
npm run codegen # Run codegen only (assumes schema files exist)
```

## Architecture

This is `@mondaydotcomorg/agent-toolkit` — an npm package providing monday.com API tools for AI agents. It exposes three subpath entry points:

- **`/core`** — Base tool interfaces and the tool registry
- **`/mcp`** — MCP (Model Context Protocol) server implementation
- **`/openai`** — OpenAI function-calling integration

### Tool System

All tools implement the `Tool<Input, Output>` interface (defined in `src/core/tool.ts`) which extends `Executable`. Tools have a `name`, `type` (READ/WRITE/ALL_API), `annotations`, and Zod-based input schemas.

There are two base classes for tools:

1. **`BaseMondayApiTool`** (`src/core/tools/platform-api-tools/base-monday-api-tool.ts`) — For tools that use the monday.com GraphQL API via `@mondaydotcomorg/api` client. Constructor receives `(apiClient, apiToken, context)`.

2. **`BaseMondayAppsTool`** (`src/core/tools/monday-apps-tools/base-tool/base-monday-apps-tool.ts`) — For tools that call monday.com Apps Framework REST endpoints via Axios. Constructor receives `(apiToken)`.

Both base classes wrap `executeInternal()` with tracking in their public `execute()` method. **Always implement `executeInternal()`, never override `execute()`.**

### Tool Categories

Tools are organized into three groups (see `src/core/tools/index.ts`):

- **`platform-api-tools/`** — GraphQL-based tools for boards, items, columns, workforms, docs, dashboards, search, etc. Registered via `allGraphqlApiTools`.
- **`monday-apps-tools/`** — REST-based tools for app management, features, versions, deployment, and storage. Registered via `allMondayAppsTools`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "Adding a New Platform API Tool" section is essentially a condensed version of what mcp-tool.md already covers in detail. Two sources for the same process will drift. Could simplify this to a one-liner pointing to /mcp-tool instead of maintaining parallel step lists.

- **`monday-dev-tools/`** — Sprint/development workflow tools. Registered via `allMondayDevTools`.

### Adding a New Platform API Tool

1. Create a directory under `src/core/tools/platform-api-tools/your-tool-name/`
2. Add GraphQL operations in `.graphql.ts` files using `gql` from `graphql-request`, then run `npm run codegen` to generate TS types
3. Define Zod input schema as a const object — every field needs `.describe()` for MCP tool documentation
4. Create a class extending `BaseMondayApiTool<typeof yourToolSchema>`
5. Set `name` (snake_case), `type`, and `annotations` via `createMondayApiAnnotations()` (sets `openWorldHint: true`). Annotation fields: `title`, `readOnlyHint` (true for READ), `destructiveHint` (true if deletes data), `idempotentHint` (true if repeated calls are safe)
6. Implement `getDescription()`, `getInputSchema()`, and `executeInternal()`
7. Register in `src/core/tools/platform-api-tools/index.ts` — add import, add to `allGraphqlApiTools` array, and add `export *`
8. Add tests as `.test.ts` files co-located with the tool; use `createMockApiClient()` from `test-utils/`

For detailed guidance with code examples, run `/mcp-tool` or see `../../.claude/commands/mcp-tool.md`.

### Tool Filtering & Modes

`ToolsConfiguration` (in `src/core/monday-agent-toolkit.ts`) controls which tools are available:

- **`mode`**: `'api'` (default — platform + dev tools), `'apps'` (apps framework tools only)
- **`include`/`exclude`**: Filter by tool name
- **`readOnlyMode`**: Only include tools with `type: ToolType.READ`
- **`enableDynamicApiTools`**: Controls `ALL_API` type tools (`true`/`false`/`'only'`)

### GraphQL Codegen

- Schema files: `src/monday-graphql/schema.graphql` (default) and `schema.dev.graphql` (dev)
- The API version used for fetching schemas comes from `src/utils/version.utils.ts`
- GraphQL operations in `*.graphql.ts` files generate types into `src/monday-graphql/generated/graphql/`
- Dev operations in `*.graphql.dev.ts` generate into `src/monday-graphql/generated/graphql.dev/`
- Config: `codegen.yml`

### Build Output

Rollup builds each subpath (`mcp`, `core`, `openai`) into both CJS and ESM formats with TypeScript declarations. External deps (`@mondaydotcomorg/api`, `zod`, `zod-to-json-schema`) are not bundled.

### Updating Existing Tools

When modifying an existing tool's behavior, review and update `getDescription()` to reflect the new capabilities. The description is what LLMs see when selecting tools — stale descriptions lead to incorrect tool usage.

### Version Bumping
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Document changes in CHANGELOG.md" — the CHANGELOG.md in this package is empty. If that's the intended convention going forward, fine, but worth noting that it's currently unpopulated.


**The package version must be manually bumped** in `package.json` before publishing — there is no automatic versioning. Document changes in `CHANGELOG.md`.
10 changes: 10 additions & 0 deletions packages/agent-toolkit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The package provides several modular components that can be imported separately:
The toolkit includes several pre-built tools for common monday.com operations, organized by functionality:

### Item Operations

- `CreateItemTool` - Create a new item in a monday.com board
- `DeleteItemTool` - Delete an item from a board
- `GetBoardItemsPageTool` - Get items by board id and apply filters
Expand All @@ -29,27 +30,36 @@ The toolkit includes several pre-built tools for common monday.com operations, o
- `MoveItemToGroupTool` - Move an item to a group in a monday.com board

### Board Operations

- `CreateBoardTool` - Create a monday.com board
- `GetBoardSchemaTool` - Get board schema (columns and groups) by board id
- `CreateGroupTool` - Create a new group in a monday.com board
- `CreateColumnTool` - Create a new column in a monday.com board
- `DeleteColumnTool` - Delete a column from a monday.com board

### WorkForms Operations

- `CreateFormTool` - Create a monday.com form
- `GetFormTool` - Get a form by its token, found in the form's URL
- `UpdateFormTool` - Update a monday.com form, including updating the form's feature settings, appearance settings, accessibility settings, title, description, question order, form tags, and form password
- `FormQuestionsEditorTool` - Create, update, or delete a question in a monday.com form

### Account Operations

- `ListUsersAndTeams` - Get users or teams, either by ids, names or by searching the account

### Workspace Operations

- `ListWorkspaceTool` - List workspaces available to the user, prioritizing workspaces where the user is a member

### Dynamic API Tools

- `AllMondayApiTool` - Execute any monday.com API operation by generating GraphQL queries and mutations dynamically
- `GetGraphQLSchemaTool` - Fetch the monday.com GraphQL schema structure including query and mutation definitions
- `GetTypeDetailsTool` - Get detailed information about a specific GraphQL type from the monday.com API schema

## Development

A Cursor skill is available at `.cursor/skills/agent-toolkit-api-tools/SKILL.md` with detailed guidance on creating and modifying platform API tools, including the GraphQL codegen pipeline, tool registration, and version bumping.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only mentions the Cursor skill but the Cursor SKILL.md is just a thin pointer to .claude/commands/mcp-tool.md. Might be worth referencing the Claude command too (or the Claude command as the primary, since Cursor just delegates to it).


## Usage