Getting Started
Install ZAP and build your first AI agent
This guide walks you through installing ZAP and building your first AI agent.
Prerequisites
- Cap'n Proto compiler (
capnp) - Language-specific toolchain (Rust, Go, Python, etc.)
macOS
Linux
Windows
brew install capnp# Debian/Ubuntu
sudo apt-get install capnproto libcapnp-dev
# Fedora
sudo dnf install capnproto capnproto-devel# Using Chocolatey
choco install capnproto
# Or download from https://capnproto.org/install.htmlInstallation
Rust
Go
Python
JavaScript
cargo add zap-proto[dependencies]
zap-proto = "0.1"
tokio = { version = "1", features = ["full"] }go get github.com/zap-proto/gopip install zap-protoOr with uv:
uv add zap-protonpm install @zap-proto/zapOr with pnpm:
pnpm add @zap-proto/zapQuick Start
1
Create a ZAP Client
Rust
Go
Python
JavaScript
use zap_protocol::{Zap, ClientInfo};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Connect to ZAP server
let client = Zap::connect("zap://localhost:9000").await?;
// Initialize with client info
let server_info = client.init(ClientInfo {
name: "my-agent".into(),
version: "1.0.0".into(),
}).await?;
println!("Connected to: {} v{}", server_info.name, server_info.version);
println!("Capabilities: {:?}", server_info.capabilities);
Ok(())
}package main
import (
"context"
"fmt"
"log"
zap "github.com/zap-proto/go"
)
func main() {
ctx := context.Background()
// Connect to ZAP server
client, err := zap.Connect(ctx, "zap://localhost:9000")
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Initialize with client info
serverInfo, err := client.Init(ctx, &zap.ClientInfo{
Name: "my-agent",
Version: "1.0.0",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connected to: %s v%s\n", serverInfo.Name, serverInfo.Version)
}import asyncio
from zap_protocol import Zap, ClientInfo
async def main():
# Connect to ZAP server
client = await Zap.connect("zap://localhost:9000")
# Initialize with client info
server_info = await client.init(ClientInfo(
name="my-agent",
version="1.0.0"
))
print(f"Connected to: {server_info.name} v{server_info.version}")
print(f"Capabilities: {server_info.capabilities}")
asyncio.run(main())import { Zap, ClientInfo } from '@zap-proto/zap';
async function main() {
// Connect to ZAP server
const client = await Zap.connect('zap://localhost:9000');
// Initialize with client info
const serverInfo = await client.init({
name: 'my-agent',
version: '1.0.0'
});
console.log(`Connected to: ${serverInfo.name} v${serverInfo.version}`);
console.log('Capabilities:', serverInfo.capabilities);
}
main().catch(console.error);2
List and Call Tools
Rust
Go
Python
JavaScript
// List available tools
let tools = client.list_tools().await?;
for tool in &tools {
println!("Tool: {} - {}", tool.name, tool.description);
}
// Call a tool
let result = client.call_tool(&ToolCall {
id: uuid::Uuid::new_v4().to_string(),
name: "read_file".into(),
args: serde_json::to_vec(&json!({
"path": "/etc/hosts"
}))?,
metadata: Default::default(),
}).await?;
if let Some(error) = result.error {
eprintln!("Tool error: {}", error);
} else {
let content: serde_json::Value = serde_json::from_slice(&result.content)?;
println!("Result: {}", content);
}// List available tools
tools, err := client.ListTools(ctx)
if err != nil {
log.Fatal(err)
}
for _, tool := range tools {
fmt.Printf("Tool: %s - %s\n", tool.Name, tool.Description)
}
// Call a tool
result, err := client.CallTool(ctx, &zap.ToolCall{
ID: uuid.New().String(),
Name: "read_file",
Args: []byte(`{"path": "/etc/hosts"}`),
})
if err != nil {
log.Fatal(err)
}
if result.Error != "" {
log.Printf("Tool error: %s", result.Error)
} else {
fmt.Printf("Result: %s\n", result.Content)
}# List available tools
tools = await client.list_tools()
for tool in tools:
print(f"Tool: {tool.name} - {tool.description}")
# Call a tool
result = await client.call_tool(ToolCall(
id=str(uuid.uuid4()),
name="read_file",
args=json.dumps({"path": "/etc/hosts"}).encode()
))
if result.error:
print(f"Tool error: {result.error}")
else:
content = json.loads(result.content)
print(f"Result: {content}")// List available tools
const tools = await client.listTools();
for (const tool of tools) {
console.log(`Tool: ${tool.name} - ${tool.description}`);
}
// Call a tool
const result = await client.callTool({
id: crypto.randomUUID(),
name: 'read_file',
args: JSON.stringify({ path: '/etc/hosts' })
});
if (result.error) {
console.error('Tool error:', result.error);
} else {
const content = JSON.parse(result.content);
console.log('Result:', content);
}3
Bridge MCP Servers
Rust
Go
Python
JavaScript
use zap_protocol::{Gateway, ServerConfig, Transport};
// Create gateway
let gateway = Gateway::new().await?;
// Add MCP filesystem server
let fs_id = gateway.add_server(
"filesystem",
"stdio://npx -y @modelcontextprotocol/server-filesystem /tmp",
ServerConfig {
transport: Transport::Stdio,
..Default::default()
},
).await?;
// Add MCP GitHub server
let gh_id = gateway.add_server(
"github",
"stdio://npx -y @modelcontextprotocol/server-github",
ServerConfig {
transport: Transport::Stdio,
auth: Some(Auth::Bearer(std::env::var("GITHUB_TOKEN")?)),
..Default::default()
},
).await?;
// Now use gateway.list_tools() to get tools from all servers
let all_tools = gateway.list_tools().await?;// Create gateway
gateway := zap.NewGateway()
// Add MCP filesystem server
fsID, err := gateway.AddServer(ctx, "filesystem",
"stdio://npx -y @modelcontextprotocol/server-filesystem /tmp",
&zap.ServerConfig{
Transport: zap.TransportStdio,
})
if err != nil {
log.Fatal(err)
}
// Add MCP GitHub server
ghID, err := gateway.AddServer(ctx, "github",
"stdio://npx -y @modelcontextprotocol/server-github",
&zap.ServerConfig{
Transport: zap.TransportStdio,
Auth: &zap.Auth{
Bearer: os.Getenv("GITHUB_TOKEN"),
},
})
if err != nil {
log.Fatal(err)
}
// Get tools from all servers
allTools, _ := gateway.ListTools(ctx)from zap_protocol import Gateway, ServerConfig, Transport, Auth
import os
# Create gateway
gateway = Gateway()
# Add MCP filesystem server
fs_id = await gateway.add_server(
"filesystem",
"stdio://npx -y @modelcontextprotocol/server-filesystem /tmp",
ServerConfig(transport=Transport.STDIO)
)
# Add MCP GitHub server
gh_id = await gateway.add_server(
"github",
"stdio://npx -y @modelcontextprotocol/server-github",
ServerConfig(
transport=Transport.STDIO,
auth=Auth(bearer=os.environ["GITHUB_TOKEN"])
)
)
# Get tools from all servers
all_tools = await gateway.list_tools()import { Gateway, ServerConfig, Transport, Auth } from '@zap-proto/zap';
// Create gateway
const gateway = new Gateway();
// Add MCP filesystem server
const fsId = await gateway.addServer(
'filesystem',
'stdio://npx -y @modelcontextprotocol/server-filesystem /tmp',
{ transport: Transport.STDIO }
);
// Add MCP GitHub server
const ghId = await gateway.addServer(
'github',
'stdio://npx -y @modelcontextprotocol/server-github',
{
transport: Transport.STDIO,
auth: { bearer: process.env.GITHUB_TOKEN }
}
);
// Get tools from all servers
const allTools = await gateway.listTools();Next Steps
- Schema Language - Learn the Cap'n Proto schema format
- Protocol Specification - Understand the wire format
- Language Bindings - SDK documentation for your language
- Post-Quantum Security - Enable PQ cryptography
Overview
Understanding ZAP architecture and core concepts
Schema LanguageCap'n Proto schema reference for ZAP
Protocol SpecificationZAP wire format, encoding, and RPC semantics
The Local RouterOne ZAP router per user, embedded in every process that speaks ZAP — no daemon
Language BindingsZAP SDK documentation for all supported languages
Advanced TopicsPost-quantum cryptography, consensus, identity, and blockchain integration
Was this page useful?