Skip to main content
Glama
miyaichi

OpenSincera MCP Server

by miyaichi

get_publisher_metadata

Retrieve detailed metadata for digital advertising publishers using OpenSincera API by entering a publisher ID or domain. Supports result filtering with limit and offset parameters.

Instructions

Get publisher metadata from OpenSincera API. Requires either publisherId or publisherDomain.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of results to return (1-100)
offsetNoNumber of results to skip
publisherDomainNoPublisher domain to search for
publisherIdNoPublisher ID to search for

Implementation Reference

  • MCP CallToolRequestSchema handler case for 'get_publisher_metadata': validates input with schema, calls OpenSinceraService.getPublisherMetadata, formats results with descriptions, constructs and returns MCP content response
    case 'get_publisher_metadata': { const input = GetPublisherMetadataSchema.parse(request.params.arguments); const result = await openSinceraService.getPublisherMetadata(input); if (result.publishers.length > 0) { const formattedPublishers = result.publishers.map(pub => formatPublisherWithDescriptions(pub, 'en') ).join('\n\n---\n\n'); return { content: [ { type: 'text', text: `Found ${result.totalCount} publisher(s):\n\n${formattedPublishers}`, }, ], }; } else { return { content: [ { type: 'text', text: 'No publishers found matching the criteria.', }, ], }; } }
  • Zod input validation schema for get_publisher_metadata tool
    const GetPublisherMetadataSchema = z.object({ publisherId: z.string().optional(), publisherDomain: z.string().optional(), limit: z.number().min(1).max(100).optional(), offset: z.number().min(0).optional(), }).refine( data => data.publisherId || data.publisherDomain, { message: "Either publisherId or publisherDomain must be provided", } );
  • src/index.ts:57-94 (registration)
    Tool registration in ListToolsRequestSchema response: defines name 'get_publisher_metadata', detailed description, and JSON inputSchema matching Zod schema
    { name: 'get_publisher_metadata', description: `Get detailed publisher metadata from OpenSincera API with comprehensive field descriptions. Requires either publisherId or publisherDomain. Returns publisher information including: - Basic Info: Publisher ID, name, domain, status, verification status, contact info, categories - Performance Metrics: Ads to Content Ratio (A2CR), Ads in View, Ad Refresh Rate, Page Weight, CPU Usage - Supply Chain: Total Supply Paths, Reseller Count, Global Publisher IDs (GPIDs) - Identity: ID Absorption Rate Each metric includes detailed explanations of what it measures and its business implications.`, inputSchema: { type: 'object', properties: { publisherId: { type: 'string', description: 'Publisher ID to search for', }, publisherDomain: { type: 'string', description: 'Publisher domain to search for', }, limit: { type: 'number', description: 'Maximum number of results to return (1-100)', minimum: 1, maximum: 100, }, offset: { type: 'number', description: 'Number of results to skip', minimum: 0, }, }, required: [], additionalProperties: false, }, },
  • OpenSinceraService.getPublisherMetadata: core helper function implementing API call to retrieve and map publisher metadata from OpenSincera API, with comprehensive error handling
    async getPublisherMetadata( request: GetPublisherMetadataRequest = {} ): Promise<GetPublisherMetadataResponse> { try { let endpoint: string; if (request.publisherId) { endpoint = `/publishers?id=${encodeURIComponent(request.publisherId)}`; } else if (request.publisherDomain) { endpoint = `/publishers?domain=${encodeURIComponent(request.publisherDomain)}`; } else { throw new Error('Either publisherId or publisherDomain is required'); } console.error('Making OpenSincera API request', { baseUrl: this.config.baseUrl, endpoint, headers: { Authorization: this.config.apiKey ? 'Bearer [REDACTED]' : 'No API key', }, }); const response: AxiosResponse<any> = await this.client.get(endpoint); console.error('OpenSincera API response', { status: response.status, statusText: response.statusText, dataType: Array.isArray(response.data) ? 'array' : typeof response.data, dataLength: Array.isArray(response.data) ? response.data.length : 'N/A', hasData: !!response.data, }); if (response.status === 200) { const responseData = response.data; let publisherData: any = null; if (Array.isArray(responseData) && responseData.length > 0) { publisherData = responseData[0]; } else if (responseData && typeof responseData === 'object' && responseData.publisher_id) { publisherData = responseData; } if (publisherData) { const mappedPublisher: PublisherMetadata = { publisherId: publisherData.publisher_id || publisherData.id || '', publisherName: publisherData.name || '', publisherDomain: publisherData.owner_domain || request.publisherDomain || '', status: this.mapStatus(publisherData.status), lastUpdated: publisherData.updated_at || new Date().toISOString(), contactEmail: publisherData.contact_email, categories: Array.isArray(publisherData.categories) ? publisherData.categories : publisherData.categories?.split(';') || [], verificationStatus: publisherData.visit_enabled ? 'verified' : 'unverified', metadata: { description: publisherData.pub_description, primarySupplyType: publisherData.primary_supply_type, avgAdsToContentRatio: publisherData.avg_ads_to_content_ratio, avgAdsInView: publisherData.avg_ads_in_view, avgAdRefresh: publisherData.avg_ad_refresh, totalUniqueGpids: publisherData.total_unique_gpids, idAbsorptionRate: publisherData.id_absorption_rate, avgPageWeight: publisherData.avg_page_weight, avgCpu: publisherData.avg_cpu, totalSupplyPaths: publisherData.total_supply_paths, resellerCount: publisherData.reseller_count, slug: publisherData.slug, }, }; return { publishers: [mappedPublisher], totalCount: 1, hasMore: false, }; } else { return { publishers: [], totalCount: 0, hasMore: false, }; } } if (response.status === 401) { throw new Error('Invalid API key or authentication failed'); } if (response.status === 403) { throw new Error('Access forbidden - insufficient permissions'); } if (response.status === 404) { throw new Error('Publisher not found'); } if (response.status === 429) { throw new Error('Rate limit exceeded - please try again later'); } throw new Error(`API request failed with status ${response.status}: ${response.statusText}`); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; console.error('Failed to get publisher metadata', { error: errorMessage, request, }); if ( axios.isAxiosError(error) && (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') ) { console.error('OpenSincera API network error - check endpoint URL and connectivity', { domain: request.publisherDomain, publisherId: request.publisherId, baseUrl: this.config.baseUrl, errorCode: error.code, }); } if (axios.isAxiosError(error)) { if (error.response?.data?.error) { const apiError = error.response.data.error as OpenSinceraApiError; throw new Error(`OpenSincera API Error: ${apiError.message} (${apiError.code})`); } throw new Error( `HTTP ${error.response?.status}: ${error.response?.statusText || errorMessage}` ); } throw error; } }
  • TypeScript interfaces defining request, response, and PublisherMetadata types used by getPublisherMetadata
    export interface GetPublisherMetadataRequest { publisherId?: string; publisherDomain?: string; limit?: number; offset?: number; } export interface PublisherMetadata { publisherId: string; publisherName: string; publisherDomain: string; status: 'active' | 'inactive' | 'suspended'; lastUpdated: string; contactEmail?: string; categories: string[]; verificationStatus: 'verified' | 'unverified' | 'pending'; metadata?: { description?: string; primarySupplyType?: string; avgAdsToContentRatio?: number; avgAdsInView?: number; avgAdRefresh?: number; totalUniqueGpids?: number; idAbsorptionRate?: number; avgPageWeight?: number; avgCpu?: number; totalSupplyPaths?: number; resellerCount?: number; slug?: string; }; } export interface GetPublisherMetadataResponse { publishers: PublisherMetadata[]; totalCount: number; hasMore: boolean; }

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/miyaichi/opensincera-mcp-server'

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