@@ -30,6 +30,7 @@ import {
3030 hasValidMetaPrefix ,
3131 isReservedMetaKey ,
3232} from "@/utils/metaUtils" ;
33+ import { getToolUiResourceUri } from "@modelcontextprotocol/ext-apps/app-bridge" ;
3334import { AuthDebuggerState , EMPTY_DEBUGGER_STATE } from "./lib/auth-types" ;
3435import { OAuthStateMachine } from "./lib/oauth-state-machine" ;
3536import { cacheToolOutputSchemas } from "./utils/schemaUtils" ;
@@ -101,6 +102,27 @@ import MetadataTab from "./components/MetadataTab";
101102
102103const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1" ;
103104
105+ type PrefilledAppsToolCall = {
106+ id : number ;
107+ toolName : string ;
108+ params : Record < string , unknown > ;
109+ result : CompatibilityCallToolResult ;
110+ } ;
111+
112+ const hasAppResourceUri = ( tool : Tool ) : boolean => {
113+ return Boolean ( getToolUiResourceUri ( tool ) ) ;
114+ } ;
115+
116+ const cloneToolParams = (
117+ source : Record < string , unknown > ,
118+ ) : Record < string , unknown > => {
119+ try {
120+ return structuredClone ( source ) ;
121+ } catch {
122+ return { ...source } ;
123+ }
124+ } ;
125+
104126const filterReservedMetadata = (
105127 metadata : Record < string , string > ,
106128) : Record < string , string > => {
@@ -137,6 +159,8 @@ const App = () => {
137159 const [ tasks , setTasks ] = useState < Task [ ] > ( [ ] ) ;
138160 const [ toolResult , setToolResult ] =
139161 useState < CompatibilityCallToolResult | null > ( null ) ;
162+ const [ prefilledAppsToolCall , setPrefilledAppsToolCall ] =
163+ useState < PrefilledAppsToolCall | null > ( null ) ;
140164 const [ errors , setErrors ] = useState < Record < string , string | null > > ( {
141165 resources : null ,
142166 prompts : null ,
@@ -291,6 +315,7 @@ const App = () => {
291315 const [ nextToolCursor , setNextToolCursor ] = useState < string | undefined > ( ) ;
292316 const [ nextTaskCursor , setNextTaskCursor ] = useState < string | undefined > ( ) ;
293317 const progressTokenRef = useRef ( 0 ) ;
318+ const prefilledAppsToolCallIdRef = useRef ( 0 ) ;
294319
295320 const [ activeTab , setActiveTab ] = useState < string > ( ( ) => {
296321 const hash = window . location . hash . slice ( 1 ) ;
@@ -977,7 +1002,7 @@ const App = () => {
9771002 params : Record < string , unknown > ,
9781003 toolMetadata ?: Record < string , unknown > ,
9791004 runAsTask ?: boolean ,
980- ) => {
1005+ ) : Promise < CompatibilityCallToolResult > => {
9811006 lastToolCallOriginTabRef . current = currentTabRef . current ;
9821007
9831008 try {
@@ -1045,7 +1070,7 @@ const App = () => {
10451070 "_meta" in ( response as Record < string , unknown > )
10461071 ? ( ( response as { _meta ?: Record < string , unknown > } ) . _meta ?? { } )
10471072 : undefined ;
1048- setToolResult ( {
1073+ let latestToolResult : CompatibilityCallToolResult = {
10491074 content : [
10501075 {
10511076 type : "text" ,
@@ -1056,7 +1081,8 @@ const App = () => {
10561081 ...( initialResponseMeta || { } ) ,
10571082 "io.modelcontextprotocol/related-task" : { taskId } ,
10581083 } ,
1059- } as CompatibilityCallToolResult ) ;
1084+ } ;
1085+ setToolResult ( latestToolResult ) ;
10601086
10611087 // Polling loop
10621088 let taskCompleted = false ;
@@ -1093,20 +1119,22 @@ const App = () => {
10931119 CompatibilityCallToolResultSchema ,
10941120 ) ;
10951121 console . log ( `Result received for task ${ taskId } :` , result ) ;
1096- setToolResult ( result as CompatibilityCallToolResult ) ;
1122+ latestToolResult = result as CompatibilityCallToolResult ;
1123+ setToolResult ( latestToolResult ) ;
10971124
10981125 // Refresh tasks list to show completed state
10991126 void listTasks ( ) ;
11001127 } else {
1101- setToolResult ( {
1128+ latestToolResult = {
11021129 content : [
11031130 {
11041131 type : "text" ,
11051132 text : `Task ${ taskStatus . status } : ${ taskStatus . statusMessage || "No additional information" } ` ,
11061133 } ,
11071134 ] ,
11081135 isError : true ,
1109- } ) ;
1136+ } ;
1137+ setToolResult ( latestToolResult ) ;
11101138 // Refresh tasks list to show failed/cancelled state
11111139 void listTasks ( ) ;
11121140 }
@@ -1120,7 +1148,7 @@ const App = () => {
11201148 ? ( ( response as { _meta ?: Record < string , unknown > } ) . _meta ??
11211149 { } )
11221150 : undefined ;
1123- setToolResult ( {
1151+ latestToolResult = {
11241152 content : [
11251153 {
11261154 type : "text" ,
@@ -1131,30 +1159,37 @@ const App = () => {
11311159 ...( pollingResponseMeta || { } ) ,
11321160 "io.modelcontextprotocol/related-task" : { taskId } ,
11331161 } ,
1134- } as CompatibilityCallToolResult ) ;
1162+ } ;
1163+ setToolResult ( latestToolResult ) ;
11351164 // Refresh tasks list to show progress
11361165 void listTasks ( ) ;
11371166 }
11381167 } catch ( pollingError ) {
11391168 console . error ( "Error polling task status:" , pollingError ) ;
1140- setToolResult ( {
1169+ latestToolResult = {
11411170 content : [
11421171 {
11431172 type : "text" ,
11441173 text : `Error polling task status: ${ pollingError instanceof Error ? pollingError . message : String ( pollingError ) } ` ,
11451174 } ,
11461175 ] ,
11471176 isError : true ,
1148- } ) ;
1177+ } ;
1178+ setToolResult ( latestToolResult ) ;
11491179 taskCompleted = true ;
11501180 }
11511181 }
11521182 setIsPollingTask ( false ) ;
1183+ // Clear any validation errors since tool execution completed
1184+ setErrors ( ( prev ) => ( { ...prev , tools : null } ) ) ;
1185+ return latestToolResult ;
11531186 } else {
1154- setToolResult ( response as CompatibilityCallToolResult ) ;
1187+ const directResult = response as CompatibilityCallToolResult ;
1188+ setToolResult ( directResult ) ;
1189+ // Clear any validation errors since tool execution completed
1190+ setErrors ( ( prev ) => ( { ...prev , tools : null } ) ) ;
1191+ return directResult ;
11551192 }
1156- // Clear any validation errors since tool execution completed
1157- setErrors ( ( prev ) => ( { ...prev , tools : null } ) ) ;
11581193 } catch ( e ) {
11591194 const toolResult : CompatibilityCallToolResult = {
11601195 content : [
@@ -1168,6 +1203,7 @@ const App = () => {
11681203 setToolResult ( toolResult ) ;
11691204 // Clear validation errors - tool execution errors are shown in ToolResults
11701205 setErrors ( ( prev ) => ( { ...prev , tools : null } ) ) ;
1206+ return toolResult ;
11711207 }
11721208 } ;
11731209
@@ -1508,7 +1544,26 @@ const App = () => {
15081544 ) => {
15091545 clearError ( "tools" ) ;
15101546 setToolResult ( null ) ;
1511- await callTool ( name , params , metadata , runAsTask ) ;
1547+ const result = await callTool (
1548+ name ,
1549+ params ,
1550+ metadata ,
1551+ runAsTask ,
1552+ ) ;
1553+ const calledTool = tools . find (
1554+ ( tool ) => tool . name === name ,
1555+ ) ;
1556+ if ( calledTool && hasAppResourceUri ( calledTool ) ) {
1557+ setPrefilledAppsToolCall ( {
1558+ id : ++ prefilledAppsToolCallIdRef . current ,
1559+ toolName : name ,
1560+ params : cloneToolParams ( params ) ,
1561+ result,
1562+ } ) ;
1563+ } else {
1564+ setPrefilledAppsToolCall ( null ) ;
1565+ }
1566+ return result ;
15121567 } }
15131568 selectedTool = { selectedTool }
15141569 setSelectedTool = { ( tool ) => {
@@ -1552,6 +1607,22 @@ const App = () => {
15521607 clearError ( "tools" ) ;
15531608 listTools ( ) ;
15541609 } }
1610+ callTool = { async (
1611+ name : string ,
1612+ params : Record < string , unknown > ,
1613+ metadata ?: Record < string , unknown > ,
1614+ runAsTask ?: boolean ,
1615+ ) => {
1616+ clearError ( "tools" ) ;
1617+ setToolResult ( null ) ;
1618+ return callTool ( name , params , metadata , runAsTask ) ;
1619+ } }
1620+ prefilledToolCall = { prefilledAppsToolCall }
1621+ onPrefilledToolCallConsumed = { ( callId ) => {
1622+ setPrefilledAppsToolCall ( ( prev ) =>
1623+ prev ?. id === callId ? null : prev ,
1624+ ) ;
1625+ } }
15551626 error = { errors . tools }
15561627 mcpClient = { mcpClient }
15571628 onNotification = { ( notification ) => {
0 commit comments