Skip to content
Unverified: This page has not yet been anchored to automated code tests.

How-To: Build AI Agents and MCP Tools

Vox is an AI-native language, meaning it bridges the gap between high-level business logic and the Model Context Protocol (MCP) without glue code. Any Vox function can become an MCP tool with a single keyword.

Any Vox function can be exported as an MCP tool using the tool keyword.

tool "Calculate the sum of two integers" sum(a: int, b: int) to int {
return a + b
}
  • Type Safety: If your function returns a Result[T, E], Vox handles the MCP error response mapping for you.
  • Zero Configuration: No manifests to maintain. The tool declaration is the manifest.
  • Auto-Discovery: Tools are automatically discovered by the vox-orchestrator during development.

[!NOTE] The agent declaration is tombstoned — it is not in the active grammar. Define agent behavior as a plain function, and expose capabilities via tool/resource declarations for MCP discovery instead.

fn assistant_greet(name: str) to str {
return "Hello " + name + ", how can I assist you today?"
}

Since there is no dedicated agent construct, “handoffs” between agent-like functions are just ordinary function calls or MCP tool invocations orchestrated by vox-orchestrator.


To expose your tools to a local AI assistant (like Claude Desktop or Cursor):

  1. Run the MCP server:
    Terminal window
    vox run src/main.vox
  2. Observe Logs: The orchestrator will list all registered tools and resources.
  3. Connect: Add the generated endpoint to your claude_desktop_config.json.

Never guess if a tool works. You can test your tool directly against the generated server. (Note: A dedicated vox test-mcp CLI is an aspirational future feature).

Terminal window
# Test the 'search_docs' endpoint manually using standard tools
curl -X POST http://localhost:8080/api/tools/search_docs -d '{"query": "actors"}'

By default, a tool has the same permissions as your compiled Vox binary. Use the @require decorator to add runtime guardrails:

table User {
name: str
}
tool "Delete user data"
@require(auth.is_admin(caller))
delete_data(id: Id[User]) to Result[str] {
db.User.delete(id)
return Ok("deleted")
}

If the precondition fails, the MCP tool returns a “Tool execution failed” error to the model with the specific violation reason, preventing the LLM from attempting unauthorized actions.


Related Reference: