Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4911dbf123
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const container = result.containers.find( | ||
| (candidate) => | ||
| normalizeTrackingNumber(candidate.container_number) === number, | ||
| ); |
There was a problem hiding this comment.
Inspect all exact container matches before retracking
When /search returns multiple records for a reused container number, this selects only the first exact match even though search_container explicitly supports duplicate container numbers. If that first record belongs to a stopped shipment but a later exact match is still active, the subsequent stopped-tracking check falls through and attempts to create another tracking request rather than returning the active container. Preserve all exact matches and check them until an actively tracked record is found before deciding to retrack.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. track_container now reads every container whose number matches exactly, in search order, and returns the first one whose shipment is still tracked. It retracks only when none is tracked. The new test failed before the fix.
| const created = createdRequest(trackingRequest, { | ||
| number, | ||
| numberType: inferredNumberType, | ||
| scac: requestedScac, | ||
| }); |
There was a problem hiding this comment.
Created request details disappear
When a newly created request links to a readable container, the successful response drops tracking_request. Callers lose the request's ID and confirmed number type, despite the new tool description promising both. Include tracking_request: created alongside the container details so callers do not need another search.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/mcp/src/tools/track-container.ts
Line: 511-515
Comment:
**Created request details disappear**
When a newly created request links to a readable container, the successful response drops `tracking_request`. Callers lose the request's ID and confirmed number type, despite the new tool description promising both. Include `tracking_request: created` alongside the container details so callers do not need another search.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Fixed. The success path that also returns the linked container now includes tracking_request with its id, request_number, number_type and scac.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bd4a73ed1f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| unavailableId ??= match.id; | ||
| continue; | ||
| } | ||
| if (!containerDetails.shipment?.line_tracking_stopped_at) { |
There was a problem hiding this comment.
Treat a stopped reason as stopped tracking
When a shipment has line_tracking_stopped_reason set but line_tracking_stopped_at is absent, this condition treats the old container as actively tracked and returns it instead of creating the requested tracking request. The same module already treats either field as evidence that tracking stopped when calculating demurrage, and both fields are independently nullable in the API schema, so expose/check the reason here as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Dismissing. The backend sets the stopped reason in the same transaction as the tracking_stopped transition, and that transition stamps line_tracking_stopped_at. The API's duplicate check keys on that state. So a shipment with a reason but no stopped_at is still tracked as far as a new request is concerned, and checking the reason too would only turn this into a duplicate rejection.
| errors.some( | ||
| (entry) => | ||
| IDENTIFIER_POINTER.test(entry.source?.pointer ?? '') && | ||
| (!entry.code || IDENTIFIER_CODES.has(entry.code)), | ||
| ) |
There was a problem hiding this comment.
Preserve actionable SCAC refusal details
When the API returns code: "blank" at /data/attributes/scac for a nonblank but unsupported or unrecognized carrier—the repository's documented 422 examples use exactly that shape—this predicate classifies the response as an invalid identifier. The caller consequently receives the generic “identifier is invalid” message instead of the API's actionable explanation that the carrier is unsupported; distinguish an actually blank value from these carrier refusals or pass their detail through.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Dismissing. The API takes the JSON:API code from the validation's error type. An unknown carrier returns not_recognized and an unintegrated one returns no_integration. no_integration passes its detail through, and not_recognized tells the caller to check the SCAC. Code blank only appears when the SCAC was blank. The blank examples in openapi.json are out of date and we'll fix them separately.
| 'A new request returns the request (id, request_number, number_type, scac), not container details: ' + | ||
| 'poll list_tracking_requests for its status, then use search_container or get_shipment_details. ' + |
There was a problem hiding this comment.
Describe the linked-container success response accurately
When a newly created tracking request already contains a container relationship and that container is readable, executeTrackContainer returns the full container fields together with tracking_request and tracking_request_created: true. This description instead tells MCP clients that a new request never returns container details and instructs them to poll, which can make agents ignore the usable snapshot and issue unnecessary follow-up calls.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. The description now says container details come back only when the create response links a container, which a new request normally does not. It still tells clients to poll list_tracking_requests.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
The tool tests stub the SDK, so nothing checked that the summary the
tool builds matches what containers.route() returns from
GET /containers/{id}/map_geojson. A test now gives the real SDK client
the map_geojson fixture and asserts the request path and the route
summary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s SCAC A container prefix (MSKU, ZZQU) names the equipment owner, not the carrier. track_container passed it to createTrackingRequestFromInfer as an explicit scac, which overrode the carrier that infer_number selected (MSKU4330011 went out as MSKU instead of MAEU) and sent an invalid SCAC when infer had no prediction (ZZQU4330056 got a 422 reported as an invalid identifier). Only a caller-supplied scac now reaches the API. When neither inference nor the caller provides a carrier or number type, the tool returns a TrackContainerInputError that tells the model what to pass, instead of the old hint that formatToolError replaced with a generic message. The pending and 404 results report the SCAC the API recorded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lues The status enum offered succeeded, which the API does not recognize. Its filter[status] handler treats anything other than created, failed, or cancelled as pending, so status: succeeded silently returned pending requests. A tracking request that succeeded has status created. The enum is now pending, created, failed, and cancelled, typed against the generated filter[status] parameter so it fails to compile if the spec adds or drops a value. The descriptions say that created means the request succeeded and that each item's shipment.id (mapped from tracked_object) feeds get_shipment_details. BREAKING CHANGE: list_tracking_requests rejects status: 'succeeded'. Pass 'created' for requests that succeeded. The new 'cancelled' value selects cancelled requests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
formatToolError turned every 422 from POST /tracking_requests into "Tracking identifier X is invalid". The live run hit the account's tracking request limit and told the user the number was invalid, and the backend's duplicate, tracking_slot_limit_reached, and insufficient_credits 422s were reported the same way. track_container now parses the 422 body and classifies it by code before pointer. A duplicate returns a non-error result with the existing tracking_request id and shipment_id. Limit and credit refusals pass the API's message through. Errors that point at request_number, request_type, number, or scac with an identifier code (blank, invalid_format, not_recognized, and the like), and infer_number's bare detail with no code or pointer, say the identifier is invalid. Any other refusal, such as container_number_tracking_disabled, no_container_request_type_support, or a party that does not belong to the account, passes its detail through. search_container also dropped tracking_request search hits, so a number with a pending request was tracked again and refused as a duplicate. It now returns tracking_requests, with shipment_id on a request whose tracking was stopped, and track_container answers with a request that is still in progress (pending or awaiting_manifest, the statuses the API treats as blocking) instead of posting, and reports its real status. The API scopes its duplicate check by carrier, so when the caller names a SCAC, an in-progress request under another SCAC (or with none yet) is ignored and the new request is sent. BREAKING CHANGE: search_container's output gains a required tracking_requests array, and total_results now counts containers, shipments, and tracking requests. track_container returns a result with tracking_request_created: false and source 'duplicate' or 'search_match' for a number that is already tracked or has an in-progress request, where it used to fail with an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
track_container rejects CAIU1234567 on the ISO 6346 check digit, so the prompt's example number now uses MSKU4330011, which passes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
list_tracking_requests accepts pending, created, failed, or cancelled. created matches requests that succeeded and are still tracking; a stopped request has status tracking_stopped, which the filter cannot select. track_container needs scac when the carrier cannot be inferred and never uses the container prefix as the SCAC. It returns an existing container or in-progress (pending or awaiting_manifest) request with tracking_request_created false before it creates one. The examples use MSKU4330011, which passes the ISO 6346 check digit; CAIU1234567 fails it and never reaches the API. The overview examples drop the request_type argument the tool does not accept and use number instead of the deprecated containerNumber alias. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MCP guide's tool table listed filters and request_type, which the strict input schema rejects, and left out request_number and scac. Match the server.ts schema and docs/mcp/home.mdx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MCP guide and TOOLS_OVERVIEW still showed status, port, carrier, updated_after, and a comma-separated include string. Both tools use strict input schemas, so those calls fail validation. The guide table now lists the inputs the schemas accept, and the examples use voyage_status, current_status, pod_code, shipping_line_scac, pickup_lfd, and an include array. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The example response used camelCase keys the tool never emits and had no tracking_requests array. Show the real snake_case output, add pending and failed tracking requests, say that only a request whose tracking was stopped carries shipment_id, and say total_results counts all three result types. TOOLS_OVERVIEW.md's Returns line says the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…i in the MCP guides The MCP guide's tools table, TOOLS_OVERVIEW.md, and the package README left out tools the server registers. Add summarize_containers, list_parties, and search_docs to each, add whoami to the package README, which now counts all 14 tools, and add a search_docs section to the MCP tools reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…container A new request was described by the submitted number and the locally inferred type, without the request's id. Every path that creates a request now returns tracking_request with the id, request_number, number_type, and scac the API sent back, falling back to the submitted values for an attribute the response leaves out. That includes the path that also returns the linked container's details. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… longer tracked track_container returned early on any container search hit for the number. Search returns every container with a shipment, including one whose shipment stopped tracking, and the API accepts a new request for such a container because container numbers are reused on later voyages. It also treated a lone search hit with a different number as a match, although search matches substrings and reference numbers. track_container now checks for an in-progress tracking request first. It then reads every container whose number matches exactly, in search order, because a reused number can match a stopped container and a tracked one. It returns the first whose shipment has no line_tracking_stopped_at. Otherwise it sends the request and lets the API's duplicate check decide. get_container's shipment summary now includes line_tracking_stopped_at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…MCP guide The get_container and get_container_transport_events examples showed camelCase fields that the tools never return. Both examples now hold actual tool output with snake_case keys, and track_container says that an existing container comes back in the get_container shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The example passed status and carrier to client.shipments.list, which the SDK rejects before sending a request, and said the call was not available through MCP although list_shipments is an MCP tool. It now filters by voyage_status and pod_code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…acked container The tool description promised detailed container information after it creates a tracking request. The create response carries the request, not a container, so a new request returns its id, request_number, number_type, and scac. The description now says container details come back only for a container that is still being tracked, and tells the caller to poll list_tracking_requests and then use search_container or get_shipment_details. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the MCP guide The Raw vs Mapped example used attributes.container_number and a mapped containerNumber and availableForPickup at the top level. The API serializes the container number as number, and mapContainer returns number and nests availableForPickup under location. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why
Live runs found that track_container sent the container owner prefix as the SCAC. They also found that it hid why a request was not created, and that list_tracking_requests accepted statuses the API rejects. The MCP docs also showed fields the tools never return.
What changed
Scope
packages/mcp,docs/mcp, and the MCP in-depth guide. #418's summarize_containers behavior is unchanged.Tradeoffs
track_container no longer returns an error for duplicates or pending requests. It returns
tracking_request_created: falsewith the reason, so agents can tell "already tracked" from a failure.Blast Radius
Breaking changes for MCP clients:
succeeded. Usecreated.tracking_requestsarray.Verification
vp run checkandvp run testpass at every commit and at the tip.Base: #439.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.The PR appears safe to merge, with a non-blocking inconsistency in the details returned after creating a request.
Fix with agent prompt
Summary
This PR corrects MCP carrier selection, tracking status filters, duplicate responses, and tracking-request search results.
Known verification failure:
dodejaidentified DEV-13514, a backend 422 shape, as the one failure in the live MCP checks.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD A[track_container] --> B[Search the account] B --> C{In-progress request?} C -->|Yes| D[Return existing request] C -->|No| E{Exact container still tracked?} E -->|Yes| F[Return container details] E -->|No| G[Infer carrier and create request] G --> H{API result} H -->|Duplicate| I[Return existing request ID] H -->|Refused| J[Explain the refusal] H -->|Created| K{Linked container readable?} K -->|No| L[Return created request details] K -->|Yes| M[Return container details without request details]Reviews (1) · Last reviewed commit: "docs: show the container number and pick..." · Reviewed by Greptile