Veefore docs

Call MCP tools from your code

A step-by-step guide to calling an MCP server's tools through Veefore from a TypeScript or Python agent with the SDK.

This guide is for an agent you write yourself. Your code calls MCP tools through the Veefore SDK instead of straight at the server, and Veefore checks each call, calls the server with its own credential, and returns the server's answer unchanged.

If your code already calls the server with the official MCP SDK, the CLI can make this change for you: see Reroute MCP calls with the CLI. If you do not write code at all, use an MCP client instead.

You will need: Node.js 20.10 or newer (and Python 3.9+ for a Python agent), an agent project, and a Veefore account. The example uses DeepWiki, which needs no token.

#Step by step

Set up the project with the CLI

In your agent project:

bash
npm install -g veefore
cd your-agent-project
veefore

The CLI opens the console to sign you in, creates an agent for this project in the Development environment, and writes two files:

  • veefore.config.json — settings, no secrets; commit it.
  • .env.local — the agent's private key and the gateway address; gitignored. The SDK reads it.

It also adds a starter policy as a draft. Answer y when it asks. If it offers to change your code and you have no tools to wrap yet, you can skip that.

Connect the MCP server

  1. Sign in at console.veefore.com and set the Environment switcher at the top to Development — the environment the CLI created your agent in.
  2. Open MCP → Connect server.
  3. Paste https://mcp.deepwiki.com/mcp, tick I know who runs this server and trust it, and click Connect.
  4. Under Agent, tick the agent the CLI created (named after your project).
  5. Keep the tools you want ticked and click Authorize N tools.

The server's slug — deepwiki here — is how your code names it. It is on the server's page and in its address.

Install the SDK

bash
npm install @veefore/sdk@1.8.0

mcpServer() needs 1.8.0 or later.

bash
pip install veefore-py==1.7.0

Call a tool

ts
import { mcpServer } from '@veefore/sdk';

const result = await mcpServer('deepwiki').callTool({
  name: 'read_wiki_structure',
  arguments: { repoName: 'modelcontextprotocol/typescript-sdk' },
});

console.log(result.content); // the server's own tools/call result

mcpServer() builds its client from .env.local. It has the same callTool as the official MCP SDK's client, so if you already use one, change only the receiver:

ts
// Before
const result = await client.callTool({ name: 'read_wiki_structure', arguments });
// After
const result = await mcpServer('deepwiki').callTool({ name: 'read_wiki_structure', arguments });
python
from veefore import guard_client

decision = guard_client().mcp_call(
    server="deepwiki",
    tool="read_wiki_structure",
    arguments={"repoName": "modelcontextprotocol/typescript-sdk"},
)
print(decision.result)  # the server's own tools/call result

guard_client() builds its client from .env.local, found from the current directory upwards. Variables already set in the environment win, which is how you configure it in production.

Run it, and check it worked

Run your agent as you normally do. To watch decisions as they happen, run veefore dev in another terminal in the project.

Then open Actions in the console. The call is listed with your agent, the tool mcp_deepwiki_read_wiki_structure, the decision and the time.

Decide what happens when a person must approve

If a rule requires approval, the SDK waits for the decision by default. A chat agent usually should not block its turn, so it can defer instead:

ts
import { isAwaitingApproval, mcpServer } from '@veefore/sdk';

const outcome = await mcpServer('deepwiki', { onApproval: 'defer' }).callTool({
  name: 'ask_wiki_question',
  arguments: { repoName: 'facebook/react', question: 'How does reconciliation work?' },
});
if (isAwaitingApproval(outcome)) return outcome.say; // tell the user, carry on

On a later turn, resumeApprovals() finds the decision and, if it was approved, performs the call once. The modes are 'wait' (default), 'defer' and 'throw'; VEEFORE_APPROVAL_MODE sets the default for the project. See Handle approvals.

Turn on protection

New environments start in Observe: calls run and are recorded, and nothing is blocked. When you have watched it for a while:

bash
veefore policies test
veefore deploy --mode ENFORCE --reason "MCP tools reviewed"

policies test shows which recent calls would start being refused before anything changes. See What your rules do for how MCP calls are decided.

#When a call is refused

Under Enforce, a refused call throws VeeforeBlockedError in TypeScript (and raises in Python) with the reason, and the server is never contacted:

ts
import { VeeforeBlockedError, mcpServer } from '@veefore/sdk';

try {
  await mcpServer('deepwiki').callTool({ name: 'ask_wiki_question', arguments });
} catch (error) {
  if (error instanceof VeeforeBlockedError) console.warn(error.message);
  else throw error;
}

MCP troubleshooting lists every refusal and its fix.

#Without the SDK

The SDK calls one gateway endpoint, POST /gateway/v1/mcp/call, with a session token from the agent's signed identity. Any language can do the same; see Sign your own assertion and the JavaScript SDK reference for mcpCall().

Identity, authority, policy and enforcement for autonomous AI agents.