@buildrlabs/mcp-registry-sdk
v0.1.3
Published
TypeScript SDK for the MCP Registry API
Maintainers
Readme
@buildrlabs/mcp-registry-sdk
Official TypeScript/JavaScript SDK for the Buildrlab MCP Registry - discover and integrate Model Context Protocol (MCP) servers into your applications.
Table of Contents
- Installation
- Getting Your API Key
- Quick Start
- Configuration
- API Reference
- Working with Results
- Error Handling
- TypeScript Support
- Examples
Installation
# npm
npm install @buildrlabs/mcp-registry-sdk
# yarn
yarn add @buildrlabs/mcp-registry-sdk
# pnpm
pnpm add @buildrlabs/mcp-registry-sdkGetting Your API Key
- Visit the Buildrlab MCP Registry and sign in
- Navigate to your dashboard
- Generate an API key
- Store it securely (environment variable recommended)
# .env file
MCP_REGISTRY_API_KEY=your-api-key-hereSecurity: Never commit your API key to version control. Always use environment variables.
Quick Start
import { McpRegistryClient } from '@buildrlabs/mcp-registry-sdk';
// Initialize the client
const client = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!
});
// List all available MCP servers
const { items: servers } = await client.listServers();
console.log(`Found ${servers.length} servers:`);
servers.forEach(server => {
console.log(`- ${server.name}: ${server.description}`);
});Configuration
Constructor Options
const client = new McpRegistryClient({
// Required: Your API key
apiKey: process.env.MCP_REGISTRY_API_KEY!,
// Optional: API environment (defaults to dev)
baseUrl: process.env.MCP_REGISTRY_API_URL
});| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| apiKey | string | Yes | - | Your MCP Registry API key |
| baseUrl | string | No | https://dev.mcp-registry.buildrlab.com | API base URL |
Environments
| Environment | URL |
|-------------|-----|
| Development | https://dev.mcp-registry.buildrlab.com (default) |
| Production | https://mcp-registry.buildrlab.com |
// Development (default)
const devClient = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!
});
// Production
const prodClient = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!,
baseUrl: 'https://mcp-registry.buildrlab.com'
});
// Using environment variable for flexibility
const client = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!,
baseUrl: process.env.MCP_REGISTRY_API_URL // Set per environment
});API Reference
listServers(options?)
Retrieve a list of MCP servers with optional filtering and pagination.
const response = await client.listServers(options);Parameters
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| limit | number | 50 | Items per page (1-100) |
| cursor | string | - | Pagination cursor from previous response |
| q | string | - | Search by name or description |
| hasRemote | boolean | - | Filter servers with remote connections |
| source | 'upstream' \| 'manual' | - | Filter by server source |
| fetchAll | boolean | false | Fetch all servers (ignores pagination) |
Response
interface ServersListResponse {
items: ServerSummary[]; // Array of server summaries
nextCursor: string | null; // Cursor for next page, null if no more pages
}
interface ServerSummary {
id: string; // Unique server identifier
name: string; // Server name
description: string; // Server description
version: string | null; // Server version
repository: string | null; // Source repository URL
hasRemote: boolean; // Has remote connection capability
hasLocal: boolean; // Has local installation option
source: 'upstream' | 'manual'; // Server source
}Examples
// Basic listing
const { items } = await client.listServers();
// Search for specific servers
const { items } = await client.listServers({ q: 'github' });
// Get servers with remote capability
const { items } = await client.listServers({ hasRemote: true });
// Paginate through results
const { items, nextCursor } = await client.listServers({ limit: 10 });
if (nextCursor) {
const nextPage = await client.listServers({ limit: 10, cursor: nextCursor });
}
// Fetch all servers at once
const { items: allServers } = await client.listServers({ fetchAll: true });getServer(id)
Retrieve detailed information about a specific MCP server.
const server = await client.getServer('server-id');Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| id | string | Yes | The server's unique identifier |
Response
interface ServerDetail {
id: string; // Unique server identifier
name: string; // Server name
description: string; // Server description
version: string | null; // Server version
repository: string | null; // Source repository URL
remotes: unknown[]; // Remote connection configurations
locals: unknown[]; // Local installation configurations
source: 'upstream' | 'manual'; // Server source
status: 'draft' | 'published'; // Publication status
updatedAt: string; // Last update timestamp (ISO 8601)
overrides?: ServerOverrides; // Custom overrides applied
}Example
const server = await client.getServer('github-mcp-server');
console.log(`Server: ${server.name}`);
console.log(`Description: ${server.description}`);
console.log(`Version: ${server.version}`);
console.log(`Repository: ${server.repository}`);
console.log(`Last Updated: ${new Date(server.updatedAt).toLocaleDateString()}`);
// Check connection options
if (server.remotes.length > 0) {
console.log('Remote connections available');
}
if (server.locals.length > 0) {
console.log('Local installation available');
}Working with Results
Iterating Over Servers
const { items: servers } = await client.listServers();
// Using forEach
servers.forEach(server => {
console.log(`${server.name} - ${server.description}`);
});
// Using for...of
for (const server of servers) {
console.log(`${server.name} v${server.version || 'unknown'}`);
}
// Using map to transform
const serverNames = servers.map(server => server.name);Filtering Results
const { items: servers } = await client.listServers();
// Find servers with repositories
const withRepos = servers.filter(server => server.repository !== null);
// Find servers with both remote and local options
const flexible = servers.filter(server => server.hasRemote && server.hasLocal);
// Group by source
const bySource = servers.reduce((acc, server) => {
acc[server.source] = acc[server.source] || [];
acc[server.source].push(server);
return acc;
}, {} as Record<string, typeof servers>);Pagination Helper
async function getAllServers(client: McpRegistryClient) {
const allServers: ServerSummary[] = [];
let cursor: string | undefined;
do {
const { items, nextCursor } = await client.listServers({
limit: 100,
cursor
});
allServers.push(...items);
cursor = nextCursor ?? undefined;
} while (cursor);
return allServers;
}
// Or simply use fetchAll
const { items: allServers } = await client.listServers({ fetchAll: true });Error Handling
The SDK provides detailed error information through the McpRegistryError class.
Basic Error Handling
import { McpRegistryClient, McpRegistryError } from '@buildrlabs/mcp-registry-sdk';
const client = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!
});
try {
const { items } = await client.listServers();
console.log(`Found ${items.length} servers`);
} catch (error) {
if (error instanceof McpRegistryError) {
console.error(`API Error: ${error.message}`);
console.error(`Status Code: ${error.statusCode}`);
} else {
console.error('Unexpected error:', error);
}
}Error Properties
class McpRegistryError extends Error {
message: string; // Human-readable error message
statusCode: number; // HTTP status code
isAuthError: boolean; // True for 401/403 errors
isNotFound: boolean; // True for 404 errors
}Handling Specific Errors
try {
const server = await client.getServer('non-existent-id');
} catch (error) {
if (error instanceof McpRegistryError) {
if (error.isAuthError) {
// 401 or 403 - Authentication/Authorization issue
console.error('API key is invalid or missing');
console.error('Please check your MCP_REGISTRY_API_KEY environment variable');
} else if (error.isNotFound) {
// 404 - Server not found
console.error('The requested server does not exist');
} else {
// Other API errors (500, etc.)
console.error(`API error (${error.statusCode}): ${error.message}`);
}
}
}Missing API Key
The SDK validates the API key at initialization:
// This throws immediately - no API call made
try {
const client = new McpRegistryClient({ apiKey: '' });
} catch (error) {
// McpRegistryError: "MCP Registry API key is required.
// Get your API key from the MCP Registry dashboard."
}Error Reference
| Status Code | isAuthError | isNotFound | Common Cause |
|-------------|---------------|--------------|--------------|
| 400 | false | false | Invalid request parameters |
| 401 | true | false | Missing or invalid API key |
| 403 | true | false | API key lacks permission |
| 404 | false | true | Server not found |
| 429 | false | false | Rate limit exceeded |
| 500 | false | false | Server error |
TypeScript Support
The SDK is written in TypeScript and exports all types for full type safety.
Importing Types
import {
McpRegistryClient,
McpRegistryError,
createMcpRegistryClient,
} from '@buildrlabs/mcp-registry-sdk';
import type {
// Client options
McpRegistryClientOptions,
ListServersOptions,
// Response types
ServerSummary,
ServerDetail,
ServersListResponse,
ServerDetailResponse,
// Enums
ServerSource, // 'upstream' | 'manual'
ServerStatus, // 'draft' | 'published'
// Other
ServerOverrides,
ErrorResponse,
} from '@buildrlabs/mcp-registry-sdk';Type-Safe Usage
import type { ServerSummary, ListServersOptions } from '@buildrlabs/mcp-registry-sdk';
// Options are fully typed
const options: ListServersOptions = {
limit: 25,
hasRemote: true,
source: 'upstream', // TypeScript ensures valid values
};
const { items } = await client.listServers(options);
// Results are fully typed
items.forEach((server: ServerSummary) => {
// TypeScript knows all available properties
console.log(server.name); // string
console.log(server.version); // string | null
console.log(server.hasRemote); // boolean
});Examples
Express.js API Endpoint
import express from 'express';
import { McpRegistryClient, McpRegistryError } from '@buildrlabs/mcp-registry-sdk';
const app = express();
const client = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!
});
app.get('/api/mcp-servers', async (req, res) => {
try {
const { q, hasRemote } = req.query;
const { items } = await client.listServers({
q: q as string,
hasRemote: hasRemote === 'true',
});
res.json({ servers: items });
} catch (error) {
if (error instanceof McpRegistryError) {
res.status(error.statusCode).json({ error: error.message });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});Next.js Server Component
import { McpRegistryClient } from '@buildrlabs/mcp-registry-sdk';
const client = new McpRegistryClient({
apiKey: process.env.MCP_REGISTRY_API_KEY!
});
export default async function McpServersPage() {
const { items: servers } = await client.listServers({ limit: 20 });
return (
<div>
<h1>MCP Servers</h1>
<ul>
{servers.map(server => (
<li key={server.id}>
<strong>{server.name}</strong>
<p>{server.description}</p>
</li>
))}
</ul>
</div>
);
}Search with Debounce (React)
import { useState, useEffect } from 'react';
import { McpRegistryClient, ServerSummary } from '@buildrlabs/mcp-registry-sdk';
const client = new McpRegistryClient({
apiKey: process.env.NEXT_PUBLIC_MCP_REGISTRY_API_KEY!
});
function useServerSearch(query: string) {
const [servers, setServers] = useState<ServerSummary[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!query.trim()) {
setServers([]);
return;
}
const timer = setTimeout(async () => {
setLoading(true);
setError(null);
try {
const { items } = await client.listServers({ q: query });
setServers(items);
} catch (err) {
setError(err instanceof Error ? err.message : 'Search failed');
} finally {
setLoading(false);
}
}, 300);
return () => clearTimeout(timer);
}, [query]);
return { servers, loading, error };
}CLI Tool
#!/usr/bin/env node
import { McpRegistryClient, McpRegistryError } from '@buildrlabs/mcp-registry-sdk';
async function main() {
const apiKey = process.env.MCP_REGISTRY_API_KEY;
if (!apiKey) {
console.error('Error: MCP_REGISTRY_API_KEY environment variable is required');
process.exit(1);
}
const client = new McpRegistryClient({ apiKey });
const [command, ...args] = process.argv.slice(2);
try {
switch (command) {
case 'list':
const { items } = await client.listServers({ fetchAll: true });
console.log(`Found ${items.length} servers:\n`);
items.forEach(s => console.log(` ${s.name} - ${s.description}`));
break;
case 'get':
if (!args[0]) {
console.error('Usage: mcp-registry get <server-id>');
process.exit(1);
}
const server = await client.getServer(args[0]);
console.log(JSON.stringify(server, null, 2));
break;
case 'search':
if (!args[0]) {
console.error('Usage: mcp-registry search <query>');
process.exit(1);
}
const { items: results } = await client.listServers({ q: args.join(' ') });
console.log(`Found ${results.length} matching servers:\n`);
results.forEach(s => console.log(` ${s.name} - ${s.description}`));
break;
default:
console.log('Usage: mcp-registry <command> [args]');
console.log('Commands: list, get <id>, search <query>');
}
} catch (error) {
if (error instanceof McpRegistryError) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
throw error;
}
}
main();License
MIT
