1- import { Button } from "@/components/ui/button" ;
2- import { Input } from "@/components/ui/input" ;
3- import {
4- Select ,
5- SelectContent ,
6- SelectItem ,
7- SelectTrigger ,
8- SelectValue ,
9- } from "@/components/ui/select" ;
10- import { Tabs , TabsList , TabsTrigger } from "@/components/ui/tabs" ;
111import { Client } from "@modelcontextprotocol/sdk/client/index.js" ;
122import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js" ;
133import {
144 CallToolResultSchema ,
155 ClientRequest ,
6+ CreateMessageRequestSchema ,
7+ CreateMessageResult ,
168 EmptyResultSchema ,
179 GetPromptResultSchema ,
1810 ListPromptsResultSchema ,
@@ -24,16 +16,28 @@ import {
2416 ServerNotification ,
2517 Tool ,
2618} from "@modelcontextprotocol/sdk/types.js" ;
19+ import { useEffect , useRef , useState } from "react" ;
20+
21+ import { Button } from "@/components/ui/button" ;
22+ import { Input } from "@/components/ui/input" ;
23+ import {
24+ Select ,
25+ SelectContent ,
26+ SelectItem ,
27+ SelectTrigger ,
28+ SelectValue ,
29+ } from "@/components/ui/select" ;
30+ import { Tabs , TabsList , TabsTrigger } from "@/components/ui/tabs" ;
2731import {
2832 Bell ,
2933 Files ,
3034 Hammer ,
35+ Hash ,
3136 MessageSquare ,
3237 Play ,
3338 Send ,
3439 Terminal ,
3540} from "lucide-react" ;
36- import { useEffect , useRef , useState } from "react" ;
3741
3842import { AnyZodObject } from "zod" ;
3943import "./App.css" ;
@@ -43,6 +47,7 @@ import PingTab from "./components/PingTab";
4347import PromptsTab , { Prompt } from "./components/PromptsTab" ;
4448import RequestsTab from "./components/RequestsTabs" ;
4549import ResourcesTab from "./components/ResourcesTab" ;
50+ import SamplingTab , { PendingRequest } from "./components/SamplingTab" ;
4651import Sidebar from "./components/Sidebar" ;
4752import ToolsTab from "./components/ToolsTab" ;
4853
@@ -77,6 +82,32 @@ const App = () => {
7782 const [ mcpClient , setMcpClient ] = useState < Client | null > ( null ) ;
7883 const [ notifications , setNotifications ] = useState < ServerNotification [ ] > ( [ ] ) ;
7984
85+ const [ pendingSampleRequests , setPendingSampleRequests ] = useState <
86+ Array <
87+ PendingRequest & {
88+ resolve : ( result : CreateMessageResult ) => void ;
89+ reject : ( error : Error ) => void ;
90+ }
91+ >
92+ > ( [ ] ) ;
93+ const nextRequestId = useRef ( 0 ) ;
94+
95+ const handleApproveSampling = ( id : number , result : CreateMessageResult ) => {
96+ setPendingSampleRequests ( ( prev ) => {
97+ const request = prev . find ( ( r ) => r . id === id ) ;
98+ request ?. resolve ( result ) ;
99+ return prev . filter ( ( r ) => r . id !== id ) ;
100+ } ) ;
101+ } ;
102+
103+ const handleRejectSampling = ( id : number ) => {
104+ setPendingSampleRequests ( ( prev ) => {
105+ const request = prev . find ( ( r ) => r . id === id ) ;
106+ request ?. reject ( new Error ( "Sampling request rejected" ) ) ;
107+ return prev . filter ( ( r ) => r . id !== id ) ;
108+ } ) ;
109+ } ;
110+
80111 const [ selectedResource , setSelectedResource ] = useState < Resource | null > (
81112 null ,
82113 ) ;
@@ -229,6 +260,15 @@ const App = () => {
229260 } ,
230261 ) ;
231262
263+ client . setRequestHandler ( CreateMessageRequestSchema , ( request ) => {
264+ return new Promise < CreateMessageResult > ( ( resolve , reject ) => {
265+ setPendingSampleRequests ( ( prev ) => [
266+ ...prev ,
267+ { id : nextRequestId . current ++ , request, resolve, reject } ,
268+ ] ) ;
269+ } ) ;
270+ } ) ;
271+
232272 setMcpClient ( client ) ;
233273 setConnectionStatus ( "connected" ) ;
234274 } catch ( e ) {
@@ -314,6 +354,15 @@ const App = () => {
314354 < Bell className = "w-4 h-4 mr-2" />
315355 Ping
316356 </ TabsTrigger >
357+ < TabsTrigger value = "sampling" className = "relative" >
358+ < Hash className = "w-4 h-4 mr-2" />
359+ Sampling
360+ { pendingSampleRequests . length > 0 && (
361+ < span className = "absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center" >
362+ { pendingSampleRequests . length }
363+ </ span >
364+ ) }
365+ </ TabsTrigger >
317366 </ TabsList >
318367
319368 < div className = "w-full" >
@@ -362,6 +411,11 @@ const App = () => {
362411 ) ;
363412 } }
364413 />
414+ < SamplingTab
415+ pendingRequests = { pendingSampleRequests }
416+ onApprove = { handleApproveSampling }
417+ onReject = { handleRejectSampling }
418+ />
365419 </ div >
366420 </ Tabs >
367421 ) : (
0 commit comments