npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

xyne-bridge-sdk

v1.2.0

Published

Xyne Bridge SDK - Production-grade TypeScript SDK for registering backend APIs with the MCP Gateway

Readme

Xyne Bridge SDK

Production-grade TypeScript SDK for registering backend REST APIs as MCP (Model Context Protocol) tools.

Overview

Xyne Bridge SDK enables you to:

  • ✅ Register REST API endpoints as discoverable tools
  • ✅ Define input/output schemas for APIs
  • ✅ Authenticate with tenantId API keys
  • ✅ Automatically send heartbeats to gateway
  • ✅ Scale across multi-service architectures

Installation

npm install xyne-bridge-sdk

Quick Start

import { createBridge } from "xyne-bridge-sdk";

// Initialize SDK
const bridge = createBridge({
  serviceName: "orders-service",
  backendId: "orders-prod-001",
  gatewayUrl: "http://localhost:3000",
  backendUrl: "http://localhost:3001",
  tenantId: "tenant-abc123"  // ← New: Authentication
});

// Register a tool
bridge.registerTool({
  name: "orders.list",
  description: "Fetch all orders",
  method: "GET",
  path: "/api/orders",
  inputSchema: {
    type: "object",
    properties: {
      limit: { type: "number" }
    }
  },
  outputSchema: {  // ← New: Response schema
    type: "object",
    properties: {
      orders: { type: "array" },
      total: { type: "number" }
    }
  }
});

// Register and start heartbeat
await bridge.start();

// Graceful shutdown
process.on("SIGTERM", async () => {
  await bridge.stop();  // ← New: Deregister + stop heartbeat
  process.exit(0);
});

Configuration

XyneBridgeConfig

interface XyneBridgeConfig {
  serviceName: string;    // Service namespace (e.g., "orders-service")
  backendId: string;      // Unique identifier (e.g., "orders-prod-001")
  gatewayUrl: string;     // Gateway URL (e.g., "http://localhost:3000")
  backendUrl: string;     // Backend URL (e.g., "http://localhost:3001")
  tenantId: string;       // Tenant API key for authentication (REQUIRED - NEW)
}

All fields are required and must be non-empty strings.

Tool Definition

interface ToolDefinition {
  name: string;                           // e.g., "orders.list"
  description?: string;                   // Optional description
  method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD";
  path: string;                           // e.g., "/api/orders" or "/api/orders/{id}"
  inputSchema: Record<string, any>;       // JSON Schema for inputs
  outputSchema?: Record<string, any>;     // JSON Schema for outputs (NEW)
}

API Methods

registerTool(tool: ToolDefinition)

Register a single tool.

bridge.registerTool({
  name: "orders.create",
  description: "Create a new order",
  method: "POST",
  path: "/api/orders",
  inputSchema: {
    type: "object",
    properties: {
      customerId: { type: "string" },
      items: { type: "array" }
    },
    required: ["customerId", "items"]
  },
  outputSchema: {
    type: "object",
    properties: {
      orderId: { type: "string" },
      status: { type: "string" }
    }
  }
});

registerTools(tools: ToolDefinition[])

Register multiple tools at once.

bridge.registerTools([tool1, tool2, tool3]);

getTools(): ToolDefinition[]

Get all registered tools.

const allTools = bridge.getTools();

async start(): Promise

Register with gateway and start automatic heartbeat (every 30 seconds).

try {
  await bridge.start();
  console.log("✓ Registered + heartbeat started");
} catch (error) {
  console.error("✗ Registration failed:", error);
}

What happens:

  1. Sends X-Tenant-ID header with tenantId
  2. Registers all tools with the gateway
  3. Starts automatic heartbeat (30 second interval)
  4. Keeps service marked as "active"

async stop(): Promise

Stop heartbeat and deregister from gateway.

await bridge.stop();
console.log("✓ Deregistered + heartbeat stopped");

What happens:

  1. Stops heartbeat interval
  2. Calls DELETE /registry/{backendId} with X-Tenant-ID header
  3. Service removed from gateway registry

isRegisteredWithGateway(): boolean

Check if currently registered.

if (bridge.isRegisteredWithGateway()) {
  console.log("Service is active");
}

getConfig(): Readonly

Get configuration for debugging.

const config = bridge.getConfig();
console.log(config);

Authentication

All requests include the X-Tenant-ID header for authentication:

X-Tenant-ID: tenant-abc123

The gateway validates this header against its configured valid tenants. If invalid or missing, requests return 401 Unauthorized.

Heartbeat Mechanism

After calling start(), the SDK automatically:

  • Sends heartbeat every 30 seconds
  • Keeps service marked as "active"
  • Gateway marks services as "stale" if no heartbeat for 60+ seconds

No configuration needed - it's automatic!

Integration Example

import express from "express";
import { createBridge } from "xyne-bridge-sdk";

const app = express();
const bridge = createBridge({
  serviceName: "orders-service",
  backendId: "orders-prod-001",
  gatewayUrl: process.env.GATEWAY_URL || "http://localhost:3000",
  backendUrl: "http://localhost:3001",
  tenantId: process.env.TENANT_ID || "default-tenant"
});

// Register tools
bridge.registerTool({
  name: "orders.list",
  description: "List all orders",
  method: "GET",
  path: "/api/orders",
  inputSchema: { type: "object" },
  outputSchema: {
    type: "object",
    properties: { orders: { type: "array" } }
  }
});

// Start server
app.listen(3001, async () => {
  try {
    await bridge.start();
    console.log("✓ Service online and registered");
  } catch (error) {
    console.error("✗ Failed to register:", error);
    process.exit(1);
  }
});

// Graceful shutdown
process.on("SIGTERM", async () => {
  console.log("Shutting down...");
  await bridge.stop();
  process.exit(0);
});

Environment Variables

GATEWAY_URL=http://localhost:3000
TENANT_ID=tenant-abc123

Testing

Check if registered:

curl http://localhost:3000/registry \
  -H "X-Tenant-ID: tenant-abc123"

Error Handling

try {
  await bridge.start();
} catch (error) {
  if (error instanceof Error) {
    console.error("Registration error:", error.message);
  }
}

Possible errors:

  • Missing/empty config fields
  • Gateway unreachable
  • Invalid tenantId
  • Network timeout

Best Practices

  1. Use environment variables for sensitive config (tenantId, URLs)
  2. Start early - call await bridge.start() in server startup
  3. Graceful shutdown - call await bridge.stop() on SIGTERM
  4. Define outputSchema - helps gateway clients understand responses
  5. Use descriptive names - e.g., orders.refund, users.create
  6. Include path parameters - e.g., /api/orders/{id}
  7. Unique backendId - include environment: orders-prod-001, orders-staging-001

Version History

v1.1.0 (Latest)

  • ✨ Added tenantId authentication with X-Tenant-ID header
  • ✨ Added outputSchema support for response documentation
  • ✨ Added automatic heartbeat mechanism (30 second intervals)
  • ✨ Added stop() method for graceful deregistration
  • 🔧 Fixed error handling for Promise types

v1.0.0

  • Initial release
  • Tool registration
  • Service discovery

License

ISC