Skip to content

Truncate card descriptions in get_cards_by_list_id#67

Open
louisabraham wants to merge 2 commits intodelorenj:mainfrom
louisabraham:fix/cards-list-preview
Open

Truncate card descriptions in get_cards_by_list_id#67
louisabraham wants to merge 2 commits intodelorenj:mainfrom
louisabraham:fix/cards-list-preview

Conversation

@louisabraham
Copy link
Copy Markdown

Summary

  • get_cards_by_list_id can return very large responses when cards have long descriptions, which wastes context window for LLM consumers
  • Card descriptions are now truncated to 200 characters in list responses
  • If total response still exceeds 50KB, descriptions are omitted entirely
  • Both cases append a notice directing users to get_card for full details

Behavior

Scenario Before After
Cards with short descriptions Full response No change
Cards with long descriptions Full descriptions (unbounded) Truncated to 200 chars + notice
Many cards with content > 50KB total Huge response Descriptions dropped + notice

Test plan

  • Build passes
  • Verified against live board with cards
  • Test with board containing cards with very long descriptions

🤖 Generated with Claude Code

When listing cards, descriptions are now capped at 200 characters
to prevent oversized responses. If the total response still exceeds
50KB, descriptions are omitted entirely. Both cases append a notice
directing users to get_card for full details.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 11, 2026 01:42
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @louisabraham, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces significant improvements to the get_cards_by_list_id tool by optimizing its response payload. The primary goal is to prevent excessively large responses, which can be problematic for consumers like Large Language Models. This is achieved by intelligently managing the length of card descriptions, ensuring that essential information is conveyed efficiently while providing clear guidance on how to retrieve complete details when needed.

Highlights

  • Response Size Optimization: Implemented logic within the get_cards_by_list_id tool to manage response size, primarily for LLM consumers, by truncating or omitting card descriptions.
  • Description Truncation: Card descriptions in get_cards_by_list_id responses are now truncated to 200 characters if they exceed this limit, with an ellipsis appended.
  • Total Response Size Limit: If the total response from get_cards_by_list_id (after description truncation) still exceeds 50KB, all card descriptions are entirely omitted from the response.
  • User Guidance Notices: Notices are appended to the response from get_cards_by_list_id when descriptions are truncated or omitted, directing users to get_card for full details.
  • Tool Description Update: The description for the get_cards_by_list_id tool has been updated to reflect that it returns a preview of cards with truncated descriptions and advises using get_card for full details.
Changelog
  • src/index.ts
    • Added CARD_LIST_DESC_LIMIT (200) and CARD_LIST_TOTAL_CHAR_LIMIT (50000) constants to TrelloServer.
    • Updated the description property for the get_cards_by_list_id tool to clarify its behavior regarding truncated descriptions.
    • Implemented logic within the get_cards_by_list_id handler to truncate card descriptions exceeding CARD_LIST_DESC_LIMIT.
    • Added a check to get_cards_by_list_id to omit all descriptions if the JSON stringified result exceeds CARD_LIST_TOTAL_CHAR_LIMIT.
    • Appended informational notices to the get_cards_by_list_id response indicating when descriptions were truncated or omitted.
Activity
  • The author has confirmed that the build passes.
  • The changes have been verified against a live Trello board containing cards.
  • Testing with a board containing cards with very long descriptions is pending.
  • The pull request was generated using Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a useful feature to manage large response sizes from the get_cards_by_list_id tool by truncating or omitting card descriptions. The implementation is solid, introducing constants for limits and updating the tool's description. I've suggested one refactoring to improve the efficiency and readability of the truncation logic by avoiding an unnecessary array iteration and using clearer variable names. Overall, this is a good improvement.

Comment on lines +82 to +105
// Truncate descriptions to keep response size manageable
const previews = cards.map(card => ({
...card,
desc:
card.desc && card.desc.length > descLimit
? card.desc.slice(0, descLimit) + '...'
: card.desc,
}));

let result = JSON.stringify(previews, null, 2);
let truncated = false;

// If total response is still too large, drop descriptions entirely
if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
const minimal = cards.map(({ desc, ...rest }) => rest);
result = JSON.stringify(minimal, null, 2);
truncated = true;
}

if (truncated) {
result += '\n\n(Descriptions omitted due to response size. Use get_card with a specific cardId for full details.)';
} else if (cards.some(c => c.desc && c.desc.length > descLimit)) {
result += '\n\n(Some descriptions were truncated. Use get_card with a specific cardId for full details.)';
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current logic for checking if descriptions were truncated involves an extra iteration over the cards array using cards.some(...). This can be made more efficient by tracking whether truncation occurred during the initial map operation. This refactoring also introduces clearer variable names (descriptionsOmitted, anyTruncated) to improve readability and avoid the ambiguity of the original truncated variable.

          // Truncate descriptions to keep response size manageable
          let anyTruncated = false;
          const previews = cards.map(card => {
            if (card.desc && card.desc.length > descLimit) {
              anyTruncated = true;
              return {
                ...card,
                desc: card.desc.slice(0, descLimit) + '...',
              };
            }
            return card;
          });

          let result = JSON.stringify(previews, null, 2);
          let descriptionsOmitted = false;

          // If total response is still too large, drop descriptions entirely
          if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
            const minimal = cards.map(({ desc, ...rest }) => rest);
            result = JSON.stringify(minimal, null, 2);
            descriptionsOmitted = true;
          }

          if (descriptionsOmitted) {
            result += '\n\n(Descriptions omitted due to response size. Use get_card with a specific cardId for full details.)';
          } else if (anyTruncated) {
            result += '\n\n(Some descriptions were truncated. Use get_card with a specific cardId for full details.)';
          }

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the get_cards_by_list_id MCP tool response to be more LLM-friendly by limiting how much card description text is returned, reducing oversized responses that waste context window.

Changes:

  • Truncate each card’s desc to a short preview in get_cards_by_list_id responses.
  • If the overall serialized response is still large, omit descriptions entirely and append a user-facing notice.
  • Update the tool description to clarify preview behavior and direct users to get_card for full details.

src/index.ts Outdated
Comment on lines +83 to +90
const previews = cards.map(card => ({
...card,
desc:
card.desc && card.desc.length > descLimit
? card.desc.slice(0, descLimit) + '...'
: card.desc,
}));

Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The truncation adds '...' after slicing to descLimit, so the resulting desc can exceed the stated 200-character limit (e.g., 203 chars). Consider slicing to descLimit - 3 (or only appending ellipsis when it fits) so the final preview length stays within the configured limit.

Suggested change
const previews = cards.map(card => ({
...card,
desc:
card.desc && card.desc.length > descLimit
? card.desc.slice(0, descLimit) + '...'
: card.desc,
}));
const previews = cards.map(card => {
const ellipsis = '...';
return {
...card,
desc:
card.desc && card.desc.length > descLimit
? descLimit > ellipsis.length
? card.desc.slice(0, descLimit - ellipsis.length) + ellipsis
: card.desc.slice(0, descLimit)
: card.desc,
};
});

Copilot uses AI. Check for mistakes.
src/index.ts Outdated
Comment on lines +101 to +105
if (truncated) {
result += '\n\n(Descriptions omitted due to response size. Use get_card with a specific cardId for full details.)';
} else if (cards.some(c => c.desc && c.desc.length > descLimit)) {
result += '\n\n(Some descriptions were truncated. Use get_card with a specific cardId for full details.)';
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

result is JSON, but in the truncated/omitted cases you append a human notice string, making the output no longer valid JSON and changing the output format depending on data. Consider keeping the JSON parseable by returning a structured JSON object (e.g., { cards, notice }) or by returning the notice as a separate content item so the JSON portion remains intact.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +99
// If total response is still too large, drop descriptions entirely
if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
const minimal = cards.map(({ desc, ...rest }) => rest);
result = JSON.stringify(minimal, null, 2);
truncated = true;
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The 50KB cutoff is implemented using result.length, which counts UTF-16 code units rather than bytes; with non-ASCII descriptions the response can exceed 50KB in bytes without triggering the omit behavior. If the intent is a byte-size limit, consider measuring Buffer.byteLength(result, 'utf8') (or equivalent in Bun) and applying the threshold on that value.

Copilot uses AI. Check for mistakes.
src/index.ts Outdated
Comment on lines +92 to +101
let truncated = false;

// If total response is still too large, drop descriptions entirely
if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
const minimal = cards.map(({ desc, ...rest }) => rest);
result = JSON.stringify(minimal, null, 2);
truncated = true;
}

if (truncated) {
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The boolean truncated is set only when descriptions are omitted entirely, not when they are truncated to a preview. Renaming it (e.g., descriptionsOmitted / omittedDescriptions) would make the control flow and messages easier to follow.

Suggested change
let truncated = false;
// If total response is still too large, drop descriptions entirely
if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
const minimal = cards.map(({ desc, ...rest }) => rest);
result = JSON.stringify(minimal, null, 2);
truncated = true;
}
if (truncated) {
let descriptionsOmitted = false;
// If total response is still too large, drop descriptions entirely
if (result.length > TrelloServer.CARD_LIST_TOTAL_CHAR_LIMIT) {
const minimal = cards.map(({ desc, ...rest }) => rest);
result = JSON.stringify(minimal, null, 2);
descriptionsOmitted = true;
}
if (descriptionsOmitted) {

Copilot uses AI. Check for mistakes.
@louisabraham
Copy link
Copy Markdown
Author

Thanks for the reviews! Addressed the feedback in https://github.com/louisabraham/mcp-server-trello/tree/anthony:

Fixed:

  • Ellipsis no longer exceeds desc limit: now slices to descLimit - 3 before appending ...
  • Truncation tracked during map (no extra .some() iteration), renamed truncateddescriptionsOmitted and added anyTruncated
  • Notice returned as a separate content item instead of appending to JSON string — keeps the JSON portion parseable

Not changed:

  • result.length vs Buffer.byteLength: The 50KB threshold is approximate and meant to catch extreme cases. UTF-16 length is close enough and avoids the overhead of byte counting on every response.

- Track truncation flag during the map pass (avoids extra iteration)
- Rename truncated -> descriptionsOmitted for clarity
- Return notice as a separate content item so JSON remains parseable

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants