feat: add create_bulk_items tool - #351
Conversation
Adds a new MCP tool that bulk creates or updates up to 10,000 items on a board using the ingest_items mutation (API-Version: 2026-07). Handles CSV generation, S3 upload, and job status polling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Return type is UploadJobInit with fields: job_id, upload_url (not s3_url/status) - Add group_id parameter (required by API, defaults to "topics") Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
I checked this against the current monday bulk-import docs, and one detail looks worth adjusting before merge: the docs recommend polling Source: https://developer.monday.com/api-reference/docs/importing-items-in-bulk Because This review note was Codex-assisted; I manually checked it against the linked monday.com docs before posting. |
Separates the single bulk tool into two distinct tools so LLMs can better recognize update capabilities: - create_bulk_items: creates new items (group_id optional, defaults to "topics") - update_bulk_items: updates existing items via on_match (group_id required) Shared logic extracted to bulk-items.utils.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; | ||
| import { boardIdSchema, groupIdSchema, itemsSchema, executeIngestItems } from './bulk-items.utils'; | ||
|
|
||
| const onMatchSchema = z.object({ |
There was a problem hiding this comment.
maybe you can reference these tools from the existing change column value / create item tools in their description
There was a problem hiding this comment.
Good idea! Added cross-references in both change_item_column_values ("For updating multiple items at once, use update_bulk_items instead") and create_item ("For creating many items at once, use create_bulk_items instead") descriptions.
| }; | ||
|
|
||
| export class UpdateBulkItemsTool extends BaseMondayApiTool<typeof updateBulkItemsSchema, never> { | ||
| name = 'update_bulk_items'; |
There was a problem hiding this comment.
can the name match the existing change column value tool?
There was a problem hiding this comment.
I'd prefer keeping update_bulk_items rather than change_item_column_values_bulk — the name was intentionally chosen for LLM discoverability. When an LLM sees "update multiple items" in a user request, update_bulk_items is a more natural match. The change_item_column_values naming is a legacy convention that's already confusing for models. That said, I've added cross-references in the existing tool descriptions so the LLM knows to route to bulk tools when appropriate.
|
|
||
| const { job_id, upload_url } = ingestRes.ingest_items; | ||
|
|
||
| const csv = buildCsv(params.items); |
There was a problem hiding this comment.
is it worth building the csv for 10 items? feels to me this solution fits huge uploads but not day-to-day updates. or is this the only existing API?
There was a problem hiding this comment.
You're right that for 5-10 items it's heavier than needed. However, ingest_items is the only bulk API available — the alternative is N individual change_item_column_values mutations which means N round-trips. Even for small batches, the CSV+S3 overhead is negligible (a few hundred bytes PUT) compared to the latency of multiple sequential GraphQL calls. We could add a threshold (e.g. <3 items → fall back to individual calls) but that adds branching complexity for marginal gain. Happy to revisit if we see performance issues in practice.
| const { job_id, upload_url } = ingestRes.ingest_items; | ||
|
|
||
| const csv = buildCsv(params.items); | ||
| const uploadResponse = await fetch(upload_url, { |
There was a problem hiding this comment.
if we return the url to the agent and instruct him to upload the file and then all us back again it will reduce the resources we use for this opteration.
the downside is that it's more work for the agent. WDYT?
There was a problem hiding this comment.
Interesting idea but I'd lean against it. Splitting into multiple tool calls means:
- The agent needs to know how to format CSV and PUT to S3 — that's fragile and model-dependent
- 3 tool calls minimum (get URL → upload → poll) instead of 1 atomic call
- More LLM tokens consumed per operation
- More failure points (agent might format CSV wrong, forget content-type header, etc.)
The resource cost on our side is one S3 PUT of a small payload + polling — both lightweight. Keeping it atomic gives us reliability and simplicity. If resource usage becomes a concern at scale we could revisit with a streaming approach, but for now the single-call UX is much more robust.
There was a problem hiding this comment.
ok just note that large file uploads can consume allot of resources (you basically pass all the payload twice).
maybe as an initial phase we should start we less than 10000 items counts
…n_values descriptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
create_bulk_itemsMCP tool that bulk creates/updates up to 10,000 items on a board via theingest_itemsmutation (API-Version: 2026-07)on_matchparameterTest plan
on_matchparameter🤖 Generated with Claude Code