feat(tools): add attachment download tools#83
Conversation
… requests Add 6 new tools to list and download attachments: - get_issue_attachments / get_issue_attachment - get_wiki_attachments / get_wiki_attachment - get_pull_request_attachments / get_pull_request_attachment List tools return attachment metadata (id, name, size, etc.). Download tools return base64-encoded file content — images are returned as MCP image content type, other files as embedded resources. Also extends Toolset type with optional `dynamicTools` field to support tools that return custom CallToolResult (needed for binary file content). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds MCP tooling to list and download Backlog attachments (issues, wiki pages, pull requests), including utilities for stream-to-base64 conversion and MIME-type/content shaping, and extends tool registration to support dynamic (binary-returning) tools.
Changes:
- Introduces attachment listing tools for issues, wiki pages, and pull requests.
- Introduces attachment download tools that return base64 content as MCP
image(inline) orresource(blob) based on MIME type. - Extends toolset typing and registration to support mixed static + dynamic tool definitions.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/streamToBase64.ts | New helper to convert Node/Web streams (or strings) to base64 for downloads. |
| src/utils/streamToBase64.test.ts | Unit tests for stream/string base64 conversion behavior. |
| src/utils/getMimeType.ts | New filename-extension → MIME type utility. |
| src/utils/getMimeType.test.ts | Unit tests for MIME type detection. |
| src/utils/buildFileContent.ts | New helper to format downloaded files into MCP image or resource content. |
| src/types/toolsets.ts | Extends Toolset to optionally include dynamicTools. |
| src/tools/tools.ts | Wires new attachment tools into issue, wiki, and git toolsets. |
| src/tools/getWikiAttachments.ts | Tool to list wiki attachments. |
| src/tools/getWikiAttachments.test.ts | Unit tests for wiki attachment listing. |
| src/tools/getWikiAttachment.ts | Dynamic tool to download a wiki attachment and return MCP content. |
| src/tools/getWikiAttachment.test.ts | Unit tests for wiki attachment download and filename decoding behavior. |
| src/tools/getPullRequestAttachments.ts | Tool to list pull request attachments. |
| src/tools/getPullRequestAttachments.test.ts | Unit tests for pull request attachment listing. |
| src/tools/getPullRequestAttachment.ts | Dynamic tool to download a pull request attachment and return MCP content. |
| src/tools/getPullRequestAttachment.test.ts | Unit tests for pull request attachment download and error path. |
| src/tools/getIssueAttachments.ts | Tool to list issue attachments. |
| src/tools/getIssueAttachments.test.ts | Unit tests for issue attachment listing. |
| src/tools/getIssueAttachment.ts | Dynamic tool to download an issue attachment and return MCP content. |
| src/tools/getIssueAttachment.test.ts | Unit tests for issue attachment download, decoding, and error path. |
| src/registerTools.ts | Registers dynamicTools in enabled toolsets using direct handlers. |
| src/registerTools.test.ts | Updates tool registration count assertions to include dynamicTools. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@nguyenthe-hien But Can you run |
This comment was marked as outdated.
This comment was marked as outdated.
|
@nguyenthe-hien I wanna ask you that when you wanna get attachments via mcp server? |
This comment was marked as outdated.
This comment was marked as outdated.
…ling - Add transferIssueAttachment tool to copy attachments between issues - Extend getIssueAttachment, getWikiAttachment, getPullRequestAttachment with inline base64 support - Refactor buildAttachmentResult utility with improved MIME detection and test coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@nguyenthe-hien |
|
I reproduced the lint failure locally and prepared a small fix branch here: https://github.com/alex-pythonista/backlog-mcp-server/tree/fix/pr-83-lint Commit:
What it changes:
Local verification passed:
Since I do not have permission to push to this PR's source branch directly, the author can cherry-pick |
|
@alex-pythonista I’ve applied your code and it works well. Thanks! |
Thank you. Nice work btw. I needed this PR for my workflow. |
|
@nguyenthe-hien @alex-pythonista |
|
@katayama8000 @nguyenthe-hien — proposing a way to slice this up. The diff has natural seams along infrastructure → list tools → download tools → transfer tool, since each layer depends on the previous. Suggested split into 4 sequential PRs: PR 1 — Infrastructure: dynamic tools + utilities (~600 LOC)
PR 2 — List tools (~240 LOC, depends on PR 1)
PR 3 — Download tools (~1,100 LOC, depends on PR 1)
PR 4 — Transfer tool + README (~700 LOC, depends on PR 3)
@nguyenthe-hien if you'd prefer, I'm happy to open PRs 1–4 from my fork using the existing commits on this branch — just let me know. |
|
@katayama8000 @alex-pythonista Per @katayama8000's request, I've split this PR into 4 smaller, sequential PRs:
How they relateAll 4 branches base on
Status
This PR (#83) will be closed once #117 is merged. Please review the new PRs instead. |
Summary
transfer_issue_attachmenttool to copy attachments between issuesget_issue_attachments,get_wiki_attachments,get_pull_request_attachments): return attachment metadata (id, name, size, createdUser, etc.)get_issue_attachment,get_wiki_attachment,get_pull_request_attachment): download and return file content as base64-encoded data with MIME type detectionimagecontent type (inline rendering)resourcecontent type (embedded blob)transfer_issue_attachment): download an attachment from one issue and upload it to anotherMotivation
The MCP server could reference attachment IDs when creating/updating issues, but had no way to list, download, or transfer existing attachments. This made it impossible for MCP clients to:
This PR uses existing
backlog-jsmethods (getIssueAttachments,getIssueAttachment,getWikisAttachments,getWikiAttachment,getPullRequestAttachments,getPullRequestAttachment,postIssueAttachment) which were available in the library but not exposed as MCP tools.Implementation
ToolDefinitionpattern (JSON output with field picking support)DynamicToolDefinitionpattern to return customCallToolResultwith binary contentToolsettype with optionaldynamicToolsfield to support mixed tool types within the same toolsetregisterTools()now also registersdynamicToolsusing direct handler (no field picking/token limit for binary content)streamToBase64,getMimeType,buildAttachmentResultwith improved MIME detection and base64 encodingNew tools
issueget_issue_attachmentsissueget_issue_attachmentissuetransfer_issue_attachmentwikiget_wiki_attachmentswikiget_wiki_attachmentgitget_pull_request_attachmentsgitget_pull_request_attachmentTest plan
npm test)npx tsc --noEmit)npm run lint)