Skip to content

fix(tools): honour select fields in b24_task_list — task body was unreachable - #261

Open
aa-blinov wants to merge 1 commit into
bitrix24:mainfrom
aa-blinov:fix/list-tasks-select-fields
Open

aa-blinov wants to merge 1 commit into
bitrix24:mainfrom
aa-blinov:fix/list-tasks-select-fields

Conversation

@aa-blinov

Copy link
Copy Markdown

Summary

Fixes #203b24_task_list accepted a select, passed it to Bitrix24 correctly, and then threw away everything outside the default seven fields, so a task's body could not be read through this MCP at all. description now comes back when it's in the select (with Bitrix24's descriptionInBbcode markup flag), and so do the select-only scalars groupId / createdBy / parentId / changedDate / closedDate.

Type of change

  • feat
  • fix
  • docs
  • chore
  • test
  • refactor
  • ci

Linked issue

Closes #203

Checklist

  • PR title follows Conventional Commits
  • pnpm lint passes
  • pnpm typecheck passes
  • pnpm test passes
  • New or changed code has tests
  • Public-facing changes reflected in docs/ and skills/ (README tool table + the b24_task_list tool description; the tool-authoring conventions are unchanged, so docs/ADDING-TOOLS.md and the agent skill need no edit)
  • No unrelated changes
  • No secrets in code, tests, or CI logs

Screenshots / logs

Live portal, same task, before and after. With the field selected:

{"total":1,"returned":1,"tasks":[{"id":"4153","title":"","description":"[b]Причина[/b]\n\n","descriptionInBbcode":true,"groupId":"111","createdBy":"35"}]}

Default listing, unchanged (no new keys, no extra bytes):

{"total":null,"returned":1,"tasks":[{"id":"4153","title":"","status":"2","deadline":null,"responsibleId":"9","createdDate":"","priority":"1"}]}

The body in that first response is 764 characters; nothing is truncated.

Notes for reviewers

The bug was entirely in the projection, not the transport. normalizeBitrix24Select did its job and tasks.task.list returned the field — toTaskShort then rebuilt each row from a fixed field list, so the select looked honoured while the data quietly vanished. Worth knowing because the same shape applies to any field a future PR wants to surface.

Two decisions I'd particularly like a second opinion on:

Why the body is opt-in but the scalars aren't. Bitrix24 omits groupId / createdBy / parentId / changedDate / closedDate unless they're selected, so "present on the wire" is already equivalent to "the operator asked for it" — projecting them when present is honouring the select, no flag needed. description is different: toTaskShort is shared with create / update / rate and the seven lifecycle verbs, and Bitrix24 echoes the full task on those endpoints. Projecting the body unconditionally would bill the agent for a description it had just written, on every mutation. Hence ToTaskShortOptions.withDescription, which only the read path sets.

What I left dropped on purpose. Bitrix24 ships nested group and creator objects alongside groupId / createdBy without being asked — member counts, work positions, avatar URLs. Those stay out of the projection; if someone wants the group name, groupId plus a group tool is the cheaper path. There's a test pinning this so it doesn't drift back in.

Issue #203 also mentions the absence of a single-task get tool. I didn't add one here — with filter: { id: N } plus a select the list tool now covers the "what is this task about" case, and a b24_task_get on v3 is a separate decision (it's the worked example in skills/manage-bx24-template-mcp/adding-tools.md but has never shipped). Happy to do it as a follow-up if you'd rather have the dedicated tool.

Unrelated to this PR but same reporter, in case it's useful triage: #203 also lists createdBy and groupId, which this covers, and the reporter's other open issue (#205) is a separate matter.

…eachable

Closes bitrix24#203.

`select: ['id', 'title', 'description']` reached Bitrix24 intact and
Bitrix24 returned the body — then `toTaskShort` rebuilt each row from a
hard-coded field list and dropped it. The select looked honoured while the
task body was unreachable through the MCP entirely, since there is no
single-task get tool either: an agent asked "what is this task about?"
had nothing but the title to go on.

Two changes:

- `description` is projected when the caller puts it in the `select`, in
  full and never truncated, alongside Bitrix24's `descriptionInBbcode`
  flag ("Y"/"N" coerced to a boolean — true means the body is BBCode,
  false HTML) so the agent knows how to read the markup.
- The select-only scalars `groupId`, `createdBy`, `parentId`,
  `changedDate` and `closedDate` are projected whenever Bitrix24 ships
  them. Bitrix24 omits these unless they are selected, so "present on the
  wire" already means "the operator asked for it" — no flag needed.
  `parentId` also unblocks walking subtasks (`MANUAL-TEST-PHRASES.md`
  §10.2).

Default listings are byte-identical to before — the default select asks
for none of these fields.

The body stays behind an explicit opt-in (`ToTaskShortOptions.
withDescription`) rather than riding along with the scalars, because
`toTaskShort` is shared with create / update / rate and the seven
lifecycle verbs, and Bitrix24 echoes the full task on those endpoints. An
always-on `description` would bill the agent for a body it had just
written, on every mutation.

The nested `group` / `creator` objects Bitrix24 adds unbidden next to
`groupId` / `createdBy` stay dropped — they carry member counts, avatar
URLs and work positions, which is a lot of tokens nobody asked for.

Verified against a live portal: with `description` in the select the body
comes back (764 chars, `descriptionInBbcode: true`); without it the
response is unchanged. +9 unit tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[agent-feedback/issue] bitrix24_list_tasks ignores 'description' (and other non-default fields) in select

1 participant