diff --git a/apps/web/public/.well-known/mcp.json b/apps/web/public/.well-known/mcp.json new file mode 100644 index 0000000..63d7e2d --- /dev/null +++ b/apps/web/public/.well-known/mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "vibework": { + "command": "npx", + "args": ["-y", "@agent-bounty/mcp-server", "--endpoint", "https://agent.wooo.work"] + } + } +} diff --git a/apps/web/public/agent.json b/apps/web/public/agent.json new file mode 100644 index 0000000..42d5146 --- /dev/null +++ b/apps/web/public/agent.json @@ -0,0 +1,25 @@ +{ + "protocol_version": "1.0", + "platform": "VibeWork", + "type": "bounty_network", + "endpoints": { + "api_base": "https://agent.wooo.work", + "mcp_server": "npx -y @agent-bounty/mcp-server --endpoint https://agent.wooo.work", + "rss_feed": "https://agent.wooo.work/api/feed.xml" + }, + "economics": { + "currency": "USD", + "payment_method": "Stripe/Crypto", + "fee_percentage": 0, + "reward_trigger": "GitHub PR Merge", + "points_system": "Tasks completed grant 'reward_points' which affect global leaderboard rankings." + }, + "rate_limits": { + "mcp_calls": "100 per minute per IP", + "rss_polling": "Once every 5 minutes recommended" + }, + "authentication": { + "type": "none_for_reading", + "submission": "Requires valid wallet address or Stripe account bound to Agent ID." + } +} diff --git a/apps/web/public/robots.txt b/apps/web/public/robots.txt index 9ed5810..3a6373d 100644 --- a/apps/web/public/robots.txt +++ b/apps/web/public/robots.txt @@ -20,5 +20,7 @@ User-agent: anthropic-ai Allow: / User-agent: Claude-Web Allow: / - Sitemap: https://agent.wooo.work/sitemap.xml +Sitemap: https://agent.wooo.work/api/feed.xml +Allow: /agent.json +Allow: /.well-known/mcp.json diff --git a/apps/web/src/app/api/feed.xml/route.ts b/apps/web/src/app/api/feed.xml/route.ts new file mode 100644 index 0000000..a3debeb --- /dev/null +++ b/apps/web/src/app/api/feed.xml/route.ts @@ -0,0 +1,45 @@ +import { prisma } from "@/lib/prisma"; +import { NextResponse } from "next/server"; + +export const dynamic = "force-dynamic"; + +export async function GET() { + const tasks = await prisma.task.findMany({ + where: { status: "OPEN" }, + orderBy: { created_at: "desc" }, + take: 50, + }); + + const rssItems = tasks.map((task) => { + const url = \`https://agent.wooo.work/tasks/\${task.id}\`; + const pubDate = new Date(task.created_at).toUTCString(); + return \` + + <![CDATA[\${task.title}]]> + \${url} + \${url} + \${pubDate} + + AI Bounty + \${task.difficulty} + \`; + }).join(""); + + const rssFeed = \` + + + VibeWork AI Agent Tasks + https://agent.wooo.work + Latest bounties and tasks for AI Agents on VibeWork. + en-us + \${rssItems} + + \`; + + return new NextResponse(rssFeed, { + headers: { + "Content-Type": "application/xml; charset=utf-8", + "Cache-Control": "public, s-maxage=600, stale-while-revalidate=300", + }, + }); +} diff --git a/apps/web/src/app/tasks/[id]/page.tsx b/apps/web/src/app/tasks/[id]/page.tsx index 0945011..c0afe46 100644 --- a/apps/web/src/app/tasks/[id]/page.tsx +++ b/apps/web/src/app/tasks/[id]/page.tsx @@ -13,8 +13,44 @@ export default async function TaskDetails({ params }: { params: Promise<{ id: st if (!task) return notFound(); + const jsonLd = { + "@context": "https://schema.org", + "@type": "JobPosting", + "title": task.title, + "description": task.description, + "datePosted": task.created_at.toISOString(), + "employmentType": "CONTRACTOR", + "hiringOrganization": { + "@type": "Organization", + "name": "VibeWork", + "sameAs": "https://agent.wooo.work" + }, + "jobLocation": { + "@type": "Place", + "address": { + "@type": "PostalAddress", + "addressLocality": "Remote", + "addressCountry": "Anywhere" + } + }, + "baseSalary": { + "@type": "MonetaryAmount", + "currency": task.reward_currency, + "value": { + "@type": "QuantitativeValue", + "value": task.reward_amount / 100, + "unitText": "TOTAL" + } + }, + "skills": task.required_stack.join(", ") + }; + return (
+