@digitalsamba/embedded-api-mcp-server
Version:
Digital Samba Embedded API MCP Server - Model Context Protocol server for Digital Samba's Embedded API
467 lines • 16.5 kB
JavaScript
/**
* Digital Samba MCP Server - Webhook Management Tools
*
* This module implements tools for managing webhooks in Digital Samba.
* It provides MCP tools for creating, updating, deleting webhooks and managing webhook events.
*
* Tools provided:
* - list-webhook-events: List all available webhook events
* - list-webhooks: List all configured webhooks
* - create-webhook: Create a new webhook
* - get-webhook: Get specific webhook details
* - update-webhook: Update webhook configuration
* - delete-webhook: Delete a webhook
*
* @module tools/webhook-management
* @author Digital Samba Team
* @version 1.0.0
*/
// MCP SDK imports
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
import logger from "../../logger.js";
/**
* Register webhook management tools
*
* @returns {ToolDefinition[]} Array of tool definitions
*/
export function registerWebhookTools() {
return [
{
name: "list-webhook-events",
description: '[Webhook Management] List all available webhook event types. Use when users say: "list webhook events", "show available events", "what events can I subscribe to", "webhook event types", "available webhooks". Returns complete catalog of subscribable events like room.created, session.ended, etc.',
inputSchema: {
type: "object",
properties: {},
},
},
{
name: "list-webhooks",
description: '[Webhook Management] List all configured webhooks in your account. Use when users say: "list webhooks", "show webhooks", "get all webhooks", "show webhook configurations", "active webhooks". Returns webhook endpoints, subscribed events, and status. Supports pagination.',
inputSchema: {
type: "object",
properties: {
limit: {
type: "number",
description: "Maximum number of webhooks to return",
},
offset: {
type: "number",
description: "Number of webhooks to skip",
},
},
},
},
{
name: "create-webhook",
description: '[Webhook Management] Create a new webhook endpoint subscription. Use when users say: "create webhook", "add webhook", "subscribe to events", "set up webhook", "configure webhook notifications". Requires endpoint URL and events array. Optional auth header for security.',
inputSchema: {
type: "object",
properties: {
endpoint: {
type: "string",
description: "The URL endpoint to receive webhook events",
},
name: {
type: "string",
description: "Name for the webhook",
},
events: {
type: "array",
description: "Array of event types to subscribe to",
items: {
type: "string",
},
},
authorizationHeader: {
type: "string",
description: "Optional authorization header value for webhook requests",
},
},
required: ["endpoint", "events"],
},
},
{
name: "get-webhook",
description: '[Webhook Management] Get detailed information about a specific webhook. Use when users say: "show webhook details", "get webhook info", "webhook configuration", "describe webhook", "webhook settings". Requires webhookId. Returns endpoint, events, and configuration.',
inputSchema: {
type: "object",
properties: {
webhookId: {
type: "string",
description: "The ID of the webhook",
},
},
required: ["webhookId"],
},
},
{
name: "update-webhook",
description: '[Webhook Management] Update webhook endpoint, events, or settings. Use when users say: "update webhook", "change webhook URL", "modify webhook events", "edit webhook", "change webhook configuration". Requires webhookId. Can update endpoint, name, events, or auth.',
inputSchema: {
type: "object",
properties: {
webhookId: {
type: "string",
description: "The ID of the webhook to update",
},
endpoint: {
type: "string",
description: "New URL endpoint for the webhook",
},
name: {
type: "string",
description: "New name for the webhook",
},
events: {
type: "array",
description: "New array of event types to subscribe to",
items: {
type: "string",
},
},
authorizationHeader: {
type: "string",
description: "New authorization header value",
},
},
required: ["webhookId"],
},
},
{
name: "delete-webhook",
description: '[Webhook Management] Permanently delete a webhook subscription. Use when users say: "delete webhook", "remove webhook", "unsubscribe webhook", "cancel webhook", "disable webhook". Requires webhookId. Stops all future event deliveries to this endpoint.',
inputSchema: {
type: "object",
properties: {
webhookId: {
type: "string",
description: "The ID of the webhook to delete",
},
},
required: ["webhookId"],
},
},
];
}
/**
* Execute a webhook management tool
*
* @param {string} toolName - Name of the tool to execute
* @param {any} params - Tool parameters
* @param {DigitalSambaApiClient} apiClient - API client instance
* @returns {Promise<any>} Tool execution result
*/
export async function executeWebhookTool(toolName, params, apiClient) {
switch (toolName) {
case "list-webhook-events":
return handleListWebhookEvents(apiClient);
case "list-webhooks":
return handleListWebhooks(params, apiClient);
case "create-webhook":
return handleCreateWebhook(params, apiClient);
case "get-webhook":
return handleGetWebhook(params, apiClient);
case "update-webhook":
return handleUpdateWebhook(params, apiClient);
case "delete-webhook":
return handleDeleteWebhook(params, apiClient);
default:
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${toolName}`);
}
}
/**
* Handle list webhook events
*/
async function handleListWebhookEvents(apiClient) {
logger.info("Listing available webhook events");
try {
const events = await apiClient.listWebhookEvents();
return {
content: [
{
type: "text",
text: `Available webhook events:\n\n${events.join("\n")}`,
},
],
};
}
catch (error) {
logger.error("Error listing webhook events", {
error: error instanceof Error ? error.message : String(error),
});
return {
content: [
{
type: "text",
text: `Error listing webhook events: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
/**
* Handle list webhooks
*/
async function handleListWebhooks(params, apiClient) {
logger.info("Listing webhooks", params);
try {
const webhooks = await apiClient.listWebhooks(params);
if (!webhooks.data || webhooks.data.length === 0) {
return {
content: [
{
type: "text",
text: "No webhooks configured.",
},
],
};
}
const webhookList = webhooks.data
.map((webhook) => `- ${webhook.name || "Unnamed"} (${webhook.id})\n Endpoint: ${webhook.endpoint}\n Events: ${webhook.events?.join(", ") || "None"}`)
.join("\n\n");
return {
content: [
{
type: "text",
text: `Found ${webhooks.total_count} webhooks:\n\n${webhookList}`,
},
],
};
}
catch (error) {
logger.error("Error listing webhooks", {
error: error instanceof Error ? error.message : String(error),
});
return {
content: [
{
type: "text",
text: `Error listing webhooks: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
/**
* Handle create webhook
*/
async function handleCreateWebhook(params, apiClient) {
const { endpoint, name, events, authorizationHeader } = params;
if (!endpoint || !events || events.length === 0) {
return {
content: [
{
type: "text",
text: "Endpoint and at least one event are required to create a webhook.",
},
],
isError: true,
};
}
logger.info("Creating webhook", { endpoint, events: events.length });
try {
const webhook = await apiClient.createWebhook({
endpoint,
name,
events,
authorization_header: authorizationHeader,
});
return {
content: [
{
type: "text",
text: `Successfully created webhook "${webhook.name || "Unnamed"}" with ID: ${webhook.id}\nEndpoint: ${webhook.endpoint}\nEvents: ${webhook.events?.join(", ")}`,
},
],
};
}
catch (error) {
logger.error("Error creating webhook", {
endpoint,
error: error instanceof Error ? error.message : String(error),
});
const errorMessage = error instanceof Error ? error.message : String(error);
let displayMessage = `Error creating webhook: ${errorMessage}`;
if (errorMessage.includes("already exists")) {
displayMessage = `A webhook with endpoint "${endpoint}" already exists`;
}
return {
content: [
{
type: "text",
text: displayMessage,
},
],
isError: true,
};
}
}
/**
* Handle get webhook
*/
async function handleGetWebhook(params, apiClient) {
const { webhookId } = params;
if (!webhookId) {
return {
content: [
{
type: "text",
text: "Webhook ID is required.",
},
],
isError: true,
};
}
logger.info("Getting webhook details", { webhookId });
try {
const webhook = await apiClient.getWebhook(webhookId);
return {
content: [
{
type: "text",
text: `Webhook Details:
ID: ${webhook.id}
Name: ${webhook.name || "Unnamed"}
Endpoint: ${webhook.endpoint}
Events: ${webhook.events?.join(", ") || "None"}
Authorization: ${webhook.authorization_header ? "Configured" : "Not configured"}
Created: ${webhook.created_at}
Updated: ${webhook.updated_at}`,
},
],
};
}
catch (error) {
logger.error("Error getting webhook", {
webhookId,
error: error instanceof Error ? error.message : String(error),
});
const errorMessage = error instanceof Error ? error.message : String(error);
let displayMessage = `Error getting webhook: ${errorMessage}`;
if (errorMessage.includes("not found") || errorMessage.includes("404")) {
displayMessage = `Webhook with ID "${webhookId}" not found`;
}
return {
content: [
{
type: "text",
text: displayMessage,
},
],
isError: true,
};
}
}
/**
* Handle update webhook
*/
async function handleUpdateWebhook(params, apiClient) {
const { webhookId, ...updates } = params;
if (!webhookId) {
return {
content: [
{
type: "text",
text: "Webhook ID is required.",
},
],
isError: true,
};
}
if (Object.keys(updates).length === 0) {
return {
content: [
{
type: "text",
text: "No updates provided. Specify endpoint, name, events, or authorizationHeader to update.",
},
],
isError: true,
};
}
logger.info("Updating webhook", { webhookId, updates: Object.keys(updates) });
try {
const webhook = await apiClient.updateWebhook(webhookId, updates);
const updatedFields = Object.keys(updates).join(", ");
return {
content: [
{
type: "text",
text: `Successfully updated webhook "${webhook.name || "Unnamed"}". Updated fields: ${updatedFields}`,
},
],
};
}
catch (error) {
logger.error("Error updating webhook", {
webhookId,
error: error instanceof Error ? error.message : String(error),
});
const errorMessage = error instanceof Error ? error.message : String(error);
let displayMessage = `Error updating webhook: ${errorMessage}`;
if (errorMessage.includes("not found") || errorMessage.includes("404")) {
displayMessage = `Webhook with ID "${webhookId}" not found`;
}
return {
content: [
{
type: "text",
text: displayMessage,
},
],
isError: true,
};
}
}
/**
* Handle delete webhook
*/
async function handleDeleteWebhook(params, apiClient) {
const { webhookId } = params;
if (!webhookId) {
return {
content: [
{
type: "text",
text: "Webhook ID is required.",
},
],
isError: true,
};
}
logger.info("Deleting webhook", { webhookId });
try {
await apiClient.deleteWebhook(webhookId);
return {
content: [
{
type: "text",
text: `Successfully deleted webhook with ID: ${webhookId}`,
},
],
};
}
catch (error) {
logger.error("Error deleting webhook", {
webhookId,
error: error instanceof Error ? error.message : String(error),
});
const errorMessage = error instanceof Error ? error.message : String(error);
let displayMessage = `Error deleting webhook: ${errorMessage}`;
if (errorMessage.includes("not found") || errorMessage.includes("404")) {
displayMessage = `Webhook with ID "${webhookId}" not found`;
}
return {
content: [
{
type: "text",
text: displayMessage,
},
],
isError: true,
};
}
}
//# sourceMappingURL=index.js.map