create_blueprint
Generate custom tech stack blueprints for software projects by specifying project type, scale, and priorities to receive tailored technology recommendations.
Instructions
Creates a new tech stack blueprint for a project. Requires API key with 'blueprint:write' scope.
The blueprint generation is asynchronous. By default, this tool waits for completion and returns the full blueprint. Set waitForCompletion=false to get the job ID immediately for manual polling.
Example usage:
Create a SaaS MVP: projectType="saas", scale="mvp", priorities=["time-to-market", "cost-efficiency"]
Create an enterprise API: projectType="api", scale="enterprise", priorities=["security", "scalability"]
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectName | No | Project name (optional) | |
| projectType | Yes | Type of project | |
| scale | Yes | Project scale | |
| projectDescription | No | Brief description (optional) | |
| priorities | No | Top 3 priorities (optional) | |
| constraints | No | Technology constraint IDs (optional) | |
| waitForCompletion | No | Wait for completion (default: true) |
Implementation Reference
- src/tools/blueprint.ts:297-407 (handler)The primary handler function that implements the core logic of the 'create_blueprint' tool. It constructs the API request, handles synchronous and asynchronous creation (with polling), fetches and formats the blueprint, and manages errors with user-friendly suggestions.export async function executeCreateBlueprint( input: CreateBlueprintInput ): Promise<{ text: string; isError?: boolean }> { const { projectName, projectType, scale, projectDescription, priorities, constraints, waitForCompletion = true } = input; debug('Creating blueprint', { projectType, scale, waitForCompletion }); try { // Build request body const requestBody: CreateBlueprintRequest = { projectName, projectContext: { projectName, projectType, projectDescription, scale, priorities: priorities as CreateBlueprintRequest['projectContext']['priorities'], constraintIds: constraints }, source: 'mcp', mcpToolName: 'create_blueprint' }; // Create the blueprint job const createResponse = await createBlueprintRequest(requestBody); // If already completed (cached result), fetch and return if (createResponse.status === 'completed' && createResponse.resultRef) { const blueprint = await getBlueprintRequest<BlueprintApiResponse>(createResponse.resultRef); const text = formatBlueprint(blueprint); return { text: `## Blueprint Created (Cached)\n\n${text}\n\n---\n*Source: MCP Server*` }; } // If not waiting, return job info if (!waitForCompletion) { return { text: `## Blueprint Generation Started **Job ID**: ${createResponse.jobId} **Project ID**: ${createResponse.projectId} **Status**: ${createResponse.status} **Progress**: ${createResponse.progress}% Poll the job status at: ${createResponse._links.job} Once complete, fetch the blueprint at: ${createResponse._links.blueprint || 'TBD'} --- *Source: MCP Server*` }; } // Poll until completion debug('Polling job until completion', { jobId: createResponse.jobId }); const finalStatus = await pollJobUntilComplete(createResponse.jobId); if (!finalStatus.resultRef) { throw new McpError(ErrorCode.API_ERROR, 'Job completed but no blueprint ID returned'); } // Fetch the completed blueprint const blueprint = await getBlueprintRequest<BlueprintApiResponse>(finalStatus.resultRef); const text = formatBlueprint(blueprint); return { text: `## Blueprint Created Successfully ${text} --- **Job ID**: ${createResponse.jobId} **Project ID**: ${createResponse.projectId} *Source: MCP Server*` }; } catch (err) { if (err instanceof McpError) { // Add helpful suggestions for common errors if (err.code === ErrorCode.CONFIG_ERROR) { err.suggestions = [ 'Ensure STACKSFINDER_API_KEY is set with a valid Pro or Team API key.', 'Get your API key from https://stacksfinder.com/settings/api' ]; } else if (err.code === ErrorCode.UNAUTHORIZED) { err.suggestions = [ "Your API key may be invalid or missing the 'blueprint:write' scope.", 'Generate a new API key with the correct permissions at https://stacksfinder.com/settings/api' ]; } else if (err.code === ErrorCode.RATE_LIMITED) { err.suggestions = [ 'You have exceeded your monthly blueprint quota.', 'Upgrade your plan at https://stacksfinder.com/pricing' ]; } return { text: err.toResponseText(), isError: true }; } const error = new McpError( ErrorCode.API_ERROR, err instanceof Error ? err.message : 'Failed to create blueprint' ); return { text: error.toResponseText(), isError: true }; }
- src/tools/blueprint.ts:173-199 (schema)Zod schema defining the input validation and types for the create_blueprint tool parameters, including project details, priorities, and options.export const CreateBlueprintInputSchema = z.object({ projectName: z.string().min(1).max(100).optional().describe('Project name (optional)'), projectType: z .enum(PROJECT_TYPES) .describe('Type of project (e.g., web-app, saas, api)'), scale: z.enum(SCALES).describe('Project scale (mvp, startup, growth, enterprise)'), projectDescription: z .string() .max(2000) .optional() .describe('Brief project description (optional)'), priorities: z .array(z.enum(PRIORITIES)) .max(3) .optional() .describe('Top 3 priorities (optional)'), constraints: z .array(z.string()) .max(20) .optional() .describe('Technology constraint IDs (optional)'), waitForCompletion: z .boolean() .optional() .default(true) .describe('Wait for blueprint generation to complete (default: true)') });
- src/server.ts:215-265 (registration)MCP server registration for the 'create_blueprint' tool, wiring the tool definition, input schema, and handler execution.server.registerTool( createBlueprintToolDefinition.name, { title: 'Create Blueprint', description: createBlueprintToolDefinition.description, inputSchema: { projectName: z.string().max(100).optional().describe('Project name (optional)'), projectType: z .enum([ 'web-app', 'mobile-app', 'api', 'desktop', 'cli', 'library', 'e-commerce', 'saas', 'marketplace' ]) .describe('Type of project'), scale: z.enum(['mvp', 'startup', 'growth', 'enterprise']).describe('Project scale'), projectDescription: z.string().max(2000).optional().describe('Brief description (optional)'), priorities: z .array( z.enum([ 'time-to-market', 'scalability', 'developer-experience', 'cost-efficiency', 'performance', 'security', 'maintainability' ]) ) .max(3) .optional() .describe('Top 3 priorities (optional)'), constraints: z.array(z.string()).max(20).optional().describe('Technology constraint IDs (optional)'), waitForCompletion: z.boolean().optional().describe('Wait for completion (default: true)') } }, async (args) => { debug('create_blueprint called', args); const input = CreateBlueprintInputSchema.parse(args); const { text, isError } = await executeCreateBlueprint(input); return { content: [{ type: 'text', text }], isError }; } );
- src/tools/blueprint.ts:206-259 (schema)Tool definition object used for MCP registration, including name, description, and JSON schema for inputs.export const createBlueprintToolDefinition = { name: 'create_blueprint', description: `Creates a new tech stack blueprint for a project. Requires API key with 'blueprint:write' scope. The blueprint generation is asynchronous. By default, this tool waits for completion and returns the full blueprint. Set waitForCompletion=false to get the job ID immediately for manual polling. Example usage: - Create a SaaS MVP: projectType="saas", scale="mvp", priorities=["time-to-market", "cost-efficiency"] - Create an enterprise API: projectType="api", scale="enterprise", priorities=["security", "scalability"]`, inputSchema: { type: 'object' as const, properties: { projectName: { type: 'string', description: 'Project name (optional)', maxLength: 100 }, projectType: { type: 'string', enum: PROJECT_TYPES, description: 'Type of project' }, scale: { type: 'string', enum: SCALES, description: 'Project scale' }, projectDescription: { type: 'string', description: 'Brief project description (optional)', maxLength: 2000 }, priorities: { type: 'array', items: { type: 'string', enum: PRIORITIES }, maxItems: 3, description: 'Top 3 priorities (optional)' }, constraints: { type: 'array', items: { type: 'string' }, maxItems: 20, description: 'Technology constraint IDs (optional)' }, waitForCompletion: { type: 'boolean', description: 'Wait for blueprint generation to complete (default: true)', default: true } }, required: ['projectType', 'scale'] } };
- src/tools/blueprint.ts:264-292 (helper)Helper function that polls the blueprint job status until completion, with timeout handling.async function pollJobUntilComplete( jobId: string, maxAttempts = 30, intervalMs = 2000 ): Promise<JobStatusResponse> { for (let attempt = 0; attempt < maxAttempts; attempt++) { const status = await getJobStatusRequest(jobId); if (status.status === 'completed') { return status; } if (status.status === 'failed' || status.status === 'cancelled') { throw new McpError( ErrorCode.API_ERROR, status.errorMessage || `Job ${status.status}: ${status.errorCode || 'Unknown error'}` ); } // Wait before next poll await new Promise((resolve) => setTimeout(resolve, intervalMs)); } throw new McpError( ErrorCode.TIMEOUT, `Blueprint generation timed out after ${(maxAttempts * intervalMs) / 1000} seconds`, ['The job is still running. Use get_blueprint with the job resultRef to check later.'] ); }