0x0x230x

Untitled

Jun 6th, 2025
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.10 KB | None | 0 0
  1. import { gigsService } from '@/lib/services/GigsService';
  2. import { createMcpHandler } from '@vercel/mcp-adapter';
  3. import { z } from 'zod';
  4. import { SupportedPlatforms } from '@/lib/types/gigs';
  5. import { formatUnits } from 'viem';
  6. import { calculateDuration } from '@/lib/utils/common';
  7.  
  8. const handler = createMcpHandler(
  9. (server) => {
  10. // TOOL 1 — list_gigs
  11. // @ts-ignore
  12. server.tool(
  13. 'list_gigs',
  14. 'List all gigs on Gigbot',
  15. {
  16. platform: z.string().optional(),
  17. gig_type: z.string().optional(),
  18. },
  19. async (input) => {
  20. console.log('list_gigs', input);
  21.  
  22. const gigs = await gigsService.getGigs({
  23. status: ['active'],
  24. platforms: input.platform
  25. ? ([input.platform] as SupportedPlatforms[])
  26. : undefined,
  27. types: input.gig_type ? ([input.gig_type] as string[]) : undefined,
  28. });
  29.  
  30. const visibleGigs = gigs.slice(0, 6);
  31. const rest = gigs.length - visibleGigs.length;
  32.  
  33. const visibleText = visibleGigs.map((gig) => {
  34. const type = gig.gig_type?.id ?? 'unknown';
  35. const platform = gig.platform ?? 'unknown';
  36. const howToEarn = gig.how_to_earn
  37. ? gig.how_to_earn.slice(0, 120) +
  38. (gig.how_to_earn.length > 120 ? '...' : '')
  39. : '(no instructions)';
  40.  
  41. return [
  42. `🎯 **#${gig.id}** – ${type} gig on ${platform}`,
  43. `📝 How to Earn: ${howToEarn}`,
  44. '',
  45. ].join('\n');
  46. });
  47.  
  48. const farcasterCount = gigs.filter(
  49. (g) => g.platform === 'farcaster',
  50. ).length;
  51. const twitterCount = gigs.filter((g) => g.platform === 'x').length;
  52. const onchainCount = gigs.filter(
  53. (g) => g.platform === 'onchain',
  54. ).length;
  55.  
  56. const notableGigs = gigs
  57. .filter(
  58. (g) =>
  59. g.gig_type?.id === 'custom_bounty' ||
  60. BigInt(g.amount || '0') >= BigInt('30000000000000000'),
  61. )
  62. .slice(0, 2);
  63.  
  64. const notableText = notableGigs.length
  65. ? [
  66. '🏅 Some notable gigs:',
  67. ...notableGigs.map(
  68. (g) =>
  69. `• #${g.id}: ${
  70. g.how_to_earn?.slice(0, 60).replace(/\n/g, ' ') ||
  71. 'Special gig'
  72. }...`,
  73. ),
  74. '',
  75. ]
  76. : [];
  77.  
  78. const summaryText = [
  79. `📊 There are ${gigs.length} active gigs in total.`,
  80. '',
  81. `🧭 Platforms:`,
  82. `• Farcaster: ${farcasterCount}`,
  83. `• X (Twitter): ${twitterCount}`,
  84. `• Onchain: ${onchainCount}`,
  85. '',
  86. ...notableText,
  87. `Need details about any specific one? Just ask by number.`,
  88. ];
  89.  
  90. return {
  91. content: [
  92. {
  93. type: 'text',
  94. text: [
  95. '🎉 Here are some active gigs on Gigbot:',
  96. '',
  97. ...visibleText,
  98. rest > 0 ? `...and ${rest} more gigs available.\n` : '',
  99. ...summaryText,
  100. ].join('\n'),
  101. },
  102. ],
  103. };
  104. },
  105. );
  106.  
  107. // TOOL 2 — get_gig_details
  108. // @ts-ignore
  109. server.tool(
  110. 'get_gig_details',
  111. 'Get detailed information for a gig by ID',
  112. {
  113. id: z.string(),
  114. },
  115. async ({ id }) => {
  116. const gig = await gigsService.getGig(Number(id));
  117.  
  118. if (!gig) {
  119. return {
  120. content: [{ type: 'text', text: `Gig with ID ${id} not found.` }],
  121. };
  122. }
  123.  
  124. const duration = calculateDuration(gig.start_time_ms, gig.end_time_ms);
  125. const reward = `${formatUnits(
  126. BigInt(gig.amount),
  127. gig.token?.decimals ?? 18,
  128. )} ${gig.token?.symbol ?? gig.ticker}`;
  129.  
  130. const postLink = gig.action_params?.post?.url || gig.external_url || '';
  131. const instructions = gig.action_params?.post?.text ?? '';
  132.  
  133. return {
  134. content: [
  135. {
  136. type: 'text',
  137. text: [
  138. `🎯 **Gig #${gig.id}** – ${gig.gig_type.id} gig on ${gig.platform}`,
  139. '',
  140. `💰 **Reward:** ${reward}`,
  141. `🕒 **Duration:** ${duration}`,
  142. '',
  143. `📝 **Task:**`,
  144. gig.how_to_earn,
  145. '',
  146. instructions ? `📋 **Instructions:**\n${instructions}` : '',
  147. '',
  148. gig.earning_criteria
  149. ? `📜 **Reward Criteria:**\n${gig.earning_criteria}`
  150. : '',
  151. '',
  152. `🚀 **Complete this gig via:**`,
  153. `• 🌐 Web: https://gigbot.xyz/gigs/${gig.id}`,
  154. `• ⚡️ Farcaster Miniapp: https://farcaster.xyz/miniapps/3FMRmta8BM3P/gigbot/gigs/${gig.id}`,
  155. `• 💬 Telegram Miniapp: https://t.me/gig_alerts_bot?startapp=${gig.id}`,
  156. '',
  157. postLink ? `🔗 **Related Link:** ${postLink}` : '',
  158. ]
  159. .filter(Boolean)
  160. .join('\n'),
  161. },
  162. ],
  163. };
  164. },
  165. );
  166. },
  167. {
  168. capabilities: {
  169. tools: {
  170. list_gigs: {
  171. description: 'List gigs with optional platform and gig_type filters',
  172. },
  173. get_gig_details: {
  174. description: 'Get detailed information for a gig by ID',
  175. },
  176. },
  177. },
  178. instructions: `
  179. You are an assistant for Gigbot. Your job is to help users discover and complete gigs easily.
  180.  
  181. You can:
  182. - List active gigs with optional filters (e.g., by platform or gig type)
  183. - Highlight recent or notable gigs
  184. - Show full details for any gig
  185. - Always include Web, Farcaster Miniapp, and Telegram Miniapp links
  186. - Never suggest manual completion steps
  187.  
  188. When listing:
  189. - Show a preview (e.g., 5–6 gigs) with type, platform, and short "How to Earn"
  190. - Summarize remaining gigs by platform (Farcaster / Twitter / Onchain)
  191. - Mention standout or high-reward gigs (e.g. token holding, special campaigns)
  192. - Offer to show full details for any gig by number
  193.  
  194. When showing gig details:
  195. - Include: Type, Platform, Duration, Reward
  196. - Show: How to Earn and Instructions (if any)
  197. - Always show:
  198. 🌐 Web → https://gigbot.xyz/gigs/[id]
  199. ⚡️ Farcaster Miniapp → https://farcaster.xyz/miniapps/3FMRmta8BM3P/gigbot/gigs/[id]
  200. 💬 Telegram Miniapp → https://t.me/gig_alerts_bot?startapp=[id]
  201. - Do not describe manual steps like “Go to Farcaster and follow…”
  202.  
  203. Keep messages brief, formatted, and actionable.`,
  204. },
  205. {
  206. redisUrl: process.env.REDIS_URL,
  207. basePath: '/api/mcp/gigs',
  208. maxDuration: 800,
  209. verboseLogs: true,
  210. },
  211. );
  212.  
  213. export const GET = async (request: Request) => {
  214. return handler(request);
  215. };
  216.  
  217. export const POST = async (request: Request) => {
  218. return handler(request);
  219. };
  220.  
Advertisement
Add Comment
Please, Sign In to add comment