1. Added Claude Code sub-agents 2. Added PRD tool to MCP Server 3. Added MCP Server UI to Dev Tools 4. Improved MCP Server Database Tool 5. Updated dependencies
308 lines
9.5 KiB
TypeScript
308 lines
9.5 KiB
TypeScript
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
import { z } from 'zod';
|
|
|
|
interface PromptTemplate {
|
|
name: string;
|
|
title: string;
|
|
description: string;
|
|
category:
|
|
| 'code-review'
|
|
| 'development'
|
|
| 'database'
|
|
| 'testing'
|
|
| 'architecture'
|
|
| 'debugging';
|
|
arguments: Array<{
|
|
name: string;
|
|
description: string;
|
|
required: boolean;
|
|
type: 'string' | 'text' | 'enum';
|
|
options?: string[];
|
|
}>;
|
|
template: string;
|
|
examples?: string[];
|
|
}
|
|
|
|
export class PromptsManager {
|
|
private static prompts: PromptTemplate[] = [
|
|
{
|
|
name: 'code_review',
|
|
title: 'Comprehensive Code Review',
|
|
description:
|
|
'Analyze code for quality, security, performance, and best practices',
|
|
category: 'code-review',
|
|
arguments: [
|
|
{
|
|
name: 'code',
|
|
description: 'The code to review',
|
|
required: true,
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'focus_area',
|
|
description: 'Specific area to focus the review on',
|
|
required: false,
|
|
type: 'enum',
|
|
options: [
|
|
'security',
|
|
'performance',
|
|
'maintainability',
|
|
'typescript',
|
|
'react',
|
|
'all',
|
|
],
|
|
},
|
|
{
|
|
name: 'severity_level',
|
|
description: 'Minimum severity level for issues to report',
|
|
required: false,
|
|
type: 'enum',
|
|
options: ['low', 'medium', 'high', 'critical'],
|
|
},
|
|
],
|
|
template: `Please review the following code with a focus on {{focus_area || 'all aspects'}}.
|
|
|
|
**Code to Review:**
|
|
\`\`\`
|
|
{{code}}
|
|
\`\`\`
|
|
|
|
**Makerkit Standards Review Criteria:**
|
|
|
|
**TypeScript Excellence:**
|
|
- Strict TypeScript with no 'any' types - use explicit types always
|
|
- Implicit type inference preferred unless impossible
|
|
- Proper error handling with try/catch and typed error objects
|
|
- Clean, clear, well-designed code without obvious comments
|
|
|
|
**React & Next.js 15 Best Practices:**
|
|
- Functional components only with 'use client' directive for client components
|
|
- Encapsulate repeated blocks of code into reusable local components
|
|
- Avoid useEffect (code smell) - justify if absolutely necessary
|
|
- Single state objects over multiple useState calls
|
|
- Prefer server-side data fetching using React Server Components
|
|
- Display loading indicators with LoadingSpinner component where appropriate
|
|
- Add data-test attributes for E2E testing where appropriate
|
|
- Server actions that redirect should handle the error using "isRedirectError" from 'next/dist/client/components/redirect-error'
|
|
|
|
**Makerkit Architecture Patterns:**
|
|
- Multi-tenant architecture with proper account-based access control
|
|
- Use account_id foreign keys for data association
|
|
- Personal vs Team accounts pattern implementation
|
|
- Proper use of Row Level Security (RLS) policies
|
|
- Supabase integration best practices
|
|
|
|
**Database Best Practices:**
|
|
- Use existing database functions instead of writing your own
|
|
- RLS are applied to all tables unless explicitly instructed otherwise
|
|
- RLS prevents data leakage between accounts
|
|
- User is prevented from updating fields that are not allowed to be updated (uses column-level permissions)
|
|
- Triggers for tracking timestamps and user tracking are used if required
|
|
- Schema is thorough and covers all data integrity and business rules, but is not unnecessarily complex or over-engineered
|
|
- Schema uses constraints/triggers where required for data integrity and business rules
|
|
- Schema prevents invalid data from being inserted or updated
|
|
|
|
**Code Quality Standards:**
|
|
- No unnecessary complexity or overly abstract code
|
|
- Consistent file structure following monorepo patterns
|
|
- Proper package organization in Turborepo structure
|
|
- Use of @kit/ui components and established patterns
|
|
|
|
{{#if severity_level}}
|
|
**Severity Filter:** Only report issues of {{severity_level}} severity or higher.
|
|
{{/if}}
|
|
|
|
**Please provide:**
|
|
1. **Overview:** Brief summary of code quality
|
|
2. **Issues Found:** List specific problems with severity levels
|
|
3. **Suggestions:** Concrete improvement recommendations
|
|
4. **Best Practices:** Relevant patterns from the Makerkit codebase
|
|
5. **Security Review:** Any security concerns or improvements`,
|
|
examples: [
|
|
'Review a React component for best practices',
|
|
'Security-focused review of authentication code',
|
|
'Performance analysis of database queries',
|
|
],
|
|
},
|
|
{
|
|
name: 'supabase_rls_policy_design',
|
|
title: 'Supabase RLS Policy Design',
|
|
description:
|
|
'Design Row Level Security policies for Makerkit multi-tenant architecture',
|
|
category: 'database',
|
|
arguments: [
|
|
{
|
|
name: 'table_name',
|
|
description: 'Table that needs RLS policies',
|
|
required: true,
|
|
type: 'string',
|
|
},
|
|
{
|
|
name: 'access_patterns',
|
|
description: 'Who should access this data and how',
|
|
required: true,
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'data_sensitivity',
|
|
description: 'Sensitivity level of the data',
|
|
required: true,
|
|
type: 'enum',
|
|
options: [
|
|
'public',
|
|
'account-restricted',
|
|
'role-restricted',
|
|
'owner-only',
|
|
],
|
|
},
|
|
],
|
|
template: `Design RLS policies for table: {{table_name}}
|
|
|
|
**Access Requirements:** {{access_patterns}}
|
|
**Data Sensitivity:** {{data_sensitivity}}
|
|
|
|
**Please provide:**
|
|
|
|
**1. Policy Design:**
|
|
- Complete RLS policy definitions (SELECT, INSERT, UPDATE, DELETE)
|
|
- Use of existing Makerkit functions: has_role_on_account, has_permission
|
|
- Account-based access control following multi-tenant patterns
|
|
|
|
**2. Security Analysis:**
|
|
- How policies enforce account boundaries
|
|
- Role-based access control integration
|
|
- Prevention of data leakage between accounts
|
|
|
|
**3. Performance Considerations:**
|
|
- Index requirements for efficient policy execution
|
|
- Query optimization with RLS overhead
|
|
- Use of SECURITY DEFINER functions where needed
|
|
|
|
**4. Policy SQL:**
|
|
\`\`\`sql
|
|
-- Enable RLS
|
|
ALTER TABLE {{table_name}} ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Your policies here
|
|
\`\`\`
|
|
|
|
**5. Testing Strategy:**
|
|
- Test cases for different user roles and permissions
|
|
- Verification of account isolation
|
|
- Performance testing with large datasets
|
|
|
|
**Makerkit RLS Standards:**
|
|
- All user data must respect account boundaries
|
|
- Use existing permission functions for consistency
|
|
- Personal accounts: auth.users.id = accounts.id
|
|
- Team accounts: check via accounts_memberships table
|
|
- Leverage roles and role_permissions for granular access`,
|
|
examples: [
|
|
'Design RLS for a documents table',
|
|
'Create policies for team collaboration data',
|
|
'Set up RLS for billing and subscription data',
|
|
],
|
|
},
|
|
];
|
|
|
|
static getAllPrompts(): PromptTemplate[] {
|
|
return this.prompts;
|
|
}
|
|
|
|
static getPromptsByCategory(category: string): PromptTemplate[] {
|
|
return this.prompts.filter((prompt) => prompt.category === category);
|
|
}
|
|
|
|
static getPrompt(name: string): PromptTemplate | null {
|
|
return this.prompts.find((prompt) => prompt.name === name) || null;
|
|
}
|
|
|
|
static searchPrompts(query: string): PromptTemplate[] {
|
|
const searchTerm = query.toLowerCase();
|
|
return this.prompts.filter(
|
|
(prompt) =>
|
|
prompt.name.toLowerCase().includes(searchTerm) ||
|
|
prompt.title.toLowerCase().includes(searchTerm) ||
|
|
prompt.description.toLowerCase().includes(searchTerm) ||
|
|
prompt.category.toLowerCase().includes(searchTerm),
|
|
);
|
|
}
|
|
|
|
static renderPrompt(name: string, args: Record<string, string>): string {
|
|
const prompt = this.getPrompt(name);
|
|
if (!prompt) {
|
|
throw new Error(`Prompt "${name}" not found`);
|
|
}
|
|
|
|
// Simple template rendering with Handlebars-like syntax
|
|
let rendered = prompt.template;
|
|
|
|
// Replace {{variable}} placeholders
|
|
rendered = rendered.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
|
|
return args[varName] || '';
|
|
});
|
|
|
|
// Replace {{variable || default}} placeholders
|
|
rendered = rendered.replace(
|
|
/\{\{(\w+)\s*\|\|\s*'([^']*)'\}\}/g,
|
|
(match, varName, defaultValue) => {
|
|
return args[varName] || defaultValue;
|
|
},
|
|
);
|
|
|
|
// Handle conditional blocks {{#if variable}}...{{/if}}
|
|
rendered = rendered.replace(
|
|
/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g,
|
|
(match, varName, content) => {
|
|
return args[varName] ? content : '';
|
|
},
|
|
);
|
|
|
|
return rendered.trim();
|
|
}
|
|
}
|
|
|
|
export function registerPromptsSystem(server: McpServer) {
|
|
// Register all prompts using the SDK's prompt API
|
|
const allPrompts = PromptsManager.getAllPrompts();
|
|
|
|
for (const promptTemplate of allPrompts) {
|
|
// Convert arguments to proper Zod schema format
|
|
const argsSchema = promptTemplate.arguments.reduce(
|
|
(acc, arg) => {
|
|
if (arg.required) {
|
|
acc[arg.name] = z.string().describe(arg.description);
|
|
} else {
|
|
acc[arg.name] = z.string().optional().describe(arg.description);
|
|
}
|
|
return acc;
|
|
},
|
|
{} as Record<string, z.ZodString | z.ZodOptional<z.ZodString>>,
|
|
);
|
|
|
|
server.prompt(
|
|
promptTemplate.name,
|
|
promptTemplate.description,
|
|
argsSchema,
|
|
async (args: Record<string, string>) => {
|
|
const renderedPrompt = PromptsManager.renderPrompt(
|
|
promptTemplate.name,
|
|
args,
|
|
);
|
|
|
|
return {
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: {
|
|
type: 'text',
|
|
text: renderedPrompt,
|
|
},
|
|
},
|
|
],
|
|
};
|
|
},
|
|
);
|
|
}
|
|
}
|