@digitalsamba/embedded-api-mcp-server
Version:
Digital Samba Embedded API MCP Server - Model Context Protocol server for Digital Samba's Embedded API
156 lines • 6.61 kB
JavaScript
/**
* Digital Samba MCP Server - Recording Resources
*
* This module implements resources for accessing Digital Samba room recordings.
* It provides MCP resources for listing and retrieving recording information.
*
* Resources provided:
* - recordings: List all recordings
* - recording: Get specific recording details
* - room-recordings: List recordings for a specific room
* - archived-recordings: List archived recordings
*
* @module resources/recordings
* @author Digital Samba Team
* @version 1.0.0
*/
// MCP SDK imports
import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
// Local modules
import { getApiKeyFromRequest } from "../../auth.js";
import { DigitalSambaApiClient } from "../../digital-samba-api.js";
import { AuthenticationError, ValidationError } from "../../errors.js";
import logger from "../../logger.js";
/**
* Set up recording resources for the MCP server
*
* This function registers all recording-related resources with the MCP server.
* Resources are read-only endpoints that provide access to recording data.
*
* @param {McpServer} server - The MCP server instance
* @param {string} apiUrl - Base URL for the Digital Samba API
* @returns {void}
*/
export function setupRecordingResources(server, apiUrl) {
// Resource for listing all recordings
server.resource("recordings", new ResourceTemplate("digitalsamba://recordings", { list: undefined }), async (uri, _params, request) => {
try {
const apiKey = getApiKeyFromRequest(request);
if (!apiKey) {
throw new AuthenticationError("API key is required to access recordings");
}
const apiClient = new DigitalSambaApiClient(apiKey, apiUrl);
const recordings = await apiClient.listRecordings();
// Format recordings as resource contents with URIs
const contents = recordings.data.map((recording) => ({
uri: `digitalsamba://recordings/${recording.id}`,
text: JSON.stringify(recording, null, 2),
}));
return { contents };
}
catch (error) {
logger.error("Error in recordings resource", {
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
});
// Resource for getting a specific recording
server.resource("recording", new ResourceTemplate("digitalsamba://recordings/{recordingId}", {
list: undefined,
}), async (uri, params, request) => {
try {
const apiKey = getApiKeyFromRequest(request);
if (!apiKey) {
throw new AuthenticationError("API key is required to access recording details");
}
const { recordingId } = params;
if (!recordingId) {
throw new ValidationError("Recording ID is required", {
validationErrors: { recordingId: "Recording ID cannot be empty" },
});
}
// Handle string | string[] type - take first value if array
const recordingIdStr = Array.isArray(recordingId)
? recordingId[0]
: recordingId;
const apiClient = new DigitalSambaApiClient(apiKey, apiUrl);
const recording = await apiClient.getRecording(recordingIdStr);
return {
contents: [
{
uri: `digitalsamba://recordings/${recordingId}`,
text: JSON.stringify(recording, null, 2),
},
],
};
}
catch (error) {
logger.error("Error in recording resource", {
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
});
// Resource for listing recordings for a specific room
server.resource("room-recordings", new ResourceTemplate("digitalsamba://rooms/{roomId}/recordings", {
list: undefined,
}), async (uri, params, request) => {
try {
const apiKey = getApiKeyFromRequest(request);
if (!apiKey) {
throw new AuthenticationError("API key is required to access room recordings");
}
const { roomId } = params;
if (!roomId) {
throw new ValidationError("Room ID is required", {
validationErrors: { roomId: "Room ID cannot be empty" },
});
}
// Handle string | string[] type - take first value if array
const roomIdStr = Array.isArray(roomId) ? roomId[0] : roomId;
const apiClient = new DigitalSambaApiClient(apiKey, apiUrl);
const recordings = await apiClient.listRecordings({
room_id: roomIdStr,
});
// Format recordings as resource contents with URIs
const contents = recordings.data.map((recording) => ({
uri: `digitalsamba://recordings/${recording.id}`,
text: JSON.stringify(recording, null, 2),
}));
return { contents };
}
catch (error) {
logger.error("Error in room-recordings resource", {
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
});
// Resource for listing archived recordings
server.resource("archived-recordings", new ResourceTemplate("digitalsamba://recordings/archived", {
list: undefined,
}), async (uri, _params, request) => {
try {
const apiKey = getApiKeyFromRequest(request);
if (!apiKey) {
throw new AuthenticationError("API key is required to access archived recordings");
}
const apiClient = new DigitalSambaApiClient(apiKey, apiUrl);
const recordings = await apiClient.listArchivedRecordings();
// Format recordings as resource contents with URIs
const contents = recordings.data.map((recording) => ({
uri: `digitalsamba://recordings/${recording.id}`,
text: JSON.stringify(recording, null, 2),
}));
return { contents };
}
catch (error) {
logger.error("Error in archived-recordings resource", {
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
});
}
//# sourceMappingURL=index.js.map