# feat\(mcp\): expose attachment upload and send · PR \#10564 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10564)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: agents/mcp-thin/attachments

Target branch: agents/mcp-thin/projects

Head commit: 71fa7c96ab7422920fedd57083b38e9992d29b42

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/10564)

[Commits](https://git.cafe/pingdotgg/t3code/pull/10564/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/10564/diffs?format=markdown)

## Description

---

Part 14/16 of the [shared-core and MCP stack](https://github.com/pingdotgg/t3code/stacks/10582). Based on [#10563](https://github.com/pingdotgg/t3code/pull/10563). Next: [#10565](https://github.com/pingdotgg/t3code/pull/10565).

Expose signed upload preparation, pending-upload discard and an attachment-aware send tool using the existing upload, claim and thread-send services.

t3_thread_send remains unchanged. The new t3_thread_send_attachments checks target ownership and permission ceilings. Each call is a new message; claimed files are retained when dispatch outcome is uncertain. Provider support stays in adapters, and no keyed replay protocol is added.

Attachment claiming and send execution now go through ThreadMessageIntake, shared with RPC. MCP retains only credential/target checks, canonical owned attachment references, and response mapping.

MCP-only rebuild of [#8700](https://github.com/pingdotgg/t3code/pull/8700), preserving attribution to Julius Marminge's original work. Original branches remain available for separate service follow-ups.

Validation: The composed stack passes 94 tests across 12 focused files, including shared core MCP and real MCP/V2 integration, attachment intake, project RPC/service contracts, and client model command selection. Server/contracts/shared/client-runtime typechecks and targeted format/lint/diff checks pass. New behavior coverage lives with the shared operation; no per-tool mock suite was added. Current-head CI is shown below.

Layer size: 5 files, +193/-0. No domain-service production implementation or documentation files change in this MCP layer.

Prepared with Codex in the OpenAI agent runtime.

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Expose attachment upload, discard, and send as MCP tools
> - Adds the `AttachmentToolkit` with three destructive tools: `t3_attachment_prepare_upload`, `t3_attachment_discard`, and `t3_thread_send_attachments`
> - `t3_thread_send_attachments` resolves attachment references against the target thread's stored attachments, rejects archived threads, and sends a new MCP-originated agent message in automatic mode, returning message and run identifiers
> - `resolveAttachmentReferences` keeps pending-upload references as-is, replaces known IDs with stored metadata, and fails unknown IDs with an invalid-request MCP failure
> - Upload-service errors map to unavailable failures; dispatch errors map to orchestration or unavailable failures depending on type
> - Behavioral Change: `t3_thread_send_attachments` accepts 1–8 attachments and an optional message capped at 120,000 characters; references that are neither pending uploads nor in the target thread's stored set are rejected
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 71fa7c9.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
