Skip to content

Library API

Use OpalServe programmatically in your Node.js applications. The library provides the same functionality as the CLI and HTTP API, exposed as TypeScript classes.

Installation

bash
npm install opalserve

Quick Start

typescript
import { OpalServeRegistry } from 'opalserve';

const registry = await OpalServeRegistry.create({
  mode: 'local',
  servers: [
    {
      name: 'my-files',
      transport: {
        type: 'stdio',
        command: 'npx',
        args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],
      },
    },
  ],
});

await registry.start();

// List all tools
const tools = registry.listTools();
console.log(`${tools.length} tools available`);

// Search
const results = registry.searchTools('read file');
console.log(results);

// Call a tool
const result = await registry.callTool('my-files:read_file', {
  path: '/path/to/file.txt',
});
console.log(result);

// Cleanup
await registry.stop();

OpalServeRegistry

The main entry point. Manages servers, tools, knowledge base, and the database.

OpalServeRegistry.create(config?)

Create a new registry instance. Loads config from cosmiconfig if no override provided.

typescript
// Load config automatically
const registry = await OpalServeRegistry.create();

// With config overrides
const registry = await OpalServeRegistry.create({
  mode: 'local',
  gateway: { port: 8080 },
  logging: { level: 'debug' },
});

// Full config
const registry = await OpalServeRegistry.create({
  mode: 'team-server',
  servers: [/* ... */],
  auth: { enabled: true, jwtSecret: process.env.JWT_SECRET },
  team: { name: 'My Team' },
});

registry.start()

Connect to all configured servers and index their tools. Returns a promise that resolves when all servers are connected.

typescript
await registry.start();
// All servers connected, tools indexed

registry.stop()

Disconnect all servers and close the database.

typescript
await registry.stop();

registry.addServer(config)

Add and connect a new MCP server at runtime.

typescript
await registry.addServer({
  name: 'my-github',
  description: 'GitHub repositories',
  transport: {
    type: 'stdio',
    command: 'npx',
    args: ['-y', '@modelcontextprotocol/server-github'],
    env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN! },
  },
  tags: ['code', 'github'],
});

registry.removeServer(name)

Disconnect and remove a server and its indexed tools.

typescript
await registry.removeServer('my-github');

registry.listServers()

Returns all registered servers with their connection status.

typescript
const servers = registry.listServers();
// [{ name: 'github', status: 'connected', toolCount: 8, ... }]

registry.listTools(serverFilter?)

Returns all indexed tools. Optionally filter by server name(s).

typescript
const allTools = registry.listTools();
const githubTools = registry.listTools(['github']);

registry.searchTools(query, options?)

Full-text search across all tools.

typescript
const results = registry.searchTools('create issue', {
  limit: 5,
  serverFilter: ['github'],
});
// [{ id: 'github:create_issue', name: 'create_issue', score: 0.95, ... }]

registry.callTool(toolId, args?)

Proxy a tool call to the backend server.

typescript
const result = await registry.callTool('github:create_issue', {
  owner: 'my-org',
  repo: 'my-repo',
  title: 'Bug report',
  body: 'Steps to reproduce...',
});
// { content: [{ type: 'text', text: 'Created issue #42' }] }

registry.healthCheck(serverName?)

Check health of registered servers.

typescript
// All servers
const health = await registry.healthCheck();

// Specific server
const githubHealth = await registry.healthCheck('github');

KnowledgeBase

Manage the shared knowledge base for AI tool context.

Creating an instance

typescript
import { KnowledgeBase } from 'opalserve';

const kb = new KnowledgeBase({
  storagePath: '~/.opalserve/data.db',
  chunkSize: 512,
  chunkOverlap: 64,
});

Or access it from the registry:

typescript
const kb = registry.knowledgeBase;

kb.addDocument(options)

Add a document to the knowledge base.

typescript
const doc = await kb.addDocument({
  title: 'Deployment Guide',
  content: '# How to Deploy\n\nMerge to main and the pipeline will...',
  tags: ['ops', 'deployment'],
});
// { id: 'doc_a1b2c3', title: 'Deployment Guide', chunks: 3 }

kb.search(query, options?)

Search the knowledge base.

typescript
const results = await kb.search('deployment process', {
  limit: 5,
  tags: ['ops'],
});
// [{ documentId: 'doc_a1b2c3', title: 'Deployment Guide', chunk: '...', score: 0.92 }]

kb.listDocuments(options?)

List all documents.

typescript
const docs = await kb.listDocuments({ tags: ['ops'] });

kb.removeDocument(id)

Remove a document and its chunks.

typescript
await kb.removeDocument('doc_a1b2c3');

UsageTracker

Track and query usage statistics.

Creating an instance

typescript
import { UsageTracker } from 'opalserve';

const tracker = new UsageTracker({
  storagePath: '~/.opalserve/data.db',
});

Or access from the registry:

typescript
const tracker = registry.usageTracker;

tracker.recordRequest(event)

Record an API request event.

typescript
tracker.recordRequest({
  userId: 'usr_a1b2c3',
  endpoint: '/api/v1/tools/github:create_issue/call',
  method: 'POST',
  toolId: 'github:create_issue',
  statusCode: 200,
  latencyMs: 234,
});

tracker.getStats(options)

Query usage statistics.

typescript
const stats = await tracker.getStats({
  period: '24h',
});
// { totalRequests: 847, toolCalls: 312, activeUsers: 5, ... }

const userStats = await tracker.getStats({
  period: '7d',
  userId: 'usr_a1b2c3',
});

tracker.getTopTools(options)

Get the most-used tools.

typescript
const topTools = await tracker.getTopTools({ period: '7d', limit: 10 });
// [{ toolId: 'github:create_issue', calls: 187 }, ...]

Auth Helpers

Utilities for authentication and user management in team-server mode.

typescript
import { AuthService } from 'opalserve';

const auth = new AuthService({
  jwtSecret: process.env.JWT_SECRET!,
  sessionTtl: 86400,
});

// Create a user
const user = await auth.createUser({
  email: 'alice@company.com',
  password: 'secure-password',
  role: 'developer',
});

// Generate a JWT token
const token = auth.generateToken(user);

// Verify a token
const payload = auth.verifyToken(token);
// { userId: 'usr_a1b2c3', email: 'alice@company.com', role: 'developer' }

// Create an API key
const apiKey = await auth.createApiKey({
  userId: user.id,
  name: 'CI/CD',
  expiresIn: 2592000,
});
// { id: 'key_d4e5f6', key: 'osk_abc123...' }

// Verify an API key
const keyUser = await auth.verifyApiKey('osk_abc123...');

Starting the HTTP Server

typescript
import { OpalServeRegistry, startServer } from 'opalserve';

const registry = await OpalServeRegistry.create();
await registry.start();

const app = await startServer(registry, {
  port: 3456,
  host: '0.0.0.0',
  cors: ['https://dashboard.company.com'],
  dashboard: true,
});

// app is a Fastify instance
console.log(`Server listening on ${app.server.address()}`);

MCP Gateway

Start OpalServe as an MCP server for integration with MCP clients.

typescript
import { OpalServeRegistry, McpGateway } from 'opalserve';

const registry = await OpalServeRegistry.create();
await registry.start();

const gateway = new McpGateway(registry);
await gateway.connectStdio(); // Connects via stdio transport

See the MCP Gateway page for details on exposed tools and client configuration.


Events

The registry emits events for server lifecycle changes.

typescript
registry.on('server:connected', (name: string, toolCount: number) => {
  console.log(`${name} connected with ${toolCount} tools`);
});

registry.on('server:disconnected', (name: string) => {
  console.log(`${name} disconnected`);
});

registry.on('server:error', (name: string, error: Error) => {
  console.error(`${name} error: ${error.message}`);
});

registry.on('server:reconnecting', (name: string, attempt: number) => {
  console.log(`${name} reconnecting (attempt ${attempt})`);
});

registry.on('tools:indexed', (serverName: string, count: number) => {
  console.log(`Indexed ${count} tools from ${serverName}`);
});

TypeScript Types

All public types are exported and can be imported directly:

typescript
import type {
  ServerConfig,
  TransportConfig,
  ToolDefinition,
  SearchResult,
  OpalServeConfig,
  UserRole,
  UsageStats,
  Document,
  DocumentChunk,
} from 'opalserve';

Types are derived from Zod schemas, so you get both runtime validation and static type checking.

Released under the MIT License.