-
Notifications
You must be signed in to change notification settings - Fork 0
fix(mcp): pinning a suggested contact is answered, not retried (product#4050) #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,18 @@ import type { LeadbayClient } from "../client.js"; | |
| import type { Tool, ToolContext } from "../types.js"; | ||
| import { leadbay_pin_contact as PIN_CONTACT_DESCRIPTION } from "../tool-descriptions.generated.js"; | ||
|
|
||
| /** | ||
| * Replaces the client's generic 404 hint on the pin/unpin endpoints. Shared | ||
| * with unpin-contact.ts so both answer a NOT_FOUND the same way. | ||
| */ | ||
| export const NOT_PINNABLE_HINT = | ||
| "This contact id is not in your organization's contact directory, so it cannot be pinned or unpinned. " + | ||
| "Almost always it is a `source: \"paid\"` enrichment candidate from leadbay_research_lead_by_id's `candidates` list; " + | ||
| "only `source: \"org\"` contacts are pinnable. The id is not wrong and the tool is not broken, so do NOT retry it. " + | ||
| "To act on this person, enrich them by job title with leadbay_enrich_titles, or add them with leadbay_add_contact — " + | ||
| "either produces a NEW org contact with a different id, which is pinnable. " + | ||
| "Note that pinning does not decide who gets enriched; enrichment selects people by job title."; | ||
|
|
||
| interface PinContactParams { | ||
| // The contact's own UUID (the `id` on a contact object) — NOT the lead id. | ||
| contact_id: string; | ||
|
|
@@ -46,7 +58,17 @@ export const pinContact: Tool<PinContactParams, PinContactResult> = { | |
| params: PinContactParams, | ||
| _ctx?: ToolContext, | ||
| ): Promise<PinContactResult> => { | ||
| await client.requestVoid("POST", `/contacts/${params.contact_id}/pin`); | ||
| try { | ||
| await client.requestVoid("POST", `/contacts/${params.contact_id}/pin`); | ||
| } catch (e: any) { | ||
| // The generic 404 hint is "Verify the ID is correct", which for this | ||
| // endpoint is wrong advice: the id IS correct, it is just a paid | ||
| // candidate rather than an org contact. Agents read that hint as "look | ||
| // it up again and retry" and hammer the endpoint (43 of 48 production | ||
| // pin calls in the 180 days to 2026-09-02 were this 404). | ||
| if (e?.code === "NOT_FOUND") throw { ...e, hint: NOT_PINNABLE_HINT }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| throw e; | ||
| } | ||
| return { pinned: true, contact_id: params.contact_id, action: "pinned" }; | ||
| }, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shaping site gets the same
pinned/pinned_by_aipassthrough asresearch-lead-by-id.tsandget-contacts.ts, but unlike those two, it has no test coverage here —contact-pin-state-passthrough.test.tsonly exercisesresearch_lead_by_idandget_contacts. Since existing test files can't be modified, this needs a new test (or an addition to the new pin-state test file) coveringget_lead_profile.