You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds a focused workflowy_children MCP read tool for bounded direct-child enumeration of large Workflowy nodes.
The new tool uses the live per-parent List API by default, sorts children by priority then id, applies optional regex filtering before pagination, and returns compact triage fields by default. It is intended for large inboxes/folders where workflowy_get, workflowy_list, or recursive workflowy_search can return too much subtree data for an LLM context.
Also adds CLI parity via workflowy children, shared pagination/projection helpers, unit tests, design/plan docs, and updates README/MCP/CLI/changelog docs.
Why
The current MCP read tools are basically all-or-nothing for large nodes. If you ask for a node with a lot of descendants, you get a huge JSON blob back. That works fine for small outlines, but it breaks down hard on real inbox-style nodes.
The concrete case here is my Workflowy “Dropbox” node. It has thousands of descendants and around a thousand direct children. I do not need an assistant to load that entire subtree just to start triaging it. I need it to do the boring but essential first step: show me the top-level children, 50 at a time, in order, with just enough metadata to decide what to open next.
Without this, the assistant gets stuck. workflowy_get and workflowy_list return too much. workflowy_search is recursive, so even a narrow regex can pull in matches from deep nested branches. The result is that the model cannot reliably enumerate the node at all.
This PR adds the missing primitive: “give me the direct children of this node, compactly, page by page.” Once that exists, an assistant can work like a human would: scan the top level, pick a child, then drill in only when needed.
Behavior
workflowy_children supports:
id: parent node ID or target key, default None
limit: page size, default 50, max 200
offset: zero-based offset
compact: default true
name_filter: optional regex applied to direct child names before pagination
ignore_case: case-insensitive filter matching
method: get, export, or backup; default uses the direct-children API
The response includes:
items
total
limit
offset
has_more
next_offset when another page exists
Compact items include id, name, layoutMode when present, completed, and has_children when known. Heavy fields such as notes, timestamps, URLs, priority, and nested descendants are omitted.
Before / After
Before, an assistant trying to inspect a large inbox had to call workflowy_get, workflowy_list, or recursive workflowy_search, which could return hundreds of KB or more of subtree JSON.
After, it can page direct children in compact batches:
I understand the motivation: pagination available to the MCP server, despite there not being a pagination available from the Workflowy API makes sense.
Two comments:
it seems workflowy_list already has the same semantics (ie returning the direct children nodes of a parent) as workflowy_children. I see the design decision to add a new children command instead of changing list to minimize risk. But I would rather we apply the pagination arguments to the existing list command, as well as get and search commands. When pagination arguments are provided, the result shape should change to include results in the items top level object and returns pagination fields (total, limit, etc...).
I think we could also add a --sort option that applies to get , list and search , defaulting to using the priority field.
What do you think? I'm happy to help with either or both of these. Or you tackle them as you see fit.
Thanks again for this work. Looking forward to integrate it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a focused
workflowy_childrenMCP read tool for bounded direct-child enumeration of large Workflowy nodes.The new tool uses the live per-parent List API by default, sorts children by
prioritythenid, applies optional regex filtering before pagination, and returns compact triage fields by default. It is intended for large inboxes/folders whereworkflowy_get,workflowy_list, or recursiveworkflowy_searchcan return too much subtree data for an LLM context.Also adds CLI parity via
workflowy children, shared pagination/projection helpers, unit tests, design/plan docs, and updates README/MCP/CLI/changelog docs.Why
The current MCP read tools are basically all-or-nothing for large nodes. If you ask for a node with a lot of descendants, you get a huge JSON blob back. That works fine for small outlines, but it breaks down hard on real inbox-style nodes.
The concrete case here is my Workflowy “Dropbox” node. It has thousands of descendants and around a thousand direct children. I do not need an assistant to load that entire subtree just to start triaging it. I need it to do the boring but essential first step: show me the top-level children, 50 at a time, in order, with just enough metadata to decide what to open next.
Without this, the assistant gets stuck.
workflowy_getandworkflowy_listreturn too much.workflowy_searchis recursive, so even a narrow regex can pull in matches from deep nested branches. The result is that the model cannot reliably enumerate the node at all.This PR adds the missing primitive: “give me the direct children of this node, compactly, page by page.” Once that exists, an assistant can work like a human would: scan the top level, pick a child, then drill in only when needed.
Behavior
workflowy_childrensupports:id: parent node ID or target key, defaultNonelimit: page size, default50, max200offset: zero-based offsetcompact: defaulttruename_filter: optional regex applied to direct child names before paginationignore_case: case-insensitive filter matchingmethod:get,export, orbackup; default uses the direct-children APIThe response includes:
itemstotallimitoffsethas_morenext_offsetwhen another page existsCompact items include
id,name,layoutModewhen present,completed, andhas_childrenwhen known. Heavy fields such as notes, timestamps, URLs, priority, and nested descendants are omitted.Before / After
Before, an assistant trying to inspect a large inbox had to call
workflowy_get,workflowy_list, or recursiveworkflowy_search, which could return hundreds of KB or more of subtree JSON.After, it can page direct children in compact batches:
{ "id": "dropbox-id", "limit": 50, "offset": 0 }returns:
{ "items": [ { "id": "child-id", "name": "Triage item", "completed": false } ], "total": 1000, "limit": 50, "offset": 0, "next_offset": 50, "has_more": true }The assistant can then continue with
offset=50,offset=100, etc., without loading nested descendants.Validation
docker run --rm -v "$PWD":/src -w /src golang:1.24.3 gofmt -w ...docker run --rm -v "$PWD":/src -w /src golang:1.24.3 go test ./...docker run --rm -v "$PWD":/src -w /src golang:1.24.3 go vet ./...docker run --rm -v "$PWD":/src -w /src golang:1.24.3 go build ./cmd/workflowygit diff --checkManual validation:
workflowy childrenagainst a temporary Workflowy backup fixture.total=3,limit=2,offset=0,next_offset=2,has_more=true.has_more=false.--name-filter ^a --ignore-casefilters before pagination.tools/listexposesworkflowy_children.tools/callreturns compact paginatedstructuredContent.workflowy_childrenis annotated as read-only and non-destructive.