MCP Integration
Use Veto with Model Context Protocol (MCP) tool definitions.
Veto supports Model Context Protocol (MCP) tool definitions natively. The SDK auto-detects MCP format and converts it transparently.
This page covers SDK-level integration: wrapping MCP tool definitions in your own code. If you want to protect an MCP server you don't own or can't modify, skip to the MCP Gateway guide instead.
Quick start
Pass MCP tool definitions directly to veto.wrap():
import { Veto } from 'veto-sdk';
const veto = await Veto.init();
const wrappedTools = veto.wrap(mcpToolDefinitions);No adapter code needed. The SDK detects MCP tools by checking for inputSchema (the MCP convention) instead of parameters (OpenAI convention) and converts automatically.
Runnable SDK example
See:
packages/sdk/examples/mcp/mcp_agent.ts
The example shows:
veto.guard(...)preflight checks before forwarding callsveto.wrapMCPTools(...)execution-time enforcement for MCP tool calls
How MCP tools differ
MCP tools use inputSchema instead of parameters:
// MCP tool format
const mcpTool = {
name: "read_file",
description: "Read a file from disk",
inputSchema: {
type: "object",
properties: {
path: { type: "string" },
},
required: ["path"],
},
};
// OpenAI tool format (what Veto normalizes to internally)
const openAITool = {
type: "function",
function: {
name: "read_file",
description: "Read a file from disk",
parameters: {
type: "object",
properties: {
path: { type: "string" },
},
required: ["path"],
},
},
};When you pass MCP tools to veto.wrap(), the SDK converts inputSchema to parameters internally. Policies and rules reference tool arguments the same way regardless of the source format.
Manual adapter
For advanced use cases, you can use the adapter functions directly:
import { fromMCP, isMCPTool } from 'veto-sdk/providers';
// Check if a tool is MCP format
if (isMCPTool(tool)) {
const normalized = fromMCP(tool);
// normalized has OpenAI-style `parameters` instead of `inputSchema`
}Example: MCP server with Veto policies
import { Veto } from 'veto-sdk';
// Your MCP server tools
const mcpTools = [
{
name: "execute_command",
description: "Run a shell command",
inputSchema: {
type: "object",
properties: {
command: { type: "string" },
cwd: { type: "string" },
},
required: ["command"],
},
},
{
name: "write_file",
description: "Write content to a file",
inputSchema: {
type: "object",
properties: {
path: { type: "string" },
content: { type: "string" },
},
required: ["path", "content"],
},
},
];
// Wrap with Veto policies
const veto = await Veto.init();
const safeMcpTools = veto.wrap(mcpTools);With a YAML rule like:
rules:
- id: restrict-commands
name: Block dangerous shell commands
action: block
tools:
- execute_command
conditions:
- field: arguments.command
operator: matches
value: "^(rm -rf|sudo|chmod 777)"Exports
| Import | What |
|---|---|
fromMCP | Convert a single MCP tool to Veto's internal format |
isMCPTool | Type guard — returns true if the tool has inputSchema |
MCPTool | TypeScript type for MCP tool definitions |
MCPToolResult | TypeScript type for MCP tool results |
All available from veto-sdk/providers.
Not your MCP server?
If you're connecting to a third-party MCP server or want to enforce policies without modifying the server code, use the MCP Gateway instead.
The gateway runs as a proxy: your MCP client calls POST /v1/mcp/:slug (managed) or veto mcp serve (self-hosted), Veto validates every tools/call against your policies, and the upstream receives the request only if it passes. No SDK, no code changes on the server side.