Skip to main content
Glama
AudienseCo

Audiense Insights MCP Server

Official
by AudienseCo

compare-audience-influencers

Compare influencer affinities and uniqueness between a selected audience and a baseline audience to identify distinct alignment patterns.

Instructions

Compares the influencers of an audience with a baseline audience. The baseline is determined as follows: If the selection was the full audience and a single country represents more than 50% of the audience, that country is used as the baseline. Otherwise, the Global baseline is applied. If the selection was a specific segment, the full audience is used as the baseline. Each influencer comparison includes: - Affinity (%) - The level of alignment between the influencer and the audience. Baseline Affinity (%) - The influencer’s affinity within the baseline audience. Uniqueness Score - A measure of how distinct the influencer is within the selected audience compared to the baseline.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
audience_influencers_idYesThe ID of the audience influencers.
baseline_audience_influencers_idYesThe ID of the baseline audience influencers.
cursorNoCursor for pagination.
countNoNumber of items per page (default: 200).
bio_keywordNoKeyword to filter influencers by their biography.
entity_typeNoFilter by entity type (person or brand).
followers_minNoMinimum number of followers.
followers_maxNoMaximum number of followers.
categoriesNoFilter influencers by categories.
countriesNoFilter influencers by country ISO codes.

Implementation Reference

  • Core handler function that constructs the Audiense API endpoint for comparing audience influencers, fetches the data, and enriches the top 100 influencers with Twitter/X user details.
    export async function compareAudienceInfluencers(
        audience_influencers_id: string,
        baseline_audience_influencers_id: string,
        cursor?: number,
        count?: number,
        bio_keyword?: string,
        entity_type?: "person" | "brand",
        followers_min?: number,
        followers_max?: number,
        categories?: string[],
        countries?: string[]
    ): Promise<{ cursor: { next: number; prev: number }; influencers: any[] } | null> {
        const queryParams = new URLSearchParams();
    
        if (cursor !== undefined) queryParams.append("cursor", cursor.toString());
        if (count !== undefined) queryParams.append("count", count.toString());
        if (bio_keyword) queryParams.append("bio_keyword", bio_keyword);
        if (entity_type) queryParams.append("entity_type", entity_type);
        if (followers_min !== undefined) queryParams.append("followers_min", followers_min.toString());
        if (followers_max !== undefined) queryParams.append("followers_max", followers_max.toString());
        if (categories && categories.length > 0) queryParams.append("categories", categories.join(","));
        if (countries && countries.length > 0) queryParams.append("countries", countries.join(","));
    
        const endpoint = `/audience_influencers/${audience_influencers_id}/compared_to/${baseline_audience_influencers_id}?${queryParams.toString()}`;
    
        const data = await makeAudienseRequest<{ cursor: { next: number; prev: number }; influencers: { id: string; affinity: number; baseline_affinity: number; uniqueness: number }[] }>(endpoint);
    
        if (!data || !data.influencers.length) {
            return data;
        }
    
        // Get the first 100 influencers for enrichment
        const influencerIds = data.influencers.slice(0, 100).map((influencer) => influencer.id);
        const twitterData = await fetchTwitterUserDetails(influencerIds);
    
        // Merge Twitter details into influencer data
        const enrichedInfluencers = data.influencers.map((influencer) => ({
            ...influencer,
            twitter: twitterData[influencer.id] || null, // Add Twitter data if available
        }));
    
        return {
            cursor: data.cursor,
            influencers: enrichedInfluencers,
        };
    }
  • src/index.ts:194-257 (registration)
    MCP server.tool registration for the 'compare-audience-influencers' tool, including description, input schema (Zod validation), and thin wrapper handler that calls the core compareAudienceInfluencers function and formats the MCP response.
    server.tool(
        "compare-audience-influencers",
        `Compares the influencers of an audience with a baseline audience. The baseline is determined as follows: 
        If the selection was the full audience and a single country represents more than 50% of the audience, that country is used as the baseline.
        Otherwise, the Global baseline is applied. If the selection was a specific segment, the full audience is used as the baseline.
        Each influencer comparison includes: 
            - Affinity (%) - The level of alignment between the influencer and the audience. Baseline Affinity (%)
            - The influencer’s affinity within the baseline audience. Uniqueness Score
            - A measure of how distinct the influencer is within the selected audience compared to the baseline.
        `,
        {
            audience_influencers_id: z.string().describe("The ID of the audience influencers."),
            baseline_audience_influencers_id: z.string().describe("The ID of the baseline audience influencers."),
            cursor: z.number().optional().describe("Cursor for pagination."),
            count: z.number().optional().describe("Number of items per page (default: 200)."),
            bio_keyword: z.string().optional().describe("Keyword to filter influencers by their biography."),
            entity_type: z.enum(["person", "brand"]).optional().describe("Filter by entity type (person or brand)."),
            followers_min: z.number().optional().describe("Minimum number of followers."),
            followers_max: z.number().optional().describe("Maximum number of followers."),
            categories: z.array(z.string()).optional().describe("Filter influencers by categories."),
            countries: z.array(z.string()).optional().describe("Filter influencers by country ISO codes."),
        },
        async ({ audience_influencers_id, baseline_audience_influencers_id, cursor, count, bio_keyword, entity_type, followers_min, followers_max, categories, countries }) => {
            const data = await compareAudienceInfluencers(
                audience_influencers_id,
                baseline_audience_influencers_id,
                cursor,
                count,
                bio_keyword,
                entity_type,
                followers_min,
                followers_max,
                categories,
                countries
            );
    
            if (!data || !data.influencers.length) {
                return {
                    content: [
                        {
                            type: "text",
                            text: `No influencers found for comparison between ${audience_influencers_id} and ${baseline_audience_influencers_id}.`,
                        },
                    ],
                };
            }
    
            const influencersText = data.influencers
                .map(
                    (influencer) =>
                        `ID: ${influencer.id}\nAffinity: ${influencer.affinity}%\nBaseline Affinity: ${influencer.baseline_affinity}%\nUniqueness: ${influencer.uniqueness}%`
                )
                .join("\n\n");
    
            return {
                content: [
                    {
                        type: "text",
                        text: JSON.stringify(data, null, 2),
                    },
                ],
            };
        }
    );
  • Zod schema for input parameters validation in the MCP tool registration.
    {
        audience_influencers_id: z.string().describe("The ID of the audience influencers."),
        baseline_audience_influencers_id: z.string().describe("The ID of the baseline audience influencers."),
        cursor: z.number().optional().describe("Cursor for pagination."),
        count: z.number().optional().describe("Number of items per page (default: 200)."),
        bio_keyword: z.string().optional().describe("Keyword to filter influencers by their biography."),
        entity_type: z.enum(["person", "brand"]).optional().describe("Filter by entity type (person or brand)."),
        followers_min: z.number().optional().describe("Minimum number of followers."),
        followers_max: z.number().optional().describe("Maximum number of followers."),
        categories: z.array(z.string()).optional().describe("Filter influencers by categories."),
        countries: z.array(z.string()).optional().describe("Filter influencers by country ISO codes."),
    },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It adds some context by detailing the baseline determination logic and the comparison metrics (Affinity, Uniqueness Score), which helps understand the tool's behavior. However, it doesn't cover critical aspects like whether this is a read-only operation, potential rate limits, error conditions, or pagination behavior (implied by cursor/count parameters), making it incomplete for a tool with 10 parameters.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, starting with the core purpose and then detailing baseline logic and comparison metrics in a structured manner. Each sentence adds value, such as explaining baseline determination and output fields, with no redundant information. However, it could be slightly more concise by integrating the baseline rules more tightly with the main function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (10 parameters, no annotations, no output schema), the description is partially complete. It covers the purpose, baseline logic, and output metrics, which are essential. However, it lacks details on return values (e.g., format of comparison results), error handling, and how parameters like 'bio_keyword' or 'followers_min' affect the comparison, leaving gaps that could hinder an AI agent's ability to use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the schema already documents all 10 parameters thoroughly. The description adds minimal value beyond the schema by implying the use of 'audience_influencers_id' and 'baseline_audience_influencers_id' for comparison, but doesn't provide additional syntax, format details, or explain how parameters like 'cursor' or 'categories' integrate with the comparison logic. This meets the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: comparing influencers between an audience and a baseline audience. It specifies the verb 'compares' and the resources 'influencers of an audience' and 'baseline audience', making the function explicit. However, it doesn't differentiate from sibling tools like 'get-audience-insights' or 'report-summary', which might also involve audience analysis, so it misses full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides implied usage by explaining how the baseline is determined (e.g., full audience vs. specific segment, country vs. Global baseline), which gives context for when to apply this tool. However, it lacks explicit guidance on when to use this tool versus alternatives like 'get-audience-insights' or 'report-summary', and doesn't mention prerequisites or exclusions, leaving gaps in usage clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/AudienseCo/mcp-audiense-insights'

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