handler() — mcp Function Reference
Architecture documentation for the handler() function in explore-function.ts from the mcp codebase.
Entity Profile
Dependency Diagram
graph TD 1767161e_720a_f6c8_bf00_3dc68740b823["handler()"] 05b504b7_268e_7c49_d109_73f7c3744be0["asErrorResult()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 05b504b7_268e_7c49_d109_73f7c3744be0 1721f7fd_bb7b_c8c3_9b4b_5677293ae256["resolveOrFetchGraph()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 1721f7fd_bb7b_c8c3_9b4b_5677293ae256 f8f0f24b_951e_04ad_fb80_1ae3dde982e9["classifyApiError()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| f8f0f24b_951e_04ad_fb80_1ae3dde982e9 2d87a17c_e46f_9198_c263_81d7c3c3054e["findSymbol()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 2d87a17c_e46f_9198_c263_81d7c3c3054e 79b44b57_42bd_0224_2b6c_fa2bf3ff180e["buildSubdomainToParentMap()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 79b44b57_42bd_0224_2b6c_fa2bf3ff180e 70483507_2c71_464c_1cbc_d74d4479f5e1["resolveDomain()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 70483507_2c71_464c_1cbc_d74d4479f5e1 129c63b6_9648_d4bb_3c4d_03d461c6ad68["describeNode()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 129c63b6_9648_d4bb_3c4d_03d461c6ad68 6666a1f2_0912_ade3_4b0e_42190c41cd97["normalizePath()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 6666a1f2_0912_ade3_4b0e_42190c41cd97 d6ed9355_f977_306b_b0ef_d7220fdefe68["get()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| d6ed9355_f977_306b_b0ef_d7220fdefe68 90af3150_ce81_c645_faa7_5b8b9bcf5ecc["has()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 90af3150_ce81_c645_faa7_5b8b9bcf5ecc 67622b0f_6b47_8f68_bac5_409b3145d2f2["asTextContentResult()"] 1767161e_720a_f6c8_bf00_3dc68740b823 -->|calls| 67622b0f_6b47_8f68_bac5_409b3145d2f2 style 1767161e_720a_f6c8_bf00_3dc68740b823 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
src/tools/explore-function.ts lines 170–353
export const handler: HandlerFunction = async (client, args, defaultWorkdir) => {
const symbolArg = typeof args?.symbol === 'string' ? args.symbol.trim() : '';
if (!symbolArg) {
return asErrorResult({
type: 'validation_error',
message: 'Missing required "symbol" parameter.',
code: 'MISSING_SYMBOL',
recoverable: false,
suggestion: 'Provide the name of a function to explore.',
});
}
const direction = (args?.direction as string) || 'both';
if (!['downstream', 'upstream', 'both'].includes(direction)) {
return asErrorResult({
type: 'validation_error',
message: `Invalid direction "${direction}". Must be "downstream", "upstream", or "both".`,
code: 'INVALID_DIRECTION',
recoverable: false,
suggestion: 'Use "downstream" (callees), "upstream" (callers), or "both".',
});
}
const depth = Math.min(3, Math.max(1, Number(args?.depth) || 2));
const rawDir = args?.directory as string | undefined;
const directory = (rawDir && rawDir.trim()) || defaultWorkdir || process.cwd();
if (!directory || typeof directory !== 'string') {
return asErrorResult({
type: 'validation_error',
message: 'No directory provided and no default workdir configured.',
code: 'MISSING_DIRECTORY',
recoverable: false,
suggestion: 'Provide a directory parameter or start the MCP server with a workdir argument.',
});
}
let graph: IndexedGraph;
try {
graph = await resolveOrFetchGraph(client, directory);
} catch (error: any) {
return asErrorResult(classifyApiError(error));
}
// Resolve symbol name to a Function or Class node
const matches = findSymbol(graph, symbolArg);
const funcMatch = matches.find(n => n.labels?.[0] === 'Function' || n.labels?.[0] === 'Class');
if (!funcMatch) {
return asErrorResult({
type: 'not_found_error',
message: `No function or class matching "${symbolArg}" found in the code graph.`,
code: 'SYMBOL_NOT_FOUND',
recoverable: false,
suggestion: 'Try a different function name or use partial matching.',
});
}
const rootId = funcMatch.id;
const subdomainToParent = buildSubdomainToParentMap(graph);
const rootDomain = resolveDomain(graph, rootId, subdomainToParent);
const rootSubName = rootDomain.subdomain;
const lines: string[] = [];
lines.push(`## ${describeNode(graph, rootId, null, subdomainToParent)}`);
lines.push('');
// Include source code for the root symbol (saves agent a Read round-trip)
const rootSource = funcMatch.properties?.sourceCode as string | undefined;
if (rootSource) {
const sourceLines = rootSource.split('\n');
const truncated = sourceLines.length > MAX_SOURCE_LINES;
const displayLines = truncated ? sourceLines.slice(0, MAX_SOURCE_LINES) : sourceLines;
const startLine = funcMatch.properties?.startLine as number | undefined;
const filePath = normalizePath(funcMatch.properties?.filePath as string || '');
const ext = filePath.split('.').pop() || '';
lines.push(`### Source`);
lines.push('```' + ext);
if (startLine) {
displayLines.forEach((l, i) => { lines.push(`${startLine + i}: ${l}`); });
} else {
displayLines.forEach(l => { lines.push(l); });
}
if (truncated) lines.push(`... (${sourceLines.length - MAX_SOURCE_LINES} more lines)`);
lines.push('```');
lines.push('');
}
// Downstream BFS (callees)
if (direction === 'downstream' || direction === 'both') {
lines.push('### Functions it calls:');
let frontier = [rootId];
const visited = new Set([rootId]);
for (let d = 1; d <= depth; d++) {
const nextFrontier: string[] = [];
if (d === 1) {
const callees = (graph.callAdj.get(rootId)?.out || [])
.filter(id => { const l = graph.nodeById.get(id)?.labels?.[0]; return l === 'Function' || l === 'Class'; });
if (callees.length === 0) {
lines.push(' (none)');
}
for (const [i, cId] of callees.entries()) {
visited.add(cId);
nextFrontier.push(cId);
lines.push(` ${i + 1}. ${describeNode(graph, cId, rootSubName, subdomainToParent)}`);
}
} else {
let anyFound = false;
for (const parentId of frontier) {
const parentNode = graph.nodeById.get(parentId);
const parentName = parentNode?.properties?.name as string || '(unknown)';
const callees = (graph.callAdj.get(parentId)?.out || [])
.filter(id => { const l = graph.nodeById.get(id)?.labels?.[0]; return l === 'Function' || l === 'Class'; })
.filter(id => !visited.has(id));
if (callees.length === 0) continue;
anyFound = true;
lines.push(` Via \`${parentName}\`:`);
for (const cId of callees) {
visited.add(cId);
nextFrontier.push(cId);
lines.push(` → ${describeNode(graph, cId, rootSubName, subdomainToParent)}`);
}
}
if (!anyFound) {
lines.push(` (no further calls at depth ${d})`);
}
}
frontier = nextFrontier;
}
lines.push('');
}
// Upstream BFS (callers)
if (direction === 'upstream' || direction === 'both') {
lines.push('### Functions that call it:');
let frontier = [rootId];
const visited = new Set([rootId]);
for (let d = 1; d <= depth; d++) {
const nextFrontier: string[] = [];
if (d === 1) {
const callers = (graph.callAdj.get(rootId)?.in || [])
.filter(id => { const l = graph.nodeById.get(id)?.labels?.[0]; return l === 'Function' || l === 'Class'; });
if (callers.length === 0) {
lines.push(' (none)');
}
for (const [i, cId] of callers.entries()) {
visited.add(cId);
nextFrontier.push(cId);
lines.push(` ${i + 1}. ${describeNode(graph, cId, rootSubName, subdomainToParent)}`);
}
} else {
let anyFound = false;
for (const parentId of frontier) {
const parentNode = graph.nodeById.get(parentId);
const parentName = parentNode?.properties?.name as string || '(unknown)';
const callers = (graph.callAdj.get(parentId)?.in || [])
.filter(id => { const l = graph.nodeById.get(id)?.labels?.[0]; return l === 'Function' || l === 'Class'; })
.filter(id => !visited.has(id));
if (callers.length === 0) continue;
anyFound = true;
lines.push(` Via \`${parentName}\`:`);
for (const cId of callers) {
visited.add(cId);
nextFrontier.push(cId);
lines.push(` → ${describeNode(graph, cId, rootSubName, subdomainToParent)}`);
}
}
if (!anyFound) {
lines.push(` (no further callers at depth ${d})`);
}
}
frontier = nextFrontier;
}
lines.push('');
}
return asTextContentResult(lines.join('\n'));
};
Domain
Subdomains
Calls
Source
Frequently Asked Questions
What does handler() do?
handler() is a function in the mcp codebase.
What does handler() call?
handler() calls 11 function(s): asErrorResult, asTextContentResult, buildSubdomainToParentMap, classifyApiError, describeNode, findSymbol, get, has, and 3 more.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free