Repository navigation
Hand Grok Bot users to X DMs after an opportunity accept - #1852
Open
serefyarar wants to merge 1 commit into
Open
serefyarar wants to merge 1 commit into
serefyarar wants to merge 1 commit into
Conversation
When the MCP OAuth client is Grok, opportunity accept/decline links carry surface=x so the existing /o handoff lands on the peer's X profile, and accept_opportunity returns the peer's X profile as the chat link when exactly one is known, falling back to the Index chat. Other clients, the web app, and email links are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
When users interact with Index through the Grok Bot MCP client, opportunity links now hand them off to X instead of keeping them in Index chat:
list_opportunities/get_opportunitymintacceptUrl/declineUrlwith&surface=x, so the existing/o/:id?surface=web handoff lands the acceptor on the peer's X profile (one known X social) instead of the Index profile.accept_opportunityreturns the peer'shttps://x.com/<handle>aschatUrl— with a message to DM them on X — when exactly one X profile can be resolved from their socials. Zero or ambiguous X socials fall back to the Index chat, as does any lookup failure.SKILL.md+paste.md, kept in sync) tells Grok to say the conversation continues in X DMs when the link is an x.com profile.How Grok is detected
The MCP server is shared by all clients, so the OAuth path now resolves the registered client name (
oauth_application.name, 5-minute in-process cache) and stampssurface: 'x'on the principal when the name matches/grok/i(newmcp.surface.ts). No Grok client has registered on dev/prod yet, hence the substring match. Session and API-key principals never get a surface; the name lookup swallows failures so it can never break authentication.New
lib/x/socials.tsnormalizes stored social values (bare handle,@handle, x.com/twitter.com URLs, packed multi-address values) into canonical lowercase profile URLs, modeled on the Telegram normalizer; it rejects non-X hosts and X product paths (/i/…,/home, …). A targeted DM composer URL would need the peer's numeric X id, which we don't store, so the profile (with its Message button) is the handoff — same depth ast.me/<handle>was for Telegram.Unchanged
Web app, morning-brief email links, and every non-Grok MCP client behave exactly as before (
actionLinkwithout a surface mints identical URLs).Maybe later
peerChatlinks inlist_opportunities(already-open chats) still point at Index chat.Testing
lib/x/socials.spec.ts(normalization, dedup, reserved paths, packed values) andlib/mcp/mcp.surface.spec.ts(name predicate) — pass.bun run typecheckandbun run lintclean (one pre-existing unused-var warning elsewhere).oauth_applicationrow to "Grok", mint a token, and checkacceptUrlcarries&surface=xandaccept_opportunityreturns the X profile aschatUrl.🤖 Generated with Claude Code