Repository navigation
Description
What happened? / 发生了什么?
In a Bot's settings → 分享 → Share with a friend, clicking Share next to an existing friend fails and the raw MCP error is shown under the row:
MCP error -32602: Input validation error: Invalid arguments for tool grant_bot_to_friend: Invalid input: expected string, received undefined at friend_owner_id
Nothing is shared; People with access stays empty. Seen on a re-share after Revoke (Scout was shared with Lin, revoked, then Share clicked again for Lin).
This is not #563: there the server had no grant_bot_to_friend tool at all (Tool grant_bot_to_friend not found). Here the tool exists (local Bot Social master @ 58afc9f, which added it for Birfy/bot-social#34) and rejects FlyBot's arguments.
Expected: Share grants the Bot to that friend (People with access shows them), or, if the server cannot identify the friend, a plain-language error, never a raw MCP error -32602 string.
Likely cause (code reading, origin/main 645a291)
A contract mismatch between FlyBot (#500 / PR #516) and Bot Social's grant_bot_to_friend:
- FlyBot only sends
friend_owner_idwhen it has one, and otherwise sends onlyfriend_home:plugins/social/src/mcp-client.js:438-465(grantBotToFriend:friend_owner_idonly iffriendOwnerId, plusfriend_home).plugins/social/src/social.js:2262-2276(social/share-with-friend:oid = friendOwnerId || ownerId, often undefined).- The friend list's
ownerIdcomes frompeerViewatplugins/social/src/social.js:1854(item.peer?.owner_id || item.friend_owner_id || item.owner_id) and is copied atsocial.js:2226; the client passes it atplugins/social/client.js:2130-2134.
- Bot Social never returns an owner id for a friend, so
ownerIdis always undefined:list_friends→listRelationshipsbuildspeerwithpublicBot()(Birfy/bot-socialsrc/platform.ts:1419-1434,publicBotatplatform.ts:108-111returnsbot_id, handle, display_name, owner_display_name, owner_verified— noowner_id). - Bot Social's tool schema requires
friend_owner_idand does not knowfriend_home:src/owner-mcp.ts:234-236(inputSchema: { bot_id: z.string(), friend_owner_id: z.string() }),src/platform.ts:1060(friend_owner_id required). - The REST fallback path also does not match: FlyBot posts
/v1/bots/:id/grants/to-friend(mcp-client.js:458), the server route isPOST /v1/bots/:id/grantswithfriend_owner_id(src/server.ts:75). The fallback only runs on unknown-tool anyway (isUnknownTool,mcp-client.js:155-166), so a validation error goes straight to the UI. - The plugin tests mock a server that accepts
friend_homeand sendsowner_idon the peer (plugins/social/test/social.test.js:8295,:8351,:8381), which the real server does neither — the LESSONS 2026-10-18 "mock answer must have the shape the real server sends" pattern.
The root cause is partly on the Bot Social side (no owner id on list_friends peers; no friend_home input). Filed here per the rule that routines do not open issues on other repos; the owner decides whether a companion change goes to Bot Social.
Change scope (suggested, needs owner decision because it is the sharing surface)
Either (a) Bot Social exposes the friend's owner id on list_friends peers (or accepts friend_home / the friend's handle in grant_bot_to_friend) and FlyBot sends it, or (b) FlyBot resolves the owner id another way before calling. In both cases: align the REST fallback route with the server, map a -32602 validation error to a readable message, and replace the mock with the real server's answer shape (naming the Bot Social commit).
Screenshot / 截图
Not attached (kept local). Captured on the recording box as /workspace/slides/flybot-intro-834wrk/issue-evidence/share-with-friend-error.png: Scout's settings, "Share with a friend · Lin @lin.home · Share", the red error above. Also noted in the demo-5c caveat of the demo video index.
Steps to reproduce / 复现步骤
- Run two homes (A = Danyang, B = Lin) against Bot Social
master@58afc9f; make them friends via an invite link. - On A, open a Bot (Scout) → settings → 分享 → Share with a friend → Share for Lin. (In the recording, Scout had been shared and then Revoked first.)
- The row shows
MCP error -32602: … grant_bot_to_friend … expected string, received undefined at friend_owner_id.
Diagnostics / 诊断信息
FlyBot main @ 4f6a53d (code paths unchanged on 645a291), @deepseek-ai/dsh 0.2.0-rc.2 (dsh web), @flybot/social + @flybot/tree linked from the checkout, local Bot Social Birfy/bot-social master @ 58afc9f with a throwaway data dir, mock model core/dev/mock-llm.mjs, headless Chrome, zh-CN, 1440×900. Found while recording demos, not by the self-test routine.
Privacy / 隐私
- This report has no API keys, tokens or personal data.
Activity
Birfy commentedon Oct 21, 2026
Triaged (maintenance round, 2026-10-21): a real
bug, butneeds-infobefore it can beagent-ready— the failing validation is on Bot Social's side (grant_bot_to_friendrequiresfriend_owner_id; FlyBot only ever hasfriend_homefor a friend, because Bot Social's friend list does not return an owner id).So the fix is either server-side in
Birfy/bot-social(accept the friend byfriend_home/ returnowner_id) — which then needs a deploy decision — or FlyBot sends the field the server wants. I will read the Bot Social side first. The other half of the expected behavior (never show a rawMCP error -32602, show a plain-language error) is in FlyBot's scope either way.Birfy commentedon Oct 21, 2026
Confirmed against
Birfy/bot-socialmaster@58afc9f1(the commit in the report) — the mismatch is real and it is a contract gap on the Bot Social side, not a FlyBot argument bug. Verified, not inferred:src/owner-mcp.ts:235—grant_bot_to_friendinputSchema: { bot_id: z.string(), friend_owner_id: z.string() }.friend_homeis not in the schema and is stripped before the handler, so the call fails validation with exactly the-32602 … received undefined at friend_owner_idin the report.src/platform.ts:1060asserts the same again (friend_owner_id required).src/platform.ts:108-111(publicBot) — a peer is{ bot_id, handle, display_name, owner_display_name, owner_verified }(plus avatar/color for an active friend).friendsOverview(:1646) andlistBotGrants(:1188) both use it, so noowner_idis ever returned for a friend, for any relationship status.friend_owner_idcan only come from the friend out of band (their ownwhoami, as the tool description says).grep friend_homeoversrc/platform.ts,src/server.ts,src/owner-mcp.ts— 0 hits. There is no handle path anywhere.src/server.ts:75— the REST route isPOST /v1/bots/:id/grantswithfriend_owner_id; FlyBot's fallback posts/v1/bots/:id/grants/to-friend(plugins/social/src/mcp-client.js:458), which does not exist. It only runs on an unknown tool / missing endpoint (isUnknownTool), so a validation error never reaches it.So today the flow cannot work for any friend who has not told you their owner id, whatever FlyBot sends.
Options (all need an owner decision — this is the sharing surface):
friend_bot_id) —list_friendsalready returnspeer.bot_id, so the owner side always has it. Resolve the peer → its owner, then keep the existingfriendships.length > 0assertion unchanged. Small, unambiguous, exposes no owner ids.friend_home(the peer's handle; FlyBot sends it today atmcp-client.js:446) and resolves it the same way. A server-only change would make the current FlyBot build work as-is; a handle is a weaker key than a bot id, so A is the better form.owner_idon active-friend peers. Bigger privacy change (every friend's connector would see it) and more plumbing on the FlyBot side; not needed for the fix.Whichever is chosen, two FlyBot-side follow-ups belong with it: fix the REST fallback to
POST /v1/bots/:id/grants(or drop it), map a-32602validation error to a plain-language line instead of the rawMCP errorstring, and replace the mock inplugins/social/test/social.test.jswith the real server's peer shape (LESSONS 2026-10-18). I have not changed anything: the Bot Social repo has no open issue or PR for this and no deploy will happen without the owner's explicit go-ahead.fix(grants): grant_bot_to_friend accepts the peer bot_id (#592) (#38)
Share with a friend by the peer Bot id (ThinkFlowLab#592) (ThinkFlowL…
Birfy commentedon Oct 21, 2026
Closing conclusion — option A, landed on both ends. The server now accepts the peer's
bot_id, and noowner_idis exposed anywhere new.Birfy/bot-social) — PR Birfy/bot-social#38, squash82bcc0c1.grant_bot_to_friendtakesfriend_bot_id(the peerbot_idfromlist_friends, or its handle), derives the owner from it and keeps the existing "must be an active friend" assertion, now filtered to that Bot;friend_owner_idstill works, and both together must name the same owner.POST /v1/bots/{id}/grantsforwards the new field. No new field is returned to a peer, so the privacy surface is unchanged. Markedawaiting-deploy— not deployed, that needs the owner's go-ahead.f2b461f0(T3, self-PASS at80849705). The share sendsfriend_bot_id; the REST fallback posts to the route the server really has,POST /v1/bots/:id/grants(it was/grants/to-friend); an invalid-input refusal now reads as one plain English line instead of the raw JSON-RPC text; the plugin's test server serves the real peer shape (abot_id, noowner_id).plugins/social274/274, and 268/274 with the three source files reverted; the server'stest/grant_bot_to_friend.test.ts6/6, 4/6 reverted.Until the server build is deployed, a share still answers with "Bot Social did not accept that share request. Its server may need an update; invite links still work." — i.e. the same failure, now explained instead of showing
MCP error -32602.