feat: Add support for MCP Resources (#13178)

Co-authored-by: Jack Wotherspoon <jackwoth@google.com>
This commit is contained in:
Alex Gavrilescu
2025-12-09 03:43:12 +01:00
committed by GitHub
parent 720b31cb8b
commit 560550f5df
20 changed files with 1146 additions and 80 deletions
@@ -36,6 +36,7 @@ describe('McpStatus', () => {
},
],
prompts: [],
resources: [],
blockedServers: [],
serverStatus: () => MCPServerStatus.CONNECTED,
authStatus: {},
@@ -147,6 +148,24 @@ describe('McpStatus', () => {
unmount();
});
it('renders correctly with resources', () => {
const { lastFrame, unmount } = render(
<McpStatus
{...baseProps}
resources={[
{
serverName: 'server-1',
name: 'resource-1',
uri: 'file:///tmp/resource-1.txt',
description: 'A test resource',
},
]}
/>,
);
expect(lastFrame()).toMatchSnapshot();
unmount();
});
it('renders correctly with a blocked server', () => {
const { lastFrame, unmount } = render(
<McpStatus
@@ -12,6 +12,7 @@ import { theme } from '../../semantic-colors.js';
import type {
HistoryItemMcpStatus,
JsonMcpPrompt,
JsonMcpResource,
JsonMcpTool,
} from '../../types.js';
@@ -19,6 +20,7 @@ interface McpStatusProps {
servers: Record<string, MCPServerConfig>;
tools: JsonMcpTool[];
prompts: JsonMcpPrompt[];
resources: JsonMcpResource[];
blockedServers: Array<{ name: string; extensionName: string }>;
serverStatus: (serverName: string) => MCPServerStatus;
authStatus: HistoryItemMcpStatus['authStatus'];
@@ -32,6 +34,7 @@ export const McpStatus: React.FC<McpStatusProps> = ({
servers,
tools,
prompts,
resources,
blockedServers,
serverStatus,
authStatus,
@@ -83,9 +86,14 @@ export const McpStatus: React.FC<McpStatusProps> = ({
const serverPrompts = prompts.filter(
(prompt) => prompt.serverName === serverName,
);
const serverResources = resources.filter(
(resource) => resource.serverName === serverName,
);
const originalStatus = serverStatus(serverName);
const hasCachedItems =
serverTools.length > 0 || serverPrompts.length > 0;
serverTools.length > 0 ||
serverPrompts.length > 0 ||
serverResources.length > 0;
const status =
originalStatus === MCPServerStatus.DISCONNECTED && hasCachedItems
? MCPServerStatus.CONNECTED
@@ -121,6 +129,7 @@ export const McpStatus: React.FC<McpStatusProps> = ({
const toolCount = serverTools.length;
const promptCount = serverPrompts.length;
const resourceCount = serverResources.length;
const parts = [];
if (toolCount > 0) {
parts.push(`${toolCount} ${toolCount === 1 ? 'tool' : 'tools'}`);
@@ -130,6 +139,11 @@ export const McpStatus: React.FC<McpStatusProps> = ({
`${promptCount} ${promptCount === 1 ? 'prompt' : 'prompts'}`,
);
}
if (resourceCount > 0) {
parts.push(
`${resourceCount} ${resourceCount === 1 ? 'resource' : 'resources'}`,
);
}
const serverAuthStatus = authStatus[serverName];
let authStatusNode: React.ReactNode = null;
@@ -233,6 +247,34 @@ export const McpStatus: React.FC<McpStatusProps> = ({
))}
</Box>
)}
{serverResources.length > 0 && (
<Box flexDirection="column" marginLeft={2}>
<Text color={theme.text.primary}>Resources:</Text>
{serverResources.map((resource, index) => {
const label = resource.name || resource.uri || 'resource';
return (
<Box
key={`${resource.serverName}-resource-${index}`}
flexDirection="column"
>
<Text>
- <Text color={theme.text.primary}>{label}</Text>
{resource.uri ? ` (${resource.uri})` : ''}
{resource.mimeType ? ` [${resource.mimeType}]` : ''}
</Text>
{showDescriptions && resource.description && (
<Box marginLeft={2}>
<Text color={theme.text.secondary}>
{resource.description.trim()}
</Text>
</Box>
)}
</Box>
);
})}
</Box>
)}
</Box>
);
})}
@@ -116,6 +116,20 @@ A test server
"
`;
exports[`McpStatus > renders correctly with resources 1`] = `
"Configured MCP servers:
🟢 server-1 - Ready (1 tool, 1 resource)
A test server
Tools:
- tool-1
A test tool
Resources:
- resource-1 (file:///tmp/resource-1.txt)
A test resource
"
`;
exports[`McpStatus > renders correctly with schema enabled 1`] = `
"Configured MCP servers: