suggest
Analyzes user questions about business, startups, investing, crypto, AI, leadership, decisions, or life advice to suggest ready-to-execute actions from a council of tech and investing legends.
Instructions
🔮 PROACTIVE LEGEND SUGGESTER - Returns ready-to-execute actions!
⚡ USE THIS PROACTIVELY on questions about: business, startups, investing, crypto, AI, leadership, decisions, life advice
HOW IT WORKS:
Pass user's message →
suggest({ message: "..." })Get back
primary_actionwith ready-to-use paramsEXECUTE the suggested action (party_mode or summon_legend)
RETURNS READY ACTIONS:
EXAMPLE FLOW:
OR for single legend:
WHEN TO USE EACH TOOL:
party_mode: Complex questions, "pros/cons", "different perspectives", debates
summon_legend: Specific expertise needed, single mentor preferred
auto_match: Deep analysis, unsure which legend, want detailed matching
ALL 3 ARE ALWAYS SUGGESTED - pick the best fit for the user's needs!
DISCLAIMER: AI personas for educational purposes only.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | The user's message or question to analyze for legend relevance |
Implementation Reference
- src/tools/suggest.ts:114-270 (handler)Core handler function that analyzes user message using keyword matching against TOPIC_MAP, computes legend scores, determines party mode suitability, generates ready-to-use suggested actions (summon_legend, party_mode, auto_match), and returns structured Suggestion object with instruction for Claude.export function suggest(input: SuggestInput): Suggestion { const msg = safeString(input.message, '').toLowerCase(); if (!msg || msg.length < 5) { return { should_invoke: false, confidence: 'low', recommended_legends: [], use_party_mode: false, suggested_actions: [], primary_action: null, instruction: 'No legend recommendation for this message.', }; } // Score legends based on keyword matches const scores = new Map<string, { score: number; reasons: string[] }>(); for (const [keyword, data] of Object.entries(TOPIC_MAP)) { if (msg.includes(keyword)) { for (const legendId of data.legends) { const current = scores.get(legendId) || { score: 0, reasons: [] }; current.score += data.boost; current.reasons.push(keyword); scores.set(legendId, current); } } } // Get top matches const sorted = Array.from(scores.entries()) .sort((a, b) => b[1].score - a[1].score) .slice(0, 3); // Determine confidence const topScore = sorted[0]?.[1].score || 0; let confidence: 'high' | 'medium' | 'low' = 'low'; if (topScore >= 5) confidence = 'high'; else if (topScore >= 3) confidence = 'medium'; // Check if party mode would be beneficial let usePartyMode = false; let partyModeReason = ''; for (const pattern of PARTY_MODE_TRIGGERS) { if (new RegExp(pattern, 'i').test(msg)) { usePartyMode = true; partyModeReason = `Question suggests wanting multiple perspectives (matched: "${pattern}")`; break; } } // Also suggest party mode for complex questions with multiple high-scoring legends if (sorted.length >= 2 && sorted[0][1].score >= 3 && sorted[1][1].score >= 3) { usePartyMode = true; partyModeReason = partyModeReason || 'Multiple legends have strong expertise in this area'; } // Build recommendations const allLegends = getAllLegends(); const recommended = sorted.map(([id, data]) => { const legend = allLegends.find(l => l.id === id); return { id, name: legend?.name || id, why: data.reasons.join(', '), }; }); // Build suggested actions with ready-to-use parameters const suggestedActions: SuggestedAction[] = []; let instruction = ''; if (recommended.length > 0 && topScore >= 2) { // Always add party_mode option if 2+ legends match if (recommended.length >= 2) { suggestedActions.push({ tool: 'party_mode', params: { question: input.message, legends: recommended.slice(0, 3).map(l => l.id), max_legends: Math.min(recommended.length, 3), }, description: `Get perspectives from ${recommended.slice(0, 3).map(l => l.name).join(', ')}`, }); } // Always add summon_legend for top match suggestedActions.push({ tool: 'summon_legend', params: { legend_id: recommended[0].id, context: input.message, }, description: `Ask ${recommended[0].name} (expert in ${recommended[0].why})`, }); // Add second legend option if available if (recommended.length >= 2) { suggestedActions.push({ tool: 'summon_legend', params: { legend_id: recommended[1].id, context: input.message, }, description: `Ask ${recommended[1].name} (expert in ${recommended[1].why})`, }); } // Always add auto_match for deeper exploration suggestedActions.push({ tool: 'auto_match', params: { question: input.message, max_matches: 3, include_prompts: false, }, description: `Deep dive: Get detailed analysis of which legends best match this question`, }); } // Determine primary action and instruction let primaryAction: SuggestedAction | null = null; if (suggestedActions.length > 0) { if (usePartyMode && suggestedActions.find(a => a.tool === 'party_mode')) { primaryAction = suggestedActions.find(a => a.tool === 'party_mode')!; instruction = `🎯 **RECOMMENDED: Use party_mode** for multiple perspectives from ${recommended.slice(0, 3).map(l => l.name).join(', ')}.\n\nCall: \`party_mode({ question: "${input.message.slice(0, 100)}${input.message.length > 100 ? '...' : ''}", legends: ${JSON.stringify(recommended.slice(0, 3).map(l => l.id))} })\``; } else { primaryAction = suggestedActions.find(a => a.tool === 'summon_legend')!; instruction = `🎯 **RECOMMENDED: Summon ${recommended[0].name}** (${recommended[0].why}).\n\nCall: \`summon_legend({ legend_id: "${recommended[0].id}", context: "${input.message.slice(0, 80)}${input.message.length > 80 ? '...' : ''}" })\``; } // Add alternatives if (suggestedActions.length > 1) { instruction += '\n\n**Alternatives:**\n'; suggestedActions.slice(0, 3).forEach((action, i) => { if (action !== primaryAction) { instruction += `${i + 1}. ${action.description}\n`; } }); } } else { instruction = 'No legend recommendation for this message.'; } return { should_invoke: topScore >= 2, confidence, recommended_legends: recommended, use_party_mode: usePartyMode, party_mode_reason: partyModeReason || undefined, suggested_actions: suggestedActions, primary_action: primaryAction, instruction, }; }
- src/tools/suggest.ts:317-383 (schema)Input/output schema and detailed description for the 'suggest' tool, instructing proactive use and providing example flows.export const suggestTool = { name: 'suggest', description: `🔮 **PROACTIVE LEGEND SUGGESTER** - Returns ready-to-execute actions! **⚡ USE THIS PROACTIVELY** on questions about: business, startups, investing, crypto, AI, leadership, decisions, life advice **HOW IT WORKS:** 1. Pass user's message → \`suggest({ message: "..." })\` 2. Get back \`primary_action\` with ready-to-use params 3. **EXECUTE the suggested action** (party_mode or summon_legend) **RETURNS READY ACTIONS:** \`\`\`json { "primary_action": { "tool": "party_mode", // or "summon_legend" "params": { ... }, // Ready to pass directly! "description": "Get perspectives from Paul Graham, Marc Andreessen" }, "suggested_actions": [ ... ], // All options "instruction": "🎯 RECOMMENDED: Use party_mode..." } \`\`\` **EXAMPLE FLOW:** \`\`\` User: "How do I raise my seed round?" 1. Call: suggest({ message: "How do I raise my seed round?" }) 2. Response includes: primary_action.tool = "party_mode" primary_action.params = { question: "...", legends: ["paul-graham", "marc-andreessen", "bill-gurley"] } 3. Execute: party_mode(primary_action.params) → Multiple legends discuss the question! \`\`\` **OR for single legend:** \`\`\` primary_action.tool = "summon_legend" primary_action.params = { legend_id: "paul-graham", context: "..." } Execute: summon_legend(primary_action.params) → Paul Graham responds in character! \`\`\` **WHEN TO USE EACH TOOL:** - **party_mode**: Complex questions, "pros/cons", "different perspectives", debates - **summon_legend**: Specific expertise needed, single mentor preferred - **auto_match**: Deep analysis, unsure which legend, want detailed matching **ALL 3 ARE ALWAYS SUGGESTED** - pick the best fit for the user's needs! DISCLAIMER: AI personas for educational purposes only.`, inputSchema: { type: 'object' as const, properties: { message: { type: 'string', description: 'The user\'s message or question to analyze for legend relevance', }, }, required: ['message'], }, };
- src/tools/index.ts:22-31 (registration)Tool registration: 'suggest' tool is included first in the allTools array exported for MCP server ListTools handler.export const allTools = [ suggestTool, // First! Claude should see this first for proactive use listLegendsTool, summonLegendTool, getLegendContextTool, getLegendInsightTool, searchLegendsTool, partyModeTool, autoMatchTool, ];
- src/index.ts:259-301 (registration)MCP server dispatch handler in CallToolRequestSchema switch statement that invokes the suggest function and formats the response.case 'suggest': { const input = args as { message: string }; if (!input.message) { return { content: [{ type: 'text', text: 'Error: message parameter is required' }], isError: true, }; } try { const result = suggest(input); // If no suggestion needed, return minimal response if (!result.should_invoke) { return { content: [{ type: 'text', text: JSON.stringify({ should_invoke: false, confidence: 'low' }), }], }; } // Return structured suggestion const formatted = formatSuggestion(result, input.message); return { content: [{ type: 'text', text: formatted + '\n\n```json\n' + JSON.stringify(result, null, 2) + '\n```', }], }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], isError: true, }; } }
- src/tools/suggest.ts:275-314 (helper)Helper function to format the Suggestion object into human-readable markdown with ready-to-use action JSON.export function formatSuggestion(suggestion: Suggestion, originalMessage: string): string { if (!suggestion.should_invoke) { return ''; // Return empty - no suggestion needed } const lines: string[] = [ '# 💡 Legend Suggestion', '', suggestion.instruction, '', '---', '', ]; // Show all available actions if (suggestion.suggested_actions.length > 0) { lines.push('## Ready-to-Use Actions'); lines.push(''); suggestion.suggested_actions.forEach((action, i) => { const isPrimary = action === suggestion.primary_action; lines.push(`### ${isPrimary ? '⭐ ' : ''}Option ${i + 1}: ${action.tool}`); lines.push(`${action.description}`); lines.push('```json'); lines.push(JSON.stringify(action.params, null, 2)); lines.push('```'); lines.push(''); }); } lines.push('---'); lines.push(`*Confidence: ${suggestion.confidence}* | *Legends matched: ${suggestion.recommended_legends.length}*`); if (suggestion.party_mode_reason) { lines.push(''); lines.push(`*Party mode reason: ${suggestion.party_mode_reason}*`); } return lines.join('\n'); }