MCP Stack
Every tool RapBotRito can call lives in the Model Context Protocol stack housed under dapp/app/lib/mcp. The architecture focuses on three qualities:
- Central registration —
toolRegistry(dapp/app/lib/mcp/tools/index.ts) registers each tool once and decides whether it should even exist (e.g., send-crypto tools only load whenAI_PRIVATE_KEYis set, Pinecone tools only when configured). - Layered authentication — The MCP HTTP route (
dapp/app/api/mcp/route.ts) optionally enforces JWTs globally, whileMCPDispatcherforces another verification for tools withrequiresJwt. - Mode-aware exposure —
getOpenAIToolSchemas(dapp/app/lib/llm/tool-bridge.ts) filters the registry based on the active chat mode, so rap battles, freestyle, and agent battles each receive different tool manifests.
These tools span multiple systems:
- On-chain — Key NFT reads/writes plus ETH transfers via the AI signer.
- Semantic search — Pinecone-backed
pinecone_searchfor lore, memes, and rhymes. - Media generation & vision — OpenAI image workflows and inline renderers (e.g.,
generate_image_with_alt). - Postgres/Prisma — Quota tracking, Key NFT usage, and other stateful mutations stored in our primary DB.
Server & Auth Highlights
- JWT extraction happens in
dapp/app/lib/mcp/server/auth.ts, which checks headers, body payloads, and cookies. Verified claims (sub,address,tokenId) are injected into tool args under__jwt. - Per-tool gating is opt-in. Any tool definition can set
requiresJwt: true, causing the dispatcher to re-run verification and add JWT metadata to the handler args. This pattern powers the Key NFT mutation tools, crypto senders, and quota-sensitive APIs. - Error propagation uses the
ToolFailurehelper intool-errors.tsso handlers canfail('message'). The SSE pipeline picks up these errors to show red chips in the UI and feed concise summaries back to the LLM.
Tool Catalog
Each tool now has a dedicated deep dive. Use this table as a hub:
| Tool | Summary | Docs |
|---|---|---|
generate_rap_verse | Multi-phase agent that crafts verses, images, and metadata. | Read more → |
generate_image_with_alt | Streams store:// images plus alt text for inline rendering. | Read more → |
pinecone_search | Semantic retrieval across memes, rhymes, gifs, and lore. | Read more → |
get_eth_balance | Direct RPC balance checks across every configured chain. | Read more → |
send_crypto_to_signed_in_user | Native transfers with JWT gating and crypto quotas. | Read more → |
send_crypto_agent | Persona-based reviewer that may call the send-crypto tool. | Read more → |
mark_key_used | Marks a user’s Key NFT as consumed inside Prisma. | Read more → |
key_nft_read | All read-only Key NFT actions (balances, holders, metadata). | Read more → |
manage_key_nft | Mint/burn/query using the AI signer. | Read more → |
keynft_used_count | Counts how many gated entries have been consumed. | Read more → |
Each page covers registry wiring, handler logic, and the corresponding presenter so you can see how backend behavior maps onto the inline chips described in the Chat Experience section.
Mode Whitelists
Each chat mode (dapp/app/lib/llm/modes/configs/*.ts) declares an mcpTools array. For example:
- Rap Battle — balances aggression with limited on-chain actions (
get_eth_balance,send_crypto_to_signed_in_user,mark_key_used,pinecone_search,generate_image_with_alt). - Freestyle — unlocks more playful tools (
key_nft_read,keynft_used_count,manage_key_nft,send_crypto_agent). - Agent Battle — relies heavily on
generate_rap_verse,send_crypto_to_signed_in_user, andmark_key_usedto enforce the high-stakes format.
Model manifests are regenerated per request. If you add a tool, simply register it and decide which modes may see it—no further wiring is needed.