MCP Tool Inspection
Check, filter, validate, and wrap MCP tools before exposing them to an agent.
MCP tools are adapted automatically, but a production harness should still inspect what the server exposed. Tool names, descriptions, input schemas, and permission expectations decide whether a tool is safe to show to a model.
Scenario
A remote MCP server exposes 40 tools. Your support agent should use only read-only documentation tools, while an internal admin agent can use a smaller set of write tools behind approval.
When to Use It
Use this pattern when:
- a server exposes more tools than one agent should see
- tool names are unclear or conflict with local tools
- a tool needs product permissions or audit records
- you need to verify required tools exist before startup succeeds
Architecture Shape
| Step | Purpose |
|---|---|
| connect server | get adapted Anvia tools |
| inspect definitions | verify name, description, and schema |
| validate required tools | fail fast for missing required capabilities |
| filter safe tools | expose only the tools this agent should use |
| wrap tools | rename, audit, permission-check, or normalize output when needed |
Inspect Definitions
import { connectMcp, mcp, type McpServer } from "@anvia/core";
const docsServer = await connectMcp(
mcp.http({
name: "docs",
url: "https://mcp.example.com/mcp",
}),
);
for (const tool of docsServer.tools) {
const definition = await tool.definition("");
logger.info({
server: docsServer.name,
tool: definition.name,
description: definition.description,
parameters: definition.parameters,
});
}Validate Required Tools
async function requireMcpTools(server: McpServer, names: string[]) {
const available = new Set(server.tools.map((tool) => tool.name));
const missing = names.filter((name) => !available.has(name));
if (missing.length > 0) {
throw new Error(`MCP server ${server.name} is missing tools: ${missing.join(", ")}`);
}
}
await requireMcpTools(docsServer, ["search_docs", "read_doc"]);Filter Tools
function pickMcpTools(server: McpServer, allowedNames: string[]) {
const allowed = new Set(allowedNames);
return server.tools.filter((tool) => allowed.has(tool.name));
}
const safeDocsTools = pickMcpTools(docsServer, ["search_docs", "read_doc"]);
const agent = new AgentBuilder("support", model)
.instructions("Use docs tools for public support documentation.")
.tools(safeDocsTools)
.defaultMaxTurns(3)
.build();Use .mcp([server]) when the agent should receive every tool from that server. Use .tools(filteredTools) when the agent should receive only selected tools.
Wrap Tools
Wrap an MCP tool when you need product-specific names, permissions, audit records, or normalized output.
import { createTool } from "@anvia/core";
import { z } from "zod";
const searchDocs = docsServer.tools.find((tool) => tool.name === "search_docs");
if (!searchDocs) {
throw new Error("docs MCP server is missing search_docs");
}
const searchInternalDocs = createTool({
name: "search_internal_docs",
description: "Search internal support documentation for the current tenant.",
input: z.object({
query: z.string().min(1),
}),
async execute({ query }) {
await permissions.require(scope.userId, "docs:read");
const result = await searchDocs.call({
query: `${query}\ntenant:${scope.tenantId}`,
});
await audit.write({
actorId: scope.userId,
action: "docs.search",
tenantId: scope.tenantId,
});
return result;
},
});Failure Modes
| Failure | Fix |
|---|---|
| server exposes unsafe tools | filter or wrap before registering |
| tool names conflict | wrap with product-specific names |
| schema is too loose | wrap with a stricter Zod schema |
| server changes tool names | validate required tools at startup |
| remote tool returns noisy output | wrap and normalize result shape |
Test Checklist
- Assert required tools exist after connection.
- Snapshot provider-facing tool definitions for critical MCP tools.
- Test wrapped tools with fake permission and audit services.
- Verify agents receive only allowed MCP tools.
- Inspect MCP metadata in Studio when available.
