things-api 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/canonical-ref.d.ts +21 -0
- package/dist/cli/canonical-ref.js +23 -0
- package/dist/cli/canonical-ref.js.map +1 -0
- package/dist/cli/commands/area.js +27 -11
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +2 -2
- package/dist/cli/commands/install-skill.js +29 -0
- package/dist/cli/commands/install-skill.js.map +1 -1
- package/dist/cli/commands/mcp.js +12 -1
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.js +73 -21
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +5 -1
- package/dist/cli/commands/reads.js +10 -3
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.js +11 -4
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +45 -30
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.js +1 -1
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +31 -6
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.js +19 -5
- package/dist/cli/did-you-mean.js.map +1 -1
- package/dist/cli/dry-run.d.ts +55 -0
- package/dist/cli/dry-run.js +92 -0
- package/dist/cli/dry-run.js.map +1 -0
- package/dist/cli/help.js +7 -6
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +7 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/read-driver.d.ts +16 -6
- package/dist/cli/read-driver.js +19 -18
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/ref-render.d.ts +14 -0
- package/dist/cli/ref-render.js +9 -0
- package/dist/cli/ref-render.js.map +1 -0
- package/dist/cli/render.d.ts +21 -6
- package/dist/cli/render.js +73 -34
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +5 -3
- package/dist/cli/resolve-invocation.js +13 -4
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/client.d.ts +18 -7
- package/dist/client.js +2 -1
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +12 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +4 -1
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +81 -42
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +11 -1
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.js +3 -0
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/serialize.js +15 -3
- package/dist/model/serialize.js.map +1 -1
- package/dist/read/area-filter.d.ts +2 -2
- package/dist/read/area-filter.js +5 -6
- package/dist/read/area-filter.js.map +1 -1
- package/dist/read/area-view.d.ts +11 -0
- package/dist/read/area-view.js +5 -1
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/project-view.d.ts +61 -1
- package/dist/read/project-view.js +74 -9
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +71 -2
- package/dist/read/queries.js +199 -10
- package/dist/read/queries.js.map +1 -1
- package/dist/read/scope.d.ts +2 -2
- package/dist/read/scope.js +5 -6
- package/dist/read/scope.js.map +1 -1
- package/dist/read/shape.d.ts +36 -17
- package/dist/read/shape.js +251 -200
- package/dist/read/shape.js.map +1 -1
- package/dist/read/show-target.js +52 -33
- package/dist/read/show-target.js.map +1 -1
- package/dist/read/truncation.d.ts +0 -7
- package/dist/read/truncation.js +24 -14
- package/dist/read/truncation.js.map +1 -1
- package/dist/read/views.d.ts +19 -7
- package/dist/read/views.js +13 -12
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +7 -0
- package/dist/surface-copy.js +7 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/write/commands.js +3 -1
- package/dist/write/commands.js.map +1 -1
- package/dist/write/move.d.ts +10 -6
- package/dist/write/move.js +417 -76
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +1 -1
- package/dist/write/operations.js.map +1 -1
- package/dist/write/pre-state.d.ts +10 -0
- package/dist/write/pre-state.js +118 -41
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/reorder.js +263 -29
- package/dist/write/reorder.js.map +1 -1
- package/package.json +1 -1
- package/schema/envelope.schema.json +14 -0
- package/skills/things-cli/SKILL.md +6 -4
- package/skills/things-cli/references/contracts.md +3 -1
- package/skills/things-cli/references/errors.md +9 -1
- package/skills/things-cli/references/model.md +6 -4
- package/skills/things-cli/references/ordering.md +21 -4
package/dist/mcp/server.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { z } from "zod";
|
|
18
18
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
|
-
import { ALL_DESC, AREA_FILTER_DESC, AREA_LIMIT_DESC, AREA_PREVIEW_LIMIT, blockedCode, capabilitiesTable, DATE_FORMAT, DEFAULT_LIST_LIMIT, diagnose, FILTER_CONTRACT, FULL_DESC, hasTagPresence, isLooseRef, isValidTimeZone, LIMIT_DESC, looseShadowNotice, MCP_WHEN_LABELS, mutationWireData, noUuidMatch, omitEmpty, OMIT_EMPTY_NOTE, OP_ID_RE, OPERATION_KINDS, openThings, PKG_VERSION, PROJECT_LIMIT_DESC, PROJECT_PREVIEW_LIMIT, REF_FORMAT, ReferenceResolutionError, REMINDER_FORMAT, schemaWarnings, shapeReadPayload, splitWhenSugar, tagFilterFields, tagFlagConflict, validateViewArgs, verifyFailedCode, WHEN_VALUES, } from "../index.js";
|
|
19
|
+
import { ALL_DESC, AREA_FILTER_DESC, AREA_LIMIT_DESC, AREA_PREVIEW_LIMIT, blockedCode, capabilitiesTable, DATE_FORMAT, DEFAULT_LIST_LIMIT, diagnose, FILTER_CONTRACT, FULL_DESC, hasTagPresence, isLooseRef, isValidTimeZone, LIMIT_DESC, looseShadowNotice, MCP_WHEN_LABELS, mutationWireData, noUuidMatch, omitEmpty, OMIT_EMPTY_NOTE, OP_ID_RE, OPERATION_KINDS, openThings, PKG_VERSION, PROJECT_LIMIT_DESC, PROJECT_PREVIEW_LIMIT, REF_FORMAT, REF_RULE_NOTE, ReferenceResolutionError, REMINDER_FORMAT, schemaWarnings, shapeReadPayload, splitWhenSugar, tagFilterFields, tagFlagConflict, validateViewArgs, verifyFailedCode, WHEN_VALUES, } from "../index.js";
|
|
20
20
|
function jsonResult(data) {
|
|
21
21
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
22
22
|
}
|
|
@@ -32,16 +32,22 @@ function readResult(data) {
|
|
|
32
32
|
/**
|
|
33
33
|
* A read result carrying truncation metadata: the data (already limited) in
|
|
34
34
|
* the first content block, and a second block with the {@link Truncation}
|
|
35
|
-
* numbers plus a one-line note the agent can read when rows were dropped.
|
|
35
|
+
* numbers plus a one-line note the agent can read when rows were dropped. `meta`
|
|
36
|
+
* merges extra whole-view metadata into that second block — the today view's
|
|
37
|
+
* `counts` aggregate (the analog of the CLI envelope's `meta.counts`), so `data`
|
|
38
|
+
* stays pure domain rows.
|
|
36
39
|
*/
|
|
37
|
-
function truncatedResult(data, truncation) {
|
|
40
|
+
function truncatedResult(data, truncation, meta) {
|
|
38
41
|
const note = truncation.truncated
|
|
39
42
|
? `showing ${truncation.shown} of ${truncation.total} items — pass limit (or all: true) to see more`
|
|
40
43
|
: undefined;
|
|
41
44
|
return {
|
|
42
45
|
content: [
|
|
43
46
|
{ type: "text", text: JSON.stringify(omitEmpty(data)) },
|
|
44
|
-
{
|
|
47
|
+
{
|
|
48
|
+
type: "text",
|
|
49
|
+
text: JSON.stringify({ truncation, ...meta, ...(note !== undefined && { note }) }),
|
|
50
|
+
},
|
|
45
51
|
],
|
|
46
52
|
};
|
|
47
53
|
}
|
|
@@ -173,7 +179,11 @@ function moveResult(result) {
|
|
|
173
179
|
return jsonResult(result.plan);
|
|
174
180
|
case "move-refused":
|
|
175
181
|
return errorResult({
|
|
176
|
-
|
|
182
|
+
// A hoisted placement block names its hazard — surface the canonical
|
|
183
|
+
// `blocked:<hazard>` code, matching a direct reorder hazard block.
|
|
184
|
+
code: result.hazard !== undefined
|
|
185
|
+
? blockedCode({ hazard: result.hazard, reason: "hazard" })
|
|
186
|
+
: result.refusal,
|
|
177
187
|
message: result.detail,
|
|
178
188
|
...(result.remediation !== undefined && { remediation: result.remediation }),
|
|
179
189
|
...(result.candidates !== undefined && { details: { candidates: result.candidates } }),
|
|
@@ -382,9 +392,10 @@ function buildInstructions(getClient) {
|
|
|
382
392
|
"confirmation parameter named in their description; refused calls return an error saying " +
|
|
383
393
|
"what to pass.",
|
|
384
394
|
"- Read-result semantics: an item's tags are its direct tags; its effective tags also include " +
|
|
385
|
-
"tags inherited from its containing project and area.
|
|
386
|
-
"
|
|
387
|
-
"is in Anytime and carries
|
|
395
|
+
"tags inherited from its containing project and area. An item's when is today or evening for " +
|
|
396
|
+
"a Today member (evening implies today), a future date for a scheduled item, else absent; an " +
|
|
397
|
+
"unscheduled start=active item is in Anytime and carries no when. Completing an item makes it " +
|
|
398
|
+
"findable in Logbook.",
|
|
388
399
|
"- For capped reads, pass limit to cap rows or all: true for everything; if both are set, all wins.",
|
|
389
400
|
`- Read results are compact: ${OMIT_EMPTY_NOTE}`,
|
|
390
401
|
];
|
|
@@ -566,8 +577,9 @@ export function createThingsMcpServer(options = {}) {
|
|
|
566
577
|
};
|
|
567
578
|
// ------------------------------------------------------------------ reads
|
|
568
579
|
server.registerTool("read_view", {
|
|
569
|
-
description: "Read a Things list as the app presents it: today (
|
|
570
|
-
"
|
|
580
|
+
description: "Read a Things list as the app presents it: today (one flat list of Today " +
|
|
581
|
+
"members, each item's when marking Today vs This Evening), inbox, anytime, " +
|
|
582
|
+
"upcoming, someday, logbook, or trash. For upcoming, " +
|
|
571
583
|
"horizon > 1 also includes future occurrences of repeating items (up to 10 each). " +
|
|
572
584
|
"anytime/someday return sections in canonical order (area + items; null area = the " +
|
|
573
585
|
"top-level block); children of someday/future-scheduled projects are excluded " +
|
|
@@ -578,7 +590,9 @@ export function createThingsMcpServer(options = {}) {
|
|
|
578
590
|
`area_limit (default ${AREA_PREVIEW_LIMIT}) per area block, and on anytime ` +
|
|
579
591
|
`project_limit (default ${PROJECT_PREVIEW_LIMIT}) per project block. ` +
|
|
580
592
|
"all: true lifts every cap; the result's second block reports the counts. " +
|
|
581
|
-
OMIT_EMPTY_NOTE
|
|
593
|
+
OMIT_EMPTY_NOTE +
|
|
594
|
+
" " +
|
|
595
|
+
REF_RULE_NOTE,
|
|
582
596
|
inputSchema: {
|
|
583
597
|
view: z.enum(["today", "inbox", "anytime", "upcoming", "someday", "logbook", "trash"]),
|
|
584
598
|
...tagFilterShape,
|
|
@@ -587,7 +601,10 @@ export function createThingsMcpServer(options = {}) {
|
|
|
587
601
|
.string()
|
|
588
602
|
.optional()
|
|
589
603
|
.describe(`today/anytime/someday/upcoming/logbook only: ${AREA_FILTER_DESC}`),
|
|
590
|
-
evening: z
|
|
604
|
+
evening: z
|
|
605
|
+
.boolean()
|
|
606
|
+
.optional()
|
|
607
|
+
.describe("today only: show only This-Evening members (when = evening)"),
|
|
591
608
|
show_active_project_items: z
|
|
592
609
|
.union([z.boolean(), z.number().int().min(1)])
|
|
593
610
|
.optional()
|
|
@@ -698,11 +715,11 @@ export function createThingsMcpServer(options = {}) {
|
|
|
698
715
|
limit,
|
|
699
716
|
});
|
|
700
717
|
filterMeta = fm;
|
|
701
|
-
return truncatedResult(shapeReadPayload("today", view, full), truncation);
|
|
718
|
+
return truncatedResult(shapeReadPayload("today", view, full, c.refPromoter()), truncation, { counts: view.counts });
|
|
702
719
|
}
|
|
703
720
|
case "inbox": {
|
|
704
721
|
const { items, truncation } = c.read.inbox({ ...filter, ...zone, limit });
|
|
705
|
-
return truncatedResult(shapeReadPayload("inbox", items, full), truncation);
|
|
722
|
+
return truncatedResult(shapeReadPayload("inbox", items, full, c.refPromoter()), truncation);
|
|
706
723
|
}
|
|
707
724
|
case "anytime": {
|
|
708
725
|
const { view, truncation, filter: fm, } = c.read.anytime({
|
|
@@ -713,7 +730,7 @@ export function createThingsMcpServer(options = {}) {
|
|
|
713
730
|
projectLimit,
|
|
714
731
|
});
|
|
715
732
|
filterMeta = fm;
|
|
716
|
-
return groupedResult(shapeReadPayload("anytime", view, full), truncation);
|
|
733
|
+
return groupedResult(shapeReadPayload("anytime", view, full, c.refPromoter()), truncation);
|
|
717
734
|
}
|
|
718
735
|
case "upcoming": {
|
|
719
736
|
const { items, truncation, filter: fm, } = c.read.upcoming({
|
|
@@ -724,7 +741,7 @@ export function createThingsMcpServer(options = {}) {
|
|
|
724
741
|
limit,
|
|
725
742
|
});
|
|
726
743
|
filterMeta = fm;
|
|
727
|
-
return truncatedResult(shapeReadPayload("upcoming", items, full), truncation);
|
|
744
|
+
return truncatedResult(shapeReadPayload("upcoming", items, full, c.refPromoter()), truncation);
|
|
728
745
|
}
|
|
729
746
|
case "someday": {
|
|
730
747
|
const active = showActiveProjectItems;
|
|
@@ -743,7 +760,7 @@ export function createThingsMcpServer(options = {}) {
|
|
|
743
760
|
projectLimit: typeof active === "number" ? active : null,
|
|
744
761
|
});
|
|
745
762
|
filterMeta = fm;
|
|
746
|
-
return groupedResult(shapeReadPayload("someday", view, full), truncation);
|
|
763
|
+
return groupedResult(shapeReadPayload("someday", view, full, c.refPromoter()), truncation);
|
|
747
764
|
}
|
|
748
765
|
case "logbook": {
|
|
749
766
|
const { items, truncation, filter: fm, } = c.read.logbook({
|
|
@@ -753,11 +770,11 @@ export function createThingsMcpServer(options = {}) {
|
|
|
753
770
|
limit,
|
|
754
771
|
});
|
|
755
772
|
filterMeta = fm;
|
|
756
|
-
return truncatedResult(shapeReadPayload("logbook", items, full), truncation);
|
|
773
|
+
return truncatedResult(shapeReadPayload("logbook", items, full, c.refPromoter()), truncation);
|
|
757
774
|
}
|
|
758
775
|
case "trash": {
|
|
759
776
|
const { items, truncation } = c.read.trash({ ...zone, limit });
|
|
760
|
-
return truncatedResult(shapeReadPayload("trash", items, full), truncation);
|
|
777
|
+
return truncatedResult(shapeReadPayload("trash", items, full, c.refPromoter()), truncation);
|
|
761
778
|
}
|
|
762
779
|
}
|
|
763
780
|
}, args.tz, () => (filterMeta !== undefined ? { filter: filterMeta } : undefined), () => looseAreaWarnings(getClient(), args.area));
|
|
@@ -766,7 +783,9 @@ export function createThingsMcpServer(options = {}) {
|
|
|
766
783
|
description: "Find items by title/notes substring. Returns open, untrashed items by default; " +
|
|
767
784
|
"include more with logged/trashed/all. Scope with project/area/tag — scope " +
|
|
768
785
|
"references must name existing items. " +
|
|
769
|
-
OMIT_EMPTY_NOTE
|
|
786
|
+
OMIT_EMPTY_NOTE +
|
|
787
|
+
" " +
|
|
788
|
+
REF_RULE_NOTE,
|
|
770
789
|
inputSchema: {
|
|
771
790
|
query: z.string(),
|
|
772
791
|
...tagFilterShape,
|
|
@@ -821,13 +840,15 @@ export function createThingsMcpServer(options = {}) {
|
|
|
821
840
|
...(args.trashed === true && { trashed: true }),
|
|
822
841
|
...(args.all === true && { all: true }),
|
|
823
842
|
});
|
|
824
|
-
return truncatedResult(shapeReadPayload("search", items, args.full === true), truncation);
|
|
843
|
+
return truncatedResult(shapeReadPayload("search", items, args.full === true, getClient().refPromoter()), truncation);
|
|
825
844
|
}, args.tz, undefined, () => looseAreaWarnings(getClient(), args.area)));
|
|
826
845
|
server.registerTool("changes_since", {
|
|
827
846
|
description: "List items created or modified since a moment — including trashed, logged, and " +
|
|
828
847
|
"repeating items (inspect each item's fields to tell them apart). Edits to tags, " +
|
|
829
848
|
"areas, and checklist items do not mark the containing item as modified. " +
|
|
830
|
-
OMIT_EMPTY_NOTE
|
|
849
|
+
OMIT_EMPTY_NOTE +
|
|
850
|
+
" " +
|
|
851
|
+
REF_RULE_NOTE,
|
|
831
852
|
inputSchema: {
|
|
832
853
|
since: z.string().describe("ISO date-time, e.g. 2026-07-06T08:00:00"),
|
|
833
854
|
...limitShape,
|
|
@@ -849,26 +870,34 @@ export function createThingsMcpServer(options = {}) {
|
|
|
849
870
|
limit,
|
|
850
871
|
...(args.tz !== undefined && { zone: args.tz }),
|
|
851
872
|
});
|
|
852
|
-
return truncatedResult(shapeReadPayload("changes", items, args.full === true), truncation);
|
|
873
|
+
return truncatedResult(shapeReadPayload("changes", items, args.full === true, getClient().refPromoter()), truncation);
|
|
853
874
|
}, args.tz));
|
|
854
875
|
server.registerTool("get_item", {
|
|
855
876
|
description: "Full detail for one item by uuid: notes, schedule, reminder, deadline, tags " +
|
|
856
877
|
"(direct and inherited), checklist with per-item state, repeat schedule, and its " +
|
|
857
878
|
"project/area/heading. " +
|
|
858
|
-
OMIT_EMPTY_NOTE
|
|
879
|
+
OMIT_EMPTY_NOTE +
|
|
880
|
+
" " +
|
|
881
|
+
REF_RULE_NOTE,
|
|
859
882
|
inputSchema: { uuid: z.string() },
|
|
860
883
|
annotations: READ_ONLY,
|
|
861
884
|
}, async (args) => readGuard(() => {
|
|
862
885
|
const item = getClient().read.byUuid(args.uuid);
|
|
863
886
|
return item === null
|
|
864
887
|
? errorResult({ code: "not-found", message: noUuidMatch("item", args.uuid) })
|
|
865
|
-
: readResult(shapeReadPayload("detail", item, false));
|
|
888
|
+
: readResult(shapeReadPayload("detail", item, false, getClient().refPromoter()));
|
|
866
889
|
}));
|
|
867
890
|
server.registerTool("get_project", {
|
|
868
|
-
description: "One project's full contents: metadata
|
|
869
|
-
"
|
|
870
|
-
"
|
|
871
|
-
|
|
891
|
+
description: "One project's full contents: metadata, its live child to-dos as one flat list (items, " +
|
|
892
|
+
"in index order — each carrying its stage, when, and, when it lives under a heading, " +
|
|
893
|
+
"its heading ref), the heading catalog (headings — every heading in index order, " +
|
|
894
|
+
"carrying archived once archived), and its logged children (logbook, most recent " +
|
|
895
|
+
"first, each carrying its heading ref). Reconstruct a heading's members by filtering " +
|
|
896
|
+
"items (or logbook) on the heading ref. The tag filters keep only the child to-dos " +
|
|
897
|
+
"matching by their own tags (a heading left with none is dropped). " +
|
|
898
|
+
OMIT_EMPTY_NOTE +
|
|
899
|
+
" " +
|
|
900
|
+
REF_RULE_NOTE,
|
|
872
901
|
inputSchema: {
|
|
873
902
|
uuid: z.string().describe("Project uuid or unique name"),
|
|
874
903
|
...tagOnlyShape,
|
|
@@ -890,17 +919,19 @@ export function createThingsMcpServer(options = {}) {
|
|
|
890
919
|
overdue: args.overdue === true,
|
|
891
920
|
...tagFilterFields(tagPresence(args)),
|
|
892
921
|
...(args.tz !== undefined && { zone: args.tz }),
|
|
893
|
-
}), args.full === true));
|
|
922
|
+
}), args.full === true, getClient().refPromoter()));
|
|
894
923
|
}, args.tz));
|
|
895
924
|
server.registerTool("get_area", {
|
|
896
|
-
description: "One area's contents: metadata plus its direct to-dos (
|
|
897
|
-
"
|
|
898
|
-
"logbook is not returned here — read it with read_view
|
|
899
|
-
"rows live in read_view trash. " +
|
|
900
|
-
`The project
|
|
925
|
+
description: "One area's contents: metadata plus its direct to-dos as one flat list (items, in " +
|
|
926
|
+
"index order — each row carrying its stage and when) and its projects in canonical " +
|
|
927
|
+
"order (projects). The area logbook is not returned here — read it with read_view " +
|
|
928
|
+
"logbook + area; trashed rows live in read_view trash. " +
|
|
929
|
+
`The project rows and the open/current direct to-dos are capped at ${AREA_PREVIEW_LIMIT} each ` +
|
|
901
930
|
"by default (project_limit / area_limit adjust them; all: true lifts both); the " +
|
|
902
931
|
"second result block reports the counts. " +
|
|
903
|
-
OMIT_EMPTY_NOTE
|
|
932
|
+
OMIT_EMPTY_NOTE +
|
|
933
|
+
" " +
|
|
934
|
+
REF_RULE_NOTE,
|
|
904
935
|
inputSchema: {
|
|
905
936
|
ref: z.string().describe("Area uuid or unique name"),
|
|
906
937
|
...tagOnlyShape,
|
|
@@ -949,14 +980,16 @@ export function createThingsMcpServer(options = {}) {
|
|
|
949
980
|
projectLimit,
|
|
950
981
|
});
|
|
951
982
|
areaNotice = notice;
|
|
952
|
-
return groupedResult(shapeReadPayload("area-view", view, args.full === true), truncation);
|
|
983
|
+
return groupedResult(shapeReadPayload("area-view", view, args.full === true, getClient().refPromoter()), truncation);
|
|
953
984
|
}, args.tz, undefined, () => (areaNotice !== undefined ? [areaNotice] : undefined));
|
|
954
985
|
});
|
|
955
986
|
server.registerTool("list_collections", {
|
|
956
987
|
description: "List every project, area, or tag (tags include their parent-tag nesting). Use to " +
|
|
957
988
|
"refresh the inventory summarized in the server instructions. The tag filters scope " +
|
|
958
989
|
"the projects list by each project's own tags (areas/tags reject them). " +
|
|
959
|
-
OMIT_EMPTY_NOTE
|
|
990
|
+
OMIT_EMPTY_NOTE +
|
|
991
|
+
" " +
|
|
992
|
+
REF_RULE_NOTE,
|
|
960
993
|
inputSchema: {
|
|
961
994
|
kind: z.enum(["projects", "areas", "tags"]),
|
|
962
995
|
...tagOnlyShape,
|
|
@@ -1001,7 +1034,7 @@ export function createThingsMcpServer(options = {}) {
|
|
|
1001
1034
|
})
|
|
1002
1035
|
: args.kind === "areas"
|
|
1003
1036
|
? c.read.areas()
|
|
1004
|
-
: c.read.tags(), args.full === true));
|
|
1037
|
+
: c.read.tags(), args.full === true, c.refPromoter()));
|
|
1005
1038
|
}, args.tz));
|
|
1006
1039
|
// ---------------------------------------------------------------- to-dos
|
|
1007
1040
|
const whenSchema = z.string().optional().describe(WHEN_VALUES);
|
|
@@ -2116,7 +2149,9 @@ export function createThingsMcpServer(options = {}) {
|
|
|
2116
2149
|
"position the block instead. Refs that span different containers or buckets are refused. " +
|
|
2117
2150
|
"A Today or This Evening member also holds a slot in its own container, so a set that is " +
|
|
2118
2151
|
"coherent on BOTH axes is ambiguous — pass `in` to name the axis (the refusal names both " +
|
|
2119
|
-
"choices).
|
|
2152
|
+
"choices). A deadline-forecast set sharing one Upcoming day is dual-axis the same way (the " +
|
|
2153
|
+
"day-block vs its container order); `in: upcoming` or `in: <YYYY-MM-DD>` names the day-block. " +
|
|
2154
|
+
"The project rows the Today/Evening/day lists intermix with to-dos may be " +
|
|
2120
2155
|
"reordered alongside them. Ordering the Today, Inbox, or Someday lists, a project's " +
|
|
2121
2156
|
"to-dos, or an area must first be enabled once via `things config set allow-experimental " +
|
|
2122
2157
|
"true`. To reorder a project's HEADINGS (children follow) use the heading tool's " +
|
|
@@ -2129,8 +2164,12 @@ export function createThingsMcpServer(options = {}) {
|
|
|
2129
2164
|
in: z
|
|
2130
2165
|
.string()
|
|
2131
2166
|
.optional()
|
|
2132
|
-
.describe("
|
|
2133
|
-
"
|
|
2167
|
+
.describe("Name the axis to reorder on: today | evening | anytime | someday | inbox, a project/" +
|
|
2168
|
+
"area/heading ref (uuid or unique title), upcoming (the one future day the set " +
|
|
2169
|
+
"shares), or a YYYY-MM-DD day-block. A stage-list or container axis sorts one KIND " +
|
|
2170
|
+
"at a time — a mixed to-do+project set is refused (even sharing a container); only " +
|
|
2171
|
+
"today | evening | upcoming | a day-block intermix both kinds. Reorder a project's " +
|
|
2172
|
+
"headings with the heading tool's move_heading action."),
|
|
2134
2173
|
...dryRunShape,
|
|
2135
2174
|
},
|
|
2136
2175
|
annotations: NON_DESTRUCTIVE,
|