Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { gigsService } from '@/lib/services/GigsService';
- import { createMcpHandler } from '@vercel/mcp-adapter';
- import { z } from 'zod';
- import { SupportedPlatforms } from '@/lib/types/gigs';
- import { formatUnits } from 'viem';
- import { calculateDuration } from '@/lib/utils/common';
- const handler = createMcpHandler(
- (server) => {
- // TOOL 1 — list_gigs
- // @ts-ignore
- server.tool(
- 'list_gigs',
- 'List all gigs on Gigbot',
- {
- platform: z.string().optional(),
- gig_type: z.string().optional(),
- },
- async (input) => {
- console.log('list_gigs', input);
- const gigs = await gigsService.getGigs({
- status: ['active'],
- platforms: input.platform
- ? ([input.platform] as SupportedPlatforms[])
- : undefined,
- types: input.gig_type ? ([input.gig_type] as string[]) : undefined,
- });
- const visibleGigs = gigs.slice(0, 6);
- const rest = gigs.length - visibleGigs.length;
- const visibleText = visibleGigs.map((gig) => {
- const type = gig.gig_type?.id ?? 'unknown';
- const platform = gig.platform ?? 'unknown';
- const howToEarn = gig.how_to_earn
- ? gig.how_to_earn.slice(0, 120) +
- (gig.how_to_earn.length > 120 ? '...' : '')
- : '(no instructions)';
- return [
- `🎯 **#${gig.id}** – ${type} gig on ${platform}`,
- `📝 How to Earn: ${howToEarn}`,
- '',
- ].join('\n');
- });
- const farcasterCount = gigs.filter(
- (g) => g.platform === 'farcaster',
- ).length;
- const twitterCount = gigs.filter((g) => g.platform === 'x').length;
- const onchainCount = gigs.filter(
- (g) => g.platform === 'onchain',
- ).length;
- const notableGigs = gigs
- .filter(
- (g) =>
- g.gig_type?.id === 'custom_bounty' ||
- BigInt(g.amount || '0') >= BigInt('30000000000000000'),
- )
- .slice(0, 2);
- const notableText = notableGigs.length
- ? [
- '🏅 Some notable gigs:',
- ...notableGigs.map(
- (g) =>
- `• #${g.id}: ${
- g.how_to_earn?.slice(0, 60).replace(/\n/g, ' ') ||
- 'Special gig'
- }...`,
- ),
- '',
- ]
- : [];
- const summaryText = [
- `📊 There are ${gigs.length} active gigs in total.`,
- '',
- `🧭 Platforms:`,
- `• Farcaster: ${farcasterCount}`,
- `• X (Twitter): ${twitterCount}`,
- `• Onchain: ${onchainCount}`,
- '',
- ...notableText,
- `Need details about any specific one? Just ask by number.`,
- ];
- return {
- content: [
- {
- type: 'text',
- text: [
- '🎉 Here are some active gigs on Gigbot:',
- '',
- ...visibleText,
- rest > 0 ? `...and ${rest} more gigs available.\n` : '',
- ...summaryText,
- ].join('\n'),
- },
- ],
- };
- },
- );
- // TOOL 2 — get_gig_details
- // @ts-ignore
- server.tool(
- 'get_gig_details',
- 'Get detailed information for a gig by ID',
- {
- id: z.string(),
- },
- async ({ id }) => {
- const gig = await gigsService.getGig(Number(id));
- if (!gig) {
- return {
- content: [{ type: 'text', text: `Gig with ID ${id} not found.` }],
- };
- }
- const duration = calculateDuration(gig.start_time_ms, gig.end_time_ms);
- const reward = `${formatUnits(
- BigInt(gig.amount),
- gig.token?.decimals ?? 18,
- )} ${gig.token?.symbol ?? gig.ticker}`;
- const postLink = gig.action_params?.post?.url || gig.external_url || '';
- const instructions = gig.action_params?.post?.text ?? '';
- return {
- content: [
- {
- type: 'text',
- text: [
- `🎯 **Gig #${gig.id}** – ${gig.gig_type.id} gig on ${gig.platform}`,
- '',
- `💰 **Reward:** ${reward}`,
- `🕒 **Duration:** ${duration}`,
- '',
- `📝 **Task:**`,
- gig.how_to_earn,
- '',
- instructions ? `📋 **Instructions:**\n${instructions}` : '',
- '',
- gig.earning_criteria
- ? `📜 **Reward Criteria:**\n${gig.earning_criteria}`
- : '',
- '',
- `🚀 **Complete this gig via:**`,
- `• 🌐 Web: https://gigbot.xyz/gigs/${gig.id}`,
- `• ⚡️ Farcaster Miniapp: https://farcaster.xyz/miniapps/3FMRmta8BM3P/gigbot/gigs/${gig.id}`,
- `• 💬 Telegram Miniapp: https://t.me/gig_alerts_bot?startapp=${gig.id}`,
- '',
- postLink ? `🔗 **Related Link:** ${postLink}` : '',
- ]
- .filter(Boolean)
- .join('\n'),
- },
- ],
- };
- },
- );
- },
- {
- capabilities: {
- tools: {
- list_gigs: {
- description: 'List gigs with optional platform and gig_type filters',
- },
- get_gig_details: {
- description: 'Get detailed information for a gig by ID',
- },
- },
- },
- instructions: `
- You are an assistant for Gigbot. Your job is to help users discover and complete gigs easily.
- You can:
- - List active gigs with optional filters (e.g., by platform or gig type)
- - Highlight recent or notable gigs
- - Show full details for any gig
- - Always include Web, Farcaster Miniapp, and Telegram Miniapp links
- - Never suggest manual completion steps
- When listing:
- - Show a preview (e.g., 5–6 gigs) with type, platform, and short "How to Earn"
- - Summarize remaining gigs by platform (Farcaster / Twitter / Onchain)
- - Mention standout or high-reward gigs (e.g. token holding, special campaigns)
- - Offer to show full details for any gig by number
- When showing gig details:
- - Include: Type, Platform, Duration, Reward
- - Show: How to Earn and Instructions (if any)
- - Always show:
- 🌐 Web → https://gigbot.xyz/gigs/[id]
- ⚡️ Farcaster Miniapp → https://farcaster.xyz/miniapps/3FMRmta8BM3P/gigbot/gigs/[id]
- 💬 Telegram Miniapp → https://t.me/gig_alerts_bot?startapp=[id]
- - Do not describe manual steps like “Go to Farcaster and follow…”
- Keep messages brief, formatted, and actionable.`,
- },
- {
- redisUrl: process.env.REDIS_URL,
- basePath: '/api/mcp/gigs',
- maxDuration: 800,
- verboseLogs: true,
- },
- );
- export const GET = async (request: Request) => {
- return handler(request);
- };
- export const POST = async (request: Request) => {
- return handler(request);
- };
Advertisement
Add Comment
Please, Sign In to add comment