validate_idea
Validate a startup idea before writing code. Get a 10-dimension Venture Readiness Score, evidence brief, kill/pivot/test/build verdict, and founder-fit insights to avoid building dead-on-arrival products.
Instructions
Validate a startup idea before scaffolding code for it. Returns a scorecard (10-dimension Venture Readiness Score, 0–100), an evidence brief tagged by source (observed / inferred / AI / claim), a kill / pivot / test / build verdict, founder-fit calibration deltas if a skill graph is on file, and 1–3 archetype assignments with structural cautions for that cluster. Call this BEFORE writing project scaffolding when the user is greenfield-building from a raw idea.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rawIdea | Yes | The idea to validate. Free-form text; mess is fine — Trigvale normalizes it. Be specific about who has the pain, who pays, and why now. | |
| save | No | When true, persist the brief to the user's vault so they can revisit it at trigvale.com/ideas/{id}. Default true. Set false for ephemeral checks. |
Implementation Reference
- src/index.ts:36-51 (schema)Zod schema for validate_idea arguments: rawIdea (string, 5-4000 chars) and save (optional boolean, default true).
const ValidateIdeaArgsSchema = z.object({ rawIdea: z .string() .min(5) .max(4000) .describe( "The idea to validate. Free-form text; mess is fine — Trigvale normalizes it. Be specific about who has the pain, who pays, and why now.", ), save: z .boolean() .optional() .default(true) .describe( "When true, persist the brief to the user's vault so they can revisit it at trigvale.com/ideas/{id}. Default true. Set false for ephemeral checks.", ), }); - src/index.ts:65-92 (registration)Registers the validate_idea tool in ListToolsRequestSchema handler with description and inputSchema.
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "validate_idea", description: "Validate a startup idea before scaffolding code for it. Returns a scorecard (10-dimension Venture Readiness Score, 0–100), an evidence brief tagged by source (observed / inferred / AI / claim), a kill / pivot / test / build verdict, founder-fit calibration deltas if a skill graph is on file, and 1–3 archetype assignments with structural cautions for that cluster. Call this BEFORE writing project scaffolding when the user is greenfield-building from a raw idea.", inputSchema: { type: "object", properties: { rawIdea: { type: "string", minLength: 5, maxLength: 4000, description: "The idea to validate. Free-form text; mess is fine — Trigvale normalizes it. Be specific about who has the pain, who pays, and why now.", }, save: { type: "boolean", default: true, description: "When true, persist the brief to the user's vault so they can revisit it at trigvale.com/ideas/{id}. Default true. Set false for ephemeral checks.", }, }, required: ["rawIdea"], }, }, ], })); - src/index.ts:94-131 (handler)Main handler for CallToolRequestSchema: parses args, calls POST /agent/v1/evaluate, and returns both a human-readable summary and full JSON result.
server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== "validate_idea") { throw new Error(`Unknown tool: ${request.params.name}`); } const args = ValidateIdeaArgsSchema.parse(request.params.arguments ?? {}); const res = await fetch(`${apiBase}/agent/v1/evaluate`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${agentToken}`, }, body: JSON.stringify({ rawIdea: args.rawIdea, save: args.save }), }); if (!res.ok) { const text = await res.text(); throw new Error(`Trigvale API ${res.status}: ${text || res.statusText}`); } const body = (await res.json()) as AgentEvaluateResponse; // Return both the structured object (for agent reasoning) and a // human-readable summary block (for chat clients that just render text). return { content: [ { type: "text", text: summarize(body), }, { type: "text", text: "```json\n" + JSON.stringify(body, null, 2) + "\n```", }, ], }; }); - src/index.ts:133-140 (helper)TypeScript interface AgentEvaluateResponse defining the shape of the API response.
interface AgentEvaluateResponse { ideaObject: { title: string }; scorecard: { vrs: number; confidence: string }; verdict: { verdict: string; reasons: string[] }; founderAdjustments?: { dimension: string; delta: number; reason: string }[]; archetypeAssignments?: { archetype: string; confidence: string; rationale: string }[]; saved?: { ideaId: string } | null; } - src/index.ts:142-170 (helper)Helper function summarize() that formats the API response into a human-readable markdown summary.
function summarize(body: AgentEvaluateResponse): string { const lines: string[] = []; lines.push(`# ${body.ideaObject.title}`); lines.push(""); lines.push( `**Verdict: ${body.verdict.verdict.toUpperCase()}** · VRS ${body.scorecard.vrs}/100 · ${body.scorecard.confidence} confidence`, ); lines.push(""); if (body.verdict.reasons?.length) { for (const r of body.verdict.reasons) lines.push(`- ${r}`); lines.push(""); } if (body.archetypeAssignments?.length) { const top = body.archetypeAssignments[0]!; lines.push(`Archetype: **${top.archetype}** (${top.confidence}) — ${top.rationale}`); lines.push(""); } if (body.founderAdjustments?.length) { lines.push("Founder-fit calibration applied:"); for (const a of body.founderAdjustments) { lines.push(`- ${a.dimension}: ${a.delta > 0 ? "+" : ""}${a.delta} (${a.reason})`); } lines.push(""); } if (body.saved?.ideaId) { lines.push(`Saved to vault: https://trigvale.com/ideas/${body.saved.ideaId}`); } return lines.join("\n"); }