Skip to main content
Glama
miyaichi

OpenSincera MCP Server

by miyaichi

get_publisher_metadata

Retrieve comprehensive publisher metadata including performance metrics, verification status, and supply chain details from the OpenSincera API using publisher ID or domain.

Instructions

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.

Input Schema

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

Implementation Reference

  • Core handler function in OpenSinceraService that performs the actual API request to OpenSincera, processes the response, maps to PublisherMetadata, and handles errors. This is the primary execution logic for the tool.
    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 || '', ownerDomain: publisherData.owner_domain || request.publisherDomain || '', domain: publisherData.domain, 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', parentEntityId: publisherData.parent_entity_id, similarPublishers: publisherData.similar_publishers?.content, 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; } }
  • MCP tool dispatch handler in index.ts that validates input with schema, calls the service handler, formats output with descriptions, and constructs the MCP 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 parameters.
    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:56-93 (registration)
    Tool registration in ListToolsResponse, defining name, description, and inputSchema for get_publisher_metadata.
    { 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, }, },
  • Helper function used in the tool handler to format publisher metadata with comprehensive field descriptions for user-friendly output.
    export function formatPublisherWithDescriptions( publisher: any, language: 'en' | 'ja' = 'en' ): string { const lines: string[] = []; lines.push(`# ${publisher.publisherName || 'Unknown Publisher'}`); lines.push(''); // Basic Information lines.push('## Basic Information'); lines.push(`- **Publisher ID**: ${publisher.publisherId}`); lines.push(` ${getFieldDescription('publisherId', language)}`); lines.push(''); lines.push(`- **Owner Domain**: ${publisher.ownerDomain}`); lines.push(` ${getFieldDescription('ownerDomain', language)}`); lines.push(''); if (publisher.domain) { lines.push(`- **Domain**: ${publisher.domain}`); lines.push(` ${getFieldDescription('domain', language)}`); lines.push(''); } lines.push(`- **Status**: ${publisher.status}`); lines.push(` ${getStatusDescription(publisher.status, language)}`); lines.push(''); lines.push(`- **Verification Status**: ${publisher.verificationStatus}`); lines.push(` ${getVerificationDescription(publisher.verificationStatus, language)}`); lines.push(''); if (publisher.contactEmail) { lines.push(`- **Contact Email**: ${publisher.contactEmail}`); lines.push(` ${getFieldDescription('contactEmail', language)}`); lines.push(''); } if (publisher.categories && publisher.categories.length > 0) { lines.push(`- **Categories**: ${publisher.categories.join(', ')}`); lines.push(` ${getFieldDescription('categories', language)}`); lines.push(''); } lines.push(`- **Last Updated**: ${publisher.lastUpdated}`); lines.push(` ${getFieldDescription('lastUpdated', language)}`); lines.push(''); if (publisher.parentEntityId) { lines.push(`- **Parent Entity ID**: ${publisher.parentEntityId}`); lines.push(` ${getFieldDescription('parentEntityId', language)}`); lines.push(''); } if (publisher.similarPublishers && publisher.similarPublishers.length > 0) { lines.push(`- **Similar Publishers**: ${publisher.similarPublishers.join(', ')}`); lines.push(` ${getFieldDescription('similarPublishers', language)}`); lines.push(''); } // Metadata if (publisher.metadata) { lines.push('## Performance Metrics'); lines.push(''); const metadata = publisher.metadata; if (metadata.description) { lines.push(`### Description`); lines.push(metadata.description); lines.push(''); } if (metadata.primarySupplyType) { lines.push(`### Primary Supply Type: ${metadata.primarySupplyType}`); lines.push(getFieldDescription('primarySupplyType', language)); lines.push(''); } if (metadata.avgAdsToContentRatio !== undefined) { lines.push(`### Ads to Content Ratio: ${metadata.avgAdsToContentRatio}`); lines.push(getFieldDescription('avgAdsToContentRatio', language)); lines.push(''); } if (metadata.avgAdsInView !== undefined) { lines.push(`### Ads in View: ${metadata.avgAdsInView}`); lines.push(getFieldDescription('avgAdsInView', language)); lines.push(''); } if (metadata.avgAdRefresh !== undefined) { lines.push(`### Ad Refresh Rate: ${metadata.avgAdRefresh} seconds`); lines.push(getFieldDescription('avgAdRefresh', language)); lines.push(''); } if (metadata.totalUniqueGpids !== undefined) { lines.push(`### Total Unique GPIDs: ${metadata.totalUniqueGpids}`); lines.push(getFieldDescription('totalUniqueGpids', language)); lines.push(''); } if (metadata.idAbsorptionRate !== undefined) { lines.push(`### ID Absorption Rate: ${metadata.idAbsorptionRate}`); lines.push(getFieldDescription('idAbsorptionRate', language)); lines.push(''); } if (metadata.avgPageWeight !== undefined) { lines.push(`### Average Page Weight: ${metadata.avgPageWeight} KB`); lines.push(getFieldDescription('avgPageWeight', language)); lines.push(''); } if (metadata.avgCpu !== undefined) { lines.push(`### Average CPU Usage: ${metadata.avgCpu} seconds`); lines.push(getFieldDescription('avgCpu', language)); lines.push(''); } if (metadata.totalSupplyPaths !== undefined) { lines.push(`### Total Supply Paths: ${metadata.totalSupplyPaths}`); lines.push(getFieldDescription('totalSupplyPaths', language)); lines.push(''); } if (metadata.resellerCount !== undefined) { lines.push(`### Reseller Count: ${metadata.resellerCount}`); lines.push(getFieldDescription('resellerCount', language)); lines.push(''); } } return lines.join('\n'); }

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