Skip to main content
Glama
bbernstein
by bbernstein
search-tools.ts7.24 kB
import { z } from 'zod'; import { LacyLightsGraphQLClient } from '../services/graphql-client-simple'; import { FixtureType } from '../types/lighting'; const SearchFixturesSchema = z.object({ projectId: z.string().describe('Project ID to search within'), query: z.string().describe('Search query for fixture name, manufacturer, or model'), filter: z.object({ type: z.nativeEnum(FixtureType).optional().describe('Filter by fixture type'), universe: z.number().int().min(1).optional().describe('Filter by DMX universe'), tags: z.array(z.string()).optional().describe('Filter by tags (must have all specified tags)'), manufacturer: z.string().optional().describe('Filter by manufacturer name'), model: z.string().optional().describe('Filter by model name') }).optional().describe('Additional filters to apply'), page: z.number().int().min(1).default(1).describe('Page number for pagination'), perPage: z.number().int().min(1).max(100).default(20).describe('Results per page (max 100)') }); const SearchScenesSchema = z.object({ projectId: z.string().describe('Project ID to search within'), query: z.string().describe('Search query for scene name or description'), filter: z.object({ nameContains: z.string().optional().describe('Filter scenes where name contains this text'), usesFixture: z.string().optional().describe('Filter scenes that use this fixture ID') }).optional().describe('Additional filters to apply'), page: z.number().int().min(1).default(1).describe('Page number for pagination'), perPage: z.number().int().min(1).max(100).default(20).describe('Results per page (max 100)') }); const SearchCuesSchema = z.object({ cueListId: z.string().describe('Cue list ID to search within'), query: z.string().describe('Search query for cue name or notes'), page: z.number().int().min(1).default(1).describe('Page number for pagination'), perPage: z.number().int().min(1).max(100).default(20).describe('Results per page (max 100)') }); export class SearchTools { constructor(private graphqlClient: LacyLightsGraphQLClient) {} /** * Search for fixtures by name, manufacturer, or model with optional filters */ async searchFixtures(args: z.input<typeof SearchFixturesSchema>) { const { projectId, query, filter, page, perPage } = SearchFixturesSchema.parse(args); try { const result = await this.graphqlClient.searchFixtures( projectId, query, filter, page, perPage ); const { fixtures, pagination } = result; // Format fixtures for better readability const formattedFixtures = fixtures.map(fixture => ({ id: fixture.id, name: fixture.name, description: fixture.description, manufacturer: fixture.manufacturer, model: fixture.model, type: fixture.type, mode: fixture.modeName, dmx: { universe: fixture.universe, startChannel: fixture.startChannel, channelCount: fixture.channelCount, channelRange: `${fixture.startChannel}-${fixture.startChannel + fixture.channelCount - 1}` }, tags: fixture.tags, channels: fixture.channels.map(ch => ({ offset: ch.offset, name: ch.name, type: ch.type })) })); return { results: formattedFixtures, pagination: { currentPage: pagination.page, totalPages: pagination.totalPages, totalResults: pagination.total, resultsPerPage: pagination.perPage, hasMore: pagination.hasMore }, summary: { query, filters: filter ? Object.keys(filter).filter(k => filter[k as keyof typeof filter] !== undefined) : [], resultsCount: fixtures.length, totalMatches: pagination.total }, message: `Found ${pagination.total} fixture(s) matching "${query}"${filter ? ' with filters applied' : ''}` }; } catch (error) { throw new Error(`Failed to search fixtures: ${error}`); } } /** * Search for scenes by name or description with optional filters */ async searchScenes(args: z.input<typeof SearchScenesSchema>) { const { projectId, query, filter, page, perPage} = SearchScenesSchema.parse(args); try { const result = await this.graphqlClient.searchScenes( projectId, query, filter, page, perPage ); const { scenes, pagination } = result; // Format scenes for better readability const formattedScenes = scenes.map(scene => ({ id: scene.id, name: scene.name, description: scene.description, fixtureCount: scene.fixtureCount, created: scene.createdAt, updated: scene.updatedAt })); return { results: formattedScenes, pagination: { currentPage: pagination.page, totalPages: pagination.totalPages, totalResults: pagination.total, resultsPerPage: pagination.perPage, hasMore: pagination.hasMore }, summary: { query, filters: filter ? Object.keys(filter).filter(k => filter[k as keyof typeof filter] !== undefined) : [], resultsCount: scenes.length, totalMatches: pagination.total }, message: `Found ${pagination.total} scene(s) matching "${query}"${filter ? ' with filters applied' : ''}` }; } catch (error) { throw new Error(`Failed to search scenes: ${error}`); } } /** * Search for cues by name or notes within a cue list */ async searchCues(args: z.input<typeof SearchCuesSchema>) { const { cueListId, query, page, perPage } = SearchCuesSchema.parse(args); try { const result = await this.graphqlClient.searchCues( cueListId, query, page, perPage ); const { cues, pagination } = result; // Format cues for better readability const formattedCues = cues.map(cue => { const cueWithList = cue as any; return { id: cue.id, cueNumber: cue.cueNumber, name: cue.name, notes: cue.notes, scene: { id: cue.scene.id, name: cue.scene.name }, timing: { fadeInTime: cue.fadeInTime, fadeOutTime: cue.fadeOutTime, followTime: cue.followTime }, cueList: { id: cueWithList.cueList.id, name: cueWithList.cueList.name } }; }); return { results: formattedCues, pagination: { currentPage: pagination.page, totalPages: pagination.totalPages, totalResults: pagination.total, resultsPerPage: pagination.perPage, hasMore: pagination.hasMore }, summary: { query, cueListId, resultsCount: cues.length, totalMatches: pagination.total }, message: `Found ${pagination.total} cue(s) matching "${query}" in cue list` }; } catch (error) { throw new Error(`Failed to search cues: ${error}`); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bbernstein/lacylights-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server