Skip to content

feat(mcp): set_party_role and set_custom_field tools - #425

Open
alosec wants to merge 3 commits into
mainfrom
feat/mcp-write-tools
Open

alosec wants to merge 3 commits into
mainfrom
feat/mcp-write-tools

Conversation

@alosec

@alosec alosec commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

ARCA asked Ask T49 to "set drayage carrier to Manzo Transport" for the containers on screen, and to work with a "Sales Rep" custom field (Braintrust, 10/6); the agent had no way to change records. This adds the first two record edits to the MCP (DEV-13423).

Tools

  • set_party_role: { container_ids? | shipment_ids?, role, party_id, action: 'add' | 'remove' }. Containers take only pickup_dray_carrier; shipments take every party role.
  • set_custom_field: { entity: 'container' | 'shipment', ids, api_slug, value }. null clears the field.

Both take 1 to 50 records and return { updated, unchanged, failed, summary }. Each record's current value is read first, so a repeat call reports unchanged, and one failing record doesn't stop the rest. Both are marked as non-read-only, idempotent, non-destructive writes.

They use the existing Rails endpoints: GET/POST/DELETE /v2/{containers,shipments}/:id/party_roles, POST /v2/{…}/:id/custom_fields (Rails upserts by api_slug), and DELETE /v2/{…}/:id/custom_fields/:api_slug. Rails enforces permissions. update_pathway isn't sent: the t49 side sets attribution from the request's auth channel.

For review: these tools are also listed in the public Claude and ChatGPT connector manifests (claude-connector-submission.json, chatgpt-app-submission.json). The tests require those manifests to match the live tools. In Ask T49, approval before each call happens on the agent side.

Changes

sdks/typescript-sdk/src/
├── client/managers/record-writes.ts   C  party role list/add/remove, clear custom field
├── client/managers/containers.ts      M  partyRoles, addPartyRole, removePartyRole, clearCustomField
├── client/managers/shipments.ts       M  same
├── client/managers/index.ts           M  export PartyRoleAssignment
└── client.record-writes.test.ts       C
packages/mcp/src/
├── tools/record-writes.ts             C  set_party_role, set_custom_field
├── tools/record-writes.test.ts        C
├── server.ts                          M  register both; server instructions name the writes
├── annotations.test.ts                M  write-tool list
├── mcp.test.ts                        M  tool count, legacy args
└── protocol-compat.test.ts            M  tool count, write annotations
chatgpt-app-submission.json            M  two tools
claude-connector-submission.json       M  two tools
docs/mcp/home.mdx                      M  tool reference
docs/sdk/reference/**                  M  regenerated

Testing

  • npm test --workspace @terminal49/mcp: 23 files, 402 tests pass.
  • npm test --workspace @terminal49/sdk: 251 pass (1 skipped).
  • npm run check: clean.
  • Not yet run against a live API.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

RetriggerConfidence Score: 3/5

Fix the bulk-write time budget and multi-select field support before merging.

Fix All in CodexFindings

  1. P1 Bulk edits lose their result ▶
  2. P1 Multi-select fields cannot be changed ▶
Fix with agent prompt
### Issue 1
packages/mcp/src/tools/record-writes.ts:140-152
A 50-record call needs up to 100 API requests, with only five records running at once. If each read and write takes two seconds, the call takes about 40 seconds, but the hosted endpoint stops after 30 seconds. Some records will already be changed when the caller loses the response.

Give `applyEach` a call-wide time budget, stop starting records before it runs out, and return which records were completed or not attempted.

### Issue 2
packages/mcp/src/tools/record-writes.ts:80-81
`set_custom_field` rejects the array needed to set a multi-select field. The API supports `enum_multi` fields whose values are `string[]`, but this union rejects arrays before any record is read or changed. Accept arrays of strings and add a test that sets and repeats a multi-select value.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds set_party_role and set_custom_field to MCP, backed by new SDK helpers.

  • Party roles can now be attached to or removed from records.
  • Custom fields can now be set or cleared on records.

Approval before each call remains on the agent side, as author alosec explicitly states.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[MCP write call] --> B[Check arguments]
  B --> C[Take up to 50 unique records]
  C --> D[Run five records at once]
  D --> E[Read current value]
  E --> F{Already matches?}
  F -->|Yes| G[Record unchanged]
  F -->|No| H[Send write through SDK]
  H --> I[Record updated or failed]
  G --> J[Wait for all records]
  I --> J
  J --> K[Return results and summary]
Loading

Reviews (1) · Last reviewed commit: "docs(mcp): document set_party_role and s..." · Reviewed by Greptile

alosec and others added 3 commits October 13, 2026 17:35
…hipments

Adds partyRoles, addPartyRole, removePartyRole and clearCustomField to the
container and shipment managers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lets an agent assign a party (such as the drayage carrier) or set an account
custom field on up to 50 containers or shipments, reporting per-record
updated, unchanged and failed results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
terminal49 🟢 Ready View Preview Oct 13, 2026, 10:36 PM

@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
api Ready Ready Preview Oct 13, 2026 10:36pm UTC

Request Review

Comment on lines +140 to +152
const workers = Array.from(
{ length: Math.min(CONCURRENCY, queue.length) },
async () => {
for (let id = queue.shift(); id; id = queue.shift()) {
try {
result[await change(id)].push(id);
} catch (error) {
result.failed.push({ id, error: describeError(error) });
}
}
},
);
await Promise.all(workers);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Bulk edits lose their result

A 50-record call needs up to 100 API requests, with only five records running at once. If each read and write takes two seconds, the call takes about 40 seconds, but the hosted endpoint stops after 30 seconds. Some records will already be changed when the caller loses the response.

Give applyEach a call-wide time budget, stop starting records before it runs out, and return which records were completed or not attempted.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/mcp/src/tools/record-writes.ts
Line: 140-152

Comment:
**Bulk edits lose their result**

A 50-record call needs up to 100 API requests, with only five records running at once. If each read and write takes two seconds, the call takes about 40 seconds, but the hosted endpoint stops after 30 seconds. Some records will already be changed when the caller loses the response.

Give `applyEach` a call-wide time budget, stop starting records before it runs out, and return which records were completed or not attempted.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment on lines +80 to +81
value: z
.union([z.string().max(1000), z.number(), z.boolean(), z.null()])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Multi-select fields cannot be changed

set_custom_field rejects the array needed to set a multi-select field. The API supports enum_multi fields whose values are string[], but this union rejects arrays before any record is read or changed. Accept arrays of strings and add a test that sets and repeats a multi-select value.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/mcp/src/tools/record-writes.ts
Line: 80-81

Comment:
**Multi-select fields cannot be changed**

`set_custom_field` rejects the array needed to set a multi-select field. The API supports `enum_multi` fields whose values are `string[]`, but this union rejects arrays before any record is read or changed. Accept arrays of strings and add a test that sets and repeats a multi-select value.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

@sinankeskin sinankeskin left a comment

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.

Some comments but no blocker

};
}

export function mapPartyRoles(doc: any): PartyRoleAssignment[] {

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.

What's doc here?

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.

Just an idea. Maybe instead of writing your own JSON_API compliant client you might wanna use one of these: https://jsonapi.org/implementations/#server-libraries-node-js

This branch was successfully deployed

2 active deployments
Preview — b2321806 Deployed Oct 13, 2026 by vercel[bot]
staging - docs — b2321806 Deployed Oct 13, 2026 by mintlify[bot]
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