WIP: Subscribe to resources
* In App.tsx
- added subscribeToResource()
- takes a uri
- sends a `resources/subscribe` message with the uri
- added unsubscribeFromResource()
- takes a uri
- sends a `resources/unsubscribe` message with the uri
- in ResourcesTab element,
- pass subscribeToResource and subscribeToResource invokers to component
* In notificationTypes.ts
- add ServerNotificationSchema to NotificationSchema to permit server update messages.
* In ResourcesTab.tsx
- deconstruct subscribeToResource and unsubscribeFromResource and add prop types
- Add Subscribe and Unsubscribe buttons to selected resource panel, left of the refresh button. They call the sub and unsub functions that came in on props, passing the selected resource URI.
- [WIP]: Will show the appropriate button in a follow up commit.
* In useConnection.ts
- import ResourceUpdatedNotificationSchema
- in the connect function,
- set onNotification as the handler for ResourceUpdatedNotificationSchema
This commit is contained in:
@@ -308,6 +308,31 @@ const App = () => {
|
||||
setResourceContent(JSON.stringify(response, null, 2));
|
||||
};
|
||||
|
||||
const subscribeToResource = async (uri: string) => {
|
||||
|
||||
await makeRequest(
|
||||
{
|
||||
method: "resources/subscribe" as const,
|
||||
params: { uri },
|
||||
},
|
||||
z.object({}),
|
||||
"resources",
|
||||
);
|
||||
};
|
||||
|
||||
const unsubscribeFromResource = async (uri: string) => {
|
||||
|
||||
await makeRequest(
|
||||
{
|
||||
method: "resources/unsubscribe" as const,
|
||||
params: { uri },
|
||||
},
|
||||
z.object({}),
|
||||
"resources",
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const listPrompts = async () => {
|
||||
const response = await makeRequest(
|
||||
{
|
||||
@@ -485,6 +510,14 @@ const App = () => {
|
||||
clearError("resources");
|
||||
setSelectedResource(resource);
|
||||
}}
|
||||
subscribeToResource={(uri) => {
|
||||
clearError("resources");
|
||||
subscribeToResource(uri);
|
||||
}}
|
||||
unsubscribeFromResource={(uri) => {
|
||||
clearError("resources");
|
||||
unsubscribeFromResource(uri);
|
||||
}}
|
||||
handleCompletion={handleCompletion}
|
||||
completionsSupported={completionsSupported}
|
||||
resourceContent={resourceContent}
|
||||
|
||||
@@ -26,6 +26,8 @@ const ResourcesTab = ({
|
||||
readResource,
|
||||
selectedResource,
|
||||
setSelectedResource,
|
||||
subscribeToResource,
|
||||
unsubscribeFromResource,
|
||||
handleCompletion,
|
||||
completionsSupported,
|
||||
resourceContent,
|
||||
@@ -52,6 +54,8 @@ const ResourcesTab = ({
|
||||
nextCursor: ListResourcesResult["nextCursor"];
|
||||
nextTemplateCursor: ListResourceTemplatesResult["nextCursor"];
|
||||
error: string | null;
|
||||
subscribeToResource: (uri: string) => void;
|
||||
unsubscribeFromResource: (uri: string) => void;
|
||||
}) => {
|
||||
const [selectedTemplate, setSelectedTemplate] =
|
||||
useState<ResourceTemplate | null>(null);
|
||||
@@ -164,14 +168,30 @@ const ResourcesTab = ({
|
||||
: "Select a resource or template"}
|
||||
</h3>
|
||||
{selectedResource && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => readResource(selectedResource.uri)}
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Refresh
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => subscribeToResource(selectedResource.uri)}
|
||||
>
|
||||
Subscribe
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => unsubscribeFromResource(selectedResource.uri)}
|
||||
>
|
||||
Unsubscribe
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => readResource(selectedResource.uri)}
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Refresh
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="p-4">
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
CreateMessageRequestSchema,
|
||||
ListRootsRequestSchema,
|
||||
ProgressNotificationSchema,
|
||||
ResourceUpdatedNotificationSchema,
|
||||
Request,
|
||||
Result,
|
||||
ServerCapabilities,
|
||||
@@ -247,6 +248,11 @@ export function useConnection({
|
||||
ProgressNotificationSchema,
|
||||
onNotification,
|
||||
);
|
||||
|
||||
client.setNotificationHandler(
|
||||
ResourceUpdatedNotificationSchema,
|
||||
onNotification,
|
||||
);
|
||||
}
|
||||
|
||||
if (onStdErrNotification) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
NotificationSchema as BaseNotificationSchema,
|
||||
ClientNotificationSchema,
|
||||
ServerNotificationSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -11,9 +12,9 @@ export const StdErrNotificationSchema = BaseNotificationSchema.extend({
|
||||
}),
|
||||
});
|
||||
|
||||
export const NotificationSchema = ClientNotificationSchema.or(
|
||||
StdErrNotificationSchema,
|
||||
);
|
||||
export const NotificationSchema = ClientNotificationSchema
|
||||
.or(StdErrNotificationSchema)
|
||||
.or(ServerNotificationSchema);
|
||||
|
||||
export type StdErrNotification = z.infer<typeof StdErrNotificationSchema>;
|
||||
export type Notification = z.infer<typeof NotificationSchema>;
|
||||
|
||||
Reference in New Issue
Block a user