Skip to main content
Glama

Cyberlink MCP Server

by dasein108
query.service.ts8.79 kB
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'; import { IndexedTx } from '@cosmjs/stargate'; import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { CyberlinkBaseService } from './base.service'; import { ConfigResponse, CyberlinkByFormattedIdResponse, CyberlinkResponse, CyberlinksByIdsResponse, CyberlinksByOwnerResponse, CyberlinksByOwnerTimeAnyResponse, CyberlinksByOwnerTimeResponse, CyberlinksResponse, CyberlinkState, DebugStateResponse, LastIdResponse, NamedCyberlinksResponse, } from './types'; import { removeEmptyValues } from './utils'; /** * Service class for read-only operations on the CW-Social smart contract */ export class CyberlinkQueryService extends CyberlinkBaseService { private cosmWasmClient: CosmWasmClient | null = null; private readonly nodeUrl: string; constructor(nodeUrl: string, contractAddress: string) { super(contractAddress); if (!nodeUrl) throw new Error('Missing NODE_URL'); this.nodeUrl = nodeUrl; } async initialize(): Promise<void> { try { this.cosmWasmClient = await CosmWasmClient.connect(this.nodeUrl); } catch (error) { throw new McpError( ErrorCode.InternalError, `Failed to initialize query service: ${ error instanceof Error ? error.message : 'Unknown error' }\r\nnodeUrl: ${this.nodeUrl} [ ${this.contractAddress} ] ` ); } } protected ensureInitialized(): void { if (!this.cosmWasmClient) { throw new McpError(ErrorCode.InternalError, 'CyberlinkQueryService not initialized'); } } protected async getTx(transactionHash: string): Promise<IndexedTx | null> { return this.cosmWasmClient!.getTx(transactionHash); } /** * Executes a query on the smart contract * @param queryMsg Query message * @param transform Whether to transform the results * @returns Query response */ private async executeQuery<T>( queryMsg: Record<string, any>, transform: boolean = false ): Promise<T> { this.ensureInitialized(); try { const result = await this.cosmWasmClient!.queryContractSmart(this.contractAddress, queryMsg); return (transform ? this.transformResults(result) : result) as T; } catch (error) { throw new McpError( ErrorCode.InternalError, `Query failed: ${error instanceof Error ? error.message : 'Unknown error'}` ); } } // QUERY OPERATIONS async queryCyberlinks(startAfter?: number, limit: number = 50): Promise<CyberlinksResponse> { return this.executeQuery<CyberlinksResponse>( { cyberlinks: this.createPaginationParams(startAfter, limit) }, false ); } async queryByFormattedId(fid: string): Promise<CyberlinkByFormattedIdResponse> { return this.executeQuery<CyberlinkByFormattedIdResponse>( { cyberlink_by_f_i_d: { fid: fid } }, false ); } async queryByTimeRangeAny( owner: string, startTime: string, endTime?: string, startAfter?: number, limit: number = 50 ): Promise<CyberlinksByOwnerTimeAnyResponse> { return this.executeQuery<CyberlinksByOwnerTimeAnyResponse>( { cyberlinks_by_owner_time_any: { owner, start_time: startTime, end_time: endTime, ...this.createPaginationParams(startAfter, limit), }, }, false ); } async queryByTimeRange( owner: string, startTime: string, endTime?: string, startAfter?: number, limit: number = 50 ): Promise<CyberlinksByOwnerTimeResponse> { return this.executeQuery<CyberlinksByOwnerTimeResponse>( { cyberlinks_by_owner_time: { owner, start_time: startTime, end_time: endTime, ...this.createPaginationParams(startAfter, limit), }, }, false ); } async queryLastId(): Promise<LastIdResponse> { return this.executeQuery<LastIdResponse>({ last_g_i_d: {} }, false); } async queryDebugState(): Promise<DebugStateResponse> { return this.executeQuery<DebugStateResponse>({ debug_state: {} }, false); } async queryNamedCyberlinks( startAfter?: string, limit: number = 50 ): Promise<NamedCyberlinksResponse> { return this.executeQuery<NamedCyberlinksResponse>( { named_cyberlinks: this.createPaginationParams(startAfter, limit) }, false ); } async queryByOwner( owner: string, startAfter?: number, limit: number = 50 ): Promise<CyberlinksByOwnerResponse> { return this.executeQuery<CyberlinksByOwnerResponse>( { cyberlinks_by_owner: { owner, ...this.createPaginationParams(startAfter, limit), }, }, false ); } async queryConfig(): Promise<ConfigResponse> { return this.executeQuery<ConfigResponse>({ config: {} }, false); } async queryById(gid: string): Promise<CyberlinkResponse> { return this.executeQuery<CyberlinkResponse>({ cyberlink_by_g_i_d: { gid } }, false); } async queryByIds(gids: string[]): Promise<CyberlinksByIdsResponse> { return this.executeQuery<CyberlinksByIdsResponse>({ cyberlinks_by_g_i_ds: { gids } }, false); } async queryCyberlinksByType( type: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksResponse> { return this.executeQuery<CyberlinksResponse>( { cyberlinks_by_type: { type, ...this.createPaginationParams(startAfterGid, limit) } }, false ); } async queryCyberlinksByFrom( from: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksResponse> { return this.executeQuery<CyberlinksResponse>( { cyberlinks_by_from: { from, ...this.createPaginationParams(startAfterGid, limit) } }, false ); } async queryCyberlinksByTo( to: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksResponse> { return this.executeQuery<CyberlinksResponse>( { cyberlinks_by_to: { to, ...this.createPaginationParams(startAfterGid, limit) } }, false ); } async queryCyberlinksByOwnerTime( owner: string, startTime: string, endTime?: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksByOwnerTimeResponse> { return this.executeQuery<CyberlinksByOwnerTimeResponse>( { cyberlinks_by_owner_time: { owner, start_time: startTime, end_time: endTime, ...this.createPaginationParams(startAfterGid, limit), }, }, false ); } async queryCyberlinksByOwnerTimeAny( owner: string, startTime: string, endTime?: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksByOwnerTimeAnyResponse> { return this.executeQuery<CyberlinksByOwnerTimeAnyResponse>( { cyberlinks_by_owner_time_any: { owner, start_time: startTime, end_time: endTime, ...this.createPaginationParams(startAfterGid, limit), }, }, false ); } async getGraphStats( owner?: string, type?: string ): Promise<{ owner_count?: string; type_count?: string; owner_type_count?: string; }> { return this.executeQuery( { get_graph_stats: removeEmptyValues({ owner, type, }), }, false ); } /** * Creates pagination parameters for queries * @param startAfter Start cursor * @param limit Result limit * @returns Pagination parameters */ private createPaginationParams(startAfter?: number | string, limit: number = 50) { return { start_after: startAfter, limit: Math.min(Math.max(1, limit), 100), // Ensure limit is between 1 and 100 }; } /** * Transforms query results into a record format * @param results Query results * @returns Transformed results */ private transformResults(results: [number, CyberlinkState][]): Record<number, CyberlinkState> { return results.reduce((acc, [id, state]) => { acc[id] = { ...state }; return acc; }, {} as Record<number, CyberlinkState>); } // Add a public wrapper for getTxStatus public async getTxStatus(transactionHash: string): Promise<import('./types').TxStatusResponse> { return super.getTxStatus(transactionHash); } async queryCyberlinksByOwnerAndType( owner: string, type: string, startAfterGid?: number, limit: number = 50 ): Promise<CyberlinksResponse> { return this.executeQuery<CyberlinksResponse>( { cyberlinks_by_owner_and_type: { owner, type, ...this.createPaginationParams(startAfterGid, limit), }, }, false ); } }

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/dasein108/mcp-cw-graph'

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