From 519cc621306ae71a86e2dfd740f72ccb105f0245 Mon Sep 17 00:00:00 2001 From: Steve Lam Date: Sun, 8 Nov 2026 23:10:55 -0700 Subject: [PATCH] feat(provider): support MCP URL elicitation for Claude and Codex --- .../features/threads/PendingApprovalCard.tsx | 42 +++++++++++-- apps/mobile/src/lib/openExternalUrl.ts | 1 + .../Adapters/ClaudeAdapterV2.test.ts | 36 +++++++++-- .../Adapters/ClaudeAdapterV2.ts | 19 +++++- .../Adapters/CodexAdapterV2.test.ts | 62 +++++++++++++++++++ .../Adapters/CodexAdapterV2.ts | 3 + .../src/provider/CodexMcpElicitation.test.ts | 28 ++++++++- .../src/provider/CodexMcpElicitation.ts | 27 +++++++- .../components/chat/ChildThreadApprovals.tsx | 9 +++ .../components/chat/McpElicitationLink.tsx | 37 +++++++++++ .../chat/TimelinePendingApprovalRow.tsx | 9 +++ docs/user/permission-modes.md | 9 +++ packages/client-runtime/src/secretRequest.ts | 6 +- .../src/state/threadRequests.ts | 6 ++ packages/contracts/src/httpPageUrl.test.ts | 16 +++++ packages/contracts/src/httpPageUrl.ts | 9 +++ packages/contracts/src/index.ts | 1 + packages/contracts/src/orchestrationV2.ts | 2 + packages/contracts/src/orchestratorMcp.ts | 4 +- packages/contracts/src/secretRequest.test.ts | 14 ----- packages/contracts/src/secretRequest.ts | 11 ---- 21 files changed, 306 insertions(+), 45 deletions(-) create mode 100644 apps/web/src/components/chat/McpElicitationLink.tsx create mode 100644 packages/contracts/src/httpPageUrl.test.ts create mode 100644 packages/contracts/src/httpPageUrl.ts delete mode 100644 packages/contracts/src/secretRequest.test.ts diff --git a/apps/mobile/src/features/threads/PendingApprovalCard.tsx b/apps/mobile/src/features/threads/PendingApprovalCard.tsx index f9ec44d5d4ee5..1c2092573c519 100644 --- a/apps/mobile/src/features/threads/PendingApprovalCard.tsx +++ b/apps/mobile/src/features/threads/PendingApprovalCard.tsx @@ -1,17 +1,20 @@ import { Button } from "../../components/ui/Button"; -import type { - ProviderApprovalDecision, - ProviderApprovalOption, - RuntimeRequestId, +import { + httpPageUrl, + type ProviderApprovalDecision, + type ProviderApprovalOption, + type RuntimeRequestId, } from "@t3tools/contracts"; import { FULL_ACCESS_OVERRIDE_QUESTION, fullAccessOverrideExplanation, + MCP_URL_ELICITATION_HINT, } from "@t3tools/client-runtime/state/thread-requests"; import { useState } from "react"; import { Pressable, View } from "react-native"; import { AppText as Text } from "../../components/ui/AppText"; +import { tryOpenExternalUrl } from "../../lib/openExternalUrl"; import type { PendingApproval } from "../../lib/threadActivity"; export interface PendingApprovalCardProps { @@ -37,6 +40,10 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) { const canRespond = props.approval.responseCapability === "live"; const disabled = !canRespond || props.respondingApprovalId === props.approval.requestId; const [explanationOpen, setExplanationOpen] = useState(false); + const [linkError, setLinkError] = useState(false); + const elicitationUrl = props.approval.elicitationUrl + ? httpPageUrl(props.approval.elicitationUrl) + : null; return ( @@ -50,6 +57,33 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) { {props.approval.detail} ) : null} + {elicitationUrl ? ( + + + {MCP_URL_ELICITATION_HINT} + + + {elicitationUrl.href} + +