Language Bindings
JavaScript
ZAP JavaScript SDK - Node.js and browser support
JavaScript Binding
The JavaScript binding supports both Node.js and browser environments with full TypeScript types.
Installation
npm install @zap-protocol/zap
# or
pnpm add @zap-protocol/zap
# or
yarn add @zap-protocol/zapQuick Start
import { Zap, ClientInfo, ToolCall } from '@zap-protocol/zap';
async function main() {
// Connect to ZAP server
const client = await Zap.connect('zap://localhost:9000');
// Initialize
const server = await client.init({
name: 'my-agent',
version: '1.0.0',
});
console.log(`Connected to: ${server.name} v${server.version}`);
// List tools
const tools = await client.listTools();
for (const tool of tools) {
console.log(` ${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('Error:', result.error);
} else {
console.log('Result:', result.content);
}
await client.close();
}
main().catch(console.error);Client API
Connection
// Simple connection
const client = await Zap.connect('zap://localhost:9000');
// With options
const client = await Zap.connect('zap://localhost:9000', {
timeout: 30000,
identity: identity,
});Tools
// List tools
const tools: Tool[] = await client.listTools();
// Call tool
const result: ToolResult = await client.callTool({
id: 'call-1',
name: 'my_tool',
args: JSON.stringify({ param: 'value' }),
});
// Parse result
const content = JSON.parse(result.content);Resources
// List resources
const resources: Resource[] = await client.listResources();
// Read resource
const content: ResourceContent = await client.readResource('file:///etc/hosts');
console.log(content.text);
// Subscribe to updates
const stream = await client.subscribe('file:///var/log/app.log');
for await (const update of stream) {
console.log('Update:', update.content);
}Prompts
// List prompts
const prompts: Prompt[] = await client.listPrompts();
// Get prompt messages
const messages: PromptMessage[] = await client.getPrompt('code_review', {
topic: 'javascript',
});Gateway
import { Gateway, ServerConfig, Transport, Auth } from '@zap-protocol/zap';
// Create gateway
const gateway = new Gateway();
// Add MCP server
const fsId = await gateway.addServer(
'filesystem',
'stdio://npx -y @modelcontextprotocol/server-filesystem /tmp',
{ transport: Transport.STDIO }
);
// Add with authentication
const ghId = await gateway.addServer(
'github',
'stdio://npx -y @modelcontextprotocol/server-github',
{
transport: Transport.STDIO,
auth: { bearer: process.env.GITHUB_TOKEN },
timeout: 60000,
}
);
// List all tools
const tools = await gateway.listTools();
// Check status
const status = await gateway.serverStatus(fsId);TypeScript Types
Full TypeScript definitions:
import type {
Zap,
Tool,
ToolCall,
ToolResult,
Resource,
ResourceContent,
Prompt,
PromptMessage,
ServerInfo,
ClientInfo,
Capabilities,
Metadata,
} from '@zap-protocol/zap';
interface MyToolArgs {
path: string;
}
async function callMyTool(client: Zap, path: string): Promise<string> {
const result = await client.callTool({
id: crypto.randomUUID(),
name: 'read_file',
args: JSON.stringify({ path } satisfies MyToolArgs),
});
if (result.error) {
throw new Error(result.error);
}
return result.content;
}Error Handling
import { ZapError, DisconnectedError, TimeoutError } from '@zap-protocol/zap';
try {
const result = await client.callTool(call);
} catch (error) {
if (error instanceof DisconnectedError) {
console.log('Connection lost, reconnecting...');
await client.reconnect();
} else if (error instanceof TimeoutError) {
console.log('Request timed out');
} else if (error instanceof ZapError) {
console.log('ZAP error:', error.message);
}
}Browser Support
For browser environments:
import { Zap } from '@zap-protocol/zap/browser';
// WebSocket connection
const client = await Zap.connect('zap+ws://localhost:9000');Server Implementation (Node.js)
import { Server, ZapHandler } from '@zap-protocol/zap/server';
import type {
ClientInfo,
ServerInfo,
Tool,
ToolCall,
ToolResult,
} from '@zap-protocol/zap';
class MyHandler implements ZapHandler {
async init(client: ClientInfo): Promise<ServerInfo> {
return {
name: 'my-server',
version: '1.0.0',
capabilities: {
tools: true,
resources: true,
prompts: false,
logging: true,
},
};
}
async listTools(): Promise<Tool[]> {
return [
{
name: 'hello',
description: 'Says hello',
schema: JSON.stringify({
type: 'object',
properties: { name: { type: 'string' } },
}),
annotations: {},
},
];
}
async callTool(call: ToolCall): Promise<ToolResult> {
if (call.name === 'hello') {
const args = JSON.parse(call.args);
const name = args.name || 'World';
return {
id: call.id,
content: `Hello, ${name}!`,
};
}
return {
id: call.id,
error: 'Unknown tool',
};
}
// ... other methods
}
const server = new Server(new MyHandler());
server.listen(9000);Async Patterns
Concurrent Calls
async function callToolsConcurrently(
client: Zap,
calls: ToolCall[]
): Promise<ToolResult[]> {
return Promise.all(calls.map((call) => client.callTool(call)));
}AbortController
const controller = new AbortController();
// Cancel after 10 seconds
setTimeout(() => controller.abort(), 10000);
try {
const result = await client.callTool(call, {
signal: controller.signal,
});
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request aborted');
}
}Testing
import { describe, it, expect, vi } from 'vitest';
import { Zap } from '@zap-protocol/zap';
describe('ZAP Client', () => {
it('should list tools', async () => {
const mockClient = {
listTools: vi.fn().mockResolvedValue([
{ name: 'test', description: 'Test tool' },
]),
} as unknown as Zap;
const tools = await mockClient.listTools();
expect(tools).toHaveLength(1);
expect(tools[0].name).toBe('test');
});
});Examples
Full examples at:
Last updated on