competitor_intel
Generate a board-ready competitive-intelligence report analyzing competitor moves, pricing changes, and strategic signals, with quantified recommendations and a presenter script.
Instructions
Generate a board-ready competitive-intelligence report for a company against named competitors. Returns: recent competitor moves (product releases, pricing changes, hiring, funding) each with a severity score (critical/high/medium/low), prioritised signals, a pricing-radar comparison, 3-6 quantified recommendations (expected impact in € or %, over 7/30/90/180-day horizons), and an 8-12 slide presenter script. When to use this tool: the user wants to analyse, benchmark or track competitors, or needs a competitive briefing before a strategic decision. Inputs: the user's own company (name + one-paragraph pitch) and 1-10 competitors to analyse. Delivered by Manue, the AI CMO of the Gapup portfolio.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| selfCompany | Yes | Your company info | |
| competitors | Yes | 1-10 competitors to analyze | |
| focus | No | Optional — what the buyer wants to track first (e.g. pricing moves, hiring patterns) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| executiveSummary | Yes | Board-ready prose summary (120-400 chars) | |
| competitorMoves | Yes | Recent moves per competitor with severity rating | |
| pricingRadar | No | Pricing comparison across competitors | |
| recommendations | Yes | 3-6 actionable strategic recommendations | |
| presenterScript | Yes | 8-12 slide board presenter script | |
| kpis | No | 3-5 headline KPI bubbles | |
| sources | No | Cited sources |
Implementation Reference
- src/tools/competitor-intel.ts:144-145 (handler)The handler function for the competitor_intel tool. Delegates to callGapupEndpoint('competitor-intel', input, signal) to make an HTTP POST to the Gapup API.
export async function handle(input: unknown, signal?: AbortSignal): Promise<unknown> { return callGapupEndpoint("competitor-intel", input, signal); - src/tools/competitor-intel.ts:3-142 (schema)Full tool definition including name ('competitor_intel'), description, inputSchema (selfCompany, competitors, focus), outputSchema (executiveSummary, competitorMoves, pricingRadar, recommendations, presenterScript, kpis, sources), and annotations.
export const tool = { name: "competitor_intel", description: "Generate a board-ready competitive-intelligence report for a company against named competitors. Returns: recent competitor moves (product releases, pricing changes, hiring, funding) each with a severity score (critical/high/medium/low), prioritised signals, a pricing-radar comparison, 3-6 quantified recommendations (expected impact in € or %, over 7/30/90/180-day horizons), and an 8-12 slide presenter script. When to use this tool: the user wants to analyse, benchmark or track competitors, or needs a competitive briefing before a strategic decision. Inputs: the user's own company (name + one-paragraph pitch) and 1-10 competitors to analyse. Delivered by Manue, the AI CMO of the Gapup portfolio.", inputSchema: { type: "object", properties: { selfCompany: { type: "object", description: "Your company info", properties: { name: { type: "string", minLength: 2, maxLength: 120 }, url: { type: "string", format: "uri" }, pitch: { type: "string", minLength: 10, maxLength: 400, description: "One-paragraph pitch" }, }, required: ["name", "pitch"], }, competitors: { type: "array", description: "1-10 competitors to analyze", items: { type: "object", properties: { name: { type: "string", minLength: 2, maxLength: 120 }, url: { type: "string", format: "uri" }, }, required: ["name", "url"], }, minItems: 1, maxItems: 10, }, focus: { type: "string", maxLength: 400, description: "Optional — what the buyer wants to track first (e.g. pricing moves, hiring patterns)", }, }, required: ["selfCompany", "competitors"], }, outputSchema: { type: "object", properties: { executiveSummary: { type: "string", description: "Board-ready prose summary (120-400 chars)", }, competitorMoves: { type: "array", description: "Recent moves per competitor with severity rating", items: { type: "object", properties: { competitor: { type: "string" }, move: { type: "string" }, severity: { type: "string", enum: ["critical", "high", "medium", "low"] }, date: { type: "string" }, source: { type: "string" }, }, required: ["competitor", "move", "severity"], }, }, pricingRadar: { type: "array", description: "Pricing comparison across competitors", items: { type: "object", properties: { competitor: { type: "string" }, tier: { type: "string" }, priceEur: { type: "number" }, features: { type: "array", items: { type: "string" } }, }, required: ["competitor"], }, }, recommendations: { type: "array", description: "3-6 actionable strategic recommendations", items: { type: "object", properties: { action: { type: "string" }, expectedImpact: { type: "string" }, horizon: { type: "string", enum: ["7d", "30d", "90d", "180d"] }, priority: { type: "string", enum: ["critical", "high", "medium", "low"] }, }, required: ["action", "expectedImpact", "horizon"], }, }, presenterScript: { type: "array", description: "8-12 slide board presenter script", items: { type: "object", properties: { slide: { type: "integer" }, title: { type: "string" }, keyPoints: { type: "array", items: { type: "string" } }, speakerNote: { type: "string" }, visualHint: { type: "string" }, }, required: ["slide", "title", "keyPoints", "speakerNote"], }, }, kpis: { type: "array", description: "3-5 headline KPI bubbles", items: { type: "object", properties: { label: { type: "string" }, value: { type: "string" }, trend: { type: "string", enum: ["up", "down", "stable"] }, }, required: ["label", "value"], }, }, sources: { type: "array", description: "Cited sources", items: { type: "object", properties: { url: { type: "string" }, excerpt: { type: "string" }, }, required: ["url"], }, }, }, required: ["executiveSummary", "competitorMoves", "recommendations", "presenterScript"], }, annotations: { readOnlyHint: true, idempotentHint: true, destructiveHint: false, openWorldHint: true, title: "Competitor Intelligence Report", }, } as const; - src/index.ts:21-21 (registration)Import of the tool definition and handler from the competitor-intel module.
import { tool as competitorIntelTool, handle as competitorIntelHandle } from "./tools/competitor-intel.js"; - src/index.ts:37-37 (registration)Registration of competitorIntelTool and competitorIntelHandle in the TOOLS array, linking the tool definition to its handler for the MCP server.
{ def: competitorIntelTool, handle: competitorIntelHandle }, - src/client.ts:26-86 (helper)The callGapupEndpoint helper function that performs the actual HTTP request. It POSTs to /api/agent/{slug} with the X-Api-Key header and handles errors (401, 402, 404, 429, and others).
export async function callGapupEndpoint( slug: string, input: unknown, signal?: AbortSignal ): Promise<unknown> { const apiKey = process.env.GAPUP_API_KEY; if (!apiKey) { throw new GapupAuthError( "GAPUP_API_KEY environment variable required. Get a free tier key (100 calls/mo) at https://hub.gapup.io/agents-api/onboard" ); } const res = await fetch(`${HUB_BASE_URL}/api/agent/${slug}`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Key": apiKey, "Accept": "application/json", "User-Agent": "@gapup/mcp-knowledge/0.1.0", }, body: JSON.stringify(input), signal, }); if (res.status === 401) { throw new GapupAuthError( "Invalid or missing GAPUP_API_KEY. Verify your key at https://hub.gapup.io/agents-api/onboard" ); } if (res.status === 402) { const body = await res.text().catch(() => ""); throw new GapupAuthError( `Free tier quota exhausted or paid auth required. Upgrade at https://hub.gapup.io/agents-api (received 402: ${body.slice(0, 120)})` ); } if (res.status === 404) { throw new GapupApiError( 404, `Endpoint '${slug}' not found — check GAPUP_API_BASE_URL or update the package (npm update @gapup/mcp-knowledge)` ); } if (res.status === 429) { const retryAfter = res.headers.get("Retry-After"); const retryMsg = retryAfter ? ` Retry after ${retryAfter} seconds.` : ""; const body = await res.text().catch(() => ""); throw new GapupApiError( 429, `Rate limit exceeded.${retryMsg} Upgrade your plan at https://hub.gapup.io/agents-api (received: ${body.slice(0, 100)})` ); } if (!res.ok) { const body = await res.text().catch(() => ""); throw new GapupApiError(res.status, body); } return res.json(); }