๐ File detail
tools/ListMcpResourcesTool/ListMcpResourcesTool.ts
๐งฉ .ts๐ 124 lines๐พ 3,907 bytes๐ text
โ Back to All Files๐ฏ Use case
This module implements the โListMcpResourcesToolโ tool (List Mcp Resources) โ something the model can call at runtime alongside other agent tools. On the API surface it exposes Output and ListMcpResourcesTool โ mainly types, interfaces, or factory objects. Dependencies touch schema validation. It composes internal code from services, Tool, utils, prompt, and UI (relative imports).
Generated from folder role, exports, dependency roots, and inline comments โ not hand-reviewed for every path.
๐ง Inline summary
import { z } from 'zod/v4' import { ensureConnectedClient, fetchResourcesForClient, } from '../../services/mcp/client.js'
๐ค Exports (heuristic)
OutputListMcpResourcesTool
๐ External import roots
Package roots from from "โฆ" (relative paths omitted).
zod
๐ฅ๏ธ Source preview
import { z } from 'zod/v4'
import {
ensureConnectedClient,
fetchResourcesForClient,
} from '../../services/mcp/client.js'
import { buildTool, type ToolDef } from '../../Tool.js'
import { errorMessage } from '../../utils/errors.js'
import { lazySchema } from '../../utils/lazySchema.js'
import { logMCPError } from '../../utils/log.js'
import { jsonStringify } from '../../utils/slowOperations.js'
import { isOutputLineTruncated } from '../../utils/terminal.js'
import { DESCRIPTION, LIST_MCP_RESOURCES_TOOL_NAME, PROMPT } from './prompt.js'
import { renderToolResultMessage, renderToolUseMessage } from './UI.js'
const inputSchema = lazySchema(() =>
z.object({
server: z
.string()
.optional()
.describe('Optional server name to filter resources by'),
}),
)
type InputSchema = ReturnType<typeof inputSchema>
const outputSchema = lazySchema(() =>
z.array(
z.object({
uri: z.string().describe('Resource URI'),
name: z.string().describe('Resource name'),
mimeType: z.string().optional().describe('MIME type of the resource'),
description: z.string().optional().describe('Resource description'),
server: z.string().describe('Server that provides this resource'),
}),
),
)
type OutputSchema = ReturnType<typeof outputSchema>
export type Output = z.infer<OutputSchema>
export const ListMcpResourcesTool = buildTool({
isConcurrencySafe() {
return true
},
isReadOnly() {
return true
},
toAutoClassifierInput(input) {
return input.server ?? ''
},
shouldDefer: true,
name: LIST_MCP_RESOURCES_TOOL_NAME,
searchHint: 'list resources from connected MCP servers',
maxResultSizeChars: 100_000,
async description() {
return DESCRIPTION
},
async prompt() {
return PROMPT
},
get inputSchema(): InputSchema {
return inputSchema()
},
get outputSchema(): OutputSchema {
return outputSchema()
},
async call(input, { options: { mcpClients } }) {
const { server: targetServer } = input
const clientsToProcess = targetServer
? mcpClients.filter(client => client.name === targetServer)
: mcpClients
if (targetServer && clientsToProcess.length === 0) {
throw new Error(
`Server "${targetServer}" not found. Available servers: ${mcpClients.map(c => c.name).join(', ')}`,
)
}
// fetchResourcesForClient is LRU-cached (by server name) and already
// warm from startup prefetch. Cache is invalidated on onclose and on
// resources/list_changed notifications, so results are never stale.
// ensureConnectedClient is a no-op when healthy (memoize hit), but after
// onclose it returns a fresh connection so the re-fetch succeeds.
const results = await Promise.all(
clientsToProcess.map(async client => {
if (client.type !== 'connected') return []
try {
const fresh = await ensureConnectedClient(client)
return await fetchResourcesForClient(fresh)
} catch (error) {
// One server's reconnect failure shouldn't sink the whole result.
logMCPError(client.name, errorMessage(error))
return []
}
}),
)
return {
data: results.flat(),
}
},
renderToolUseMessage,
userFacingName: () => 'listMcpResources',
renderToolResultMessage,
isResultTruncated(output: Output): boolean {
return isOutputLineTruncated(jsonStringify(output))
},
mapToolResultToToolResultBlockParam(content, toolUseID) {
if (!content || content.length === 0) {
return {
tool_use_id: toolUseID,
type: 'tool_result',
content:
'No resources found. MCP servers may still provide tools even if they have no resources.',
}
}
return {
tool_use_id: toolUseID,
type: 'tool_result',
content: jsonStringify(content),
}
},
} satisfies ToolDef<InputSchema, Output>)