人员CRUD应用

一个基于Next.js 15和MCP服务器的生产级人员管理应用,支持完整的CRUD操作、OAuth 2.0认证和实时搜索功能。

  • by barbiefortes04-jpg
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 barbiefortes04-jpg/mcp-person-crud-app

使用说明

MCP人员CRUD应用程序-Next.js 15+MCP服务器集成

描述

MCP Person CRUD应用程序是一个生产就绪的Next.js应用程序,演示 模型上下文协议(MCP)集成 具有完整的CRUD操作。内置于 Next.js 15.5 和 反应19,此应用程序展示了使用MCP服务器的高级AI代理架构,使Claude Desktop能够通过自然语言命令执行数据库操作。

生产URL: https://mcp-person-crud-app.vercel.app
GitHub存储库: https://github.com/barbiefortes04-jpg/mcp-person-crud-app

特性

  • OAuth 2.0身份验证 使用谷歌(Auth.js v5)
  • 受保护的路线 基于中间件的授权
  • 数据库支持的CRUD 使用Prisma ORM进行操作
  • 异步搜索 实时过滤功能
  • 会话管理 使用用户菜单并注销
  • 综合文档 页面(/auth设置、/security、/github、/database)
  • 响应式设计 使用Tailwind CSS和shadcn/ui
  • 以无障碍为重点 Radix UI中的UI组件
  • 无服务器就绪 使用Neon PostgreSQL
  • 安全的凭证存储 有环境变量
  • 边缘运行时兼容 中间件
  • 类型安全 带有Zod验证的表单
  • 模型上下文协议(MCP) 服务器集成
  • 样本数据种子 有10条预加载的人员记录

使用的技术

前端

  • Next.js 15.5.6 -带有App Router和服务器组件的React框架
  • 反应19 -具有并发渲染改进的最新React版本
  • TypeScript 5 -JavaScript的强类型超集
  • 顺风 CSS -实用程序优先的CSS框架
  • shadcn/ui -基于Radix UI构建的漂亮UI组件
  • React钩子形式 -性能和灵活的表单库
  • 黄道 -TypeScript第一个模式声明和验证库

后端和身份验证

  • Auth.js(NextAuth v5) -使用Google OAuth 2.0对Next.js进行现代身份验证
  • Prisma ORM 6.19.0 -类型安全数据库客户端
  • PostgreSQL -强大的关系数据库(Neon无服务器)
  • @auth/prisma适配器 -Auth.js会话的数据库适配器

基础设施

  • Node.js 20.17.0 -需要与Next.js 15.5兼容
  • Neon PostgreSQL -带连接池的无服务器PostgreSQL
  • 维塞尔 -针对Next.js优化的部署平台

入门指南

先决条件

  • Node.js 20.17.0或更新版本
  • npm或pnpm
  • 谷歌云控制台帐户(用于OAuth)
  • Neon数据库帐户(用于PostgreSQL)

地方发展设置

  1. 克隆存储库:

    git clone https://github.com/barbiefortes04-jpg/person-search-next.git
    cd person-search-next
    
  2. 安装依赖项:

    npm install
    # or
    pnpm install
    
  3. 设置环境变量:

    创建一个 .env.local 根目录中的文件:

    # Database (Neon PostgreSQL)
    DATABASE_URL="postgresql://username:password@host/database?sslmode=require"
    
    # Auth.js
    NEXTAUTH_SECRET="your-secret-from-npx-auth-secret"
    NEXTAUTH_URL="http://localhost:3000"
    
    # Google OAuth (from Google Cloud Console)
    GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
    GOOGLE_CLIENT_SECRET="your-client-secret"
    
  4. 设置数据库:

    npx prisma db push
    npx tsx prisma/seed.ts
    
  5. 配置Google OAuth:

    • 首选 谷歌云控制台
    • 创建OAuth 2.0凭据
    • 添加授权重定向URI: http://localhost:3000/api/auth/callback/google

运行开发服务器

npm run dev
# or
pnpm dev

打开 http://localhost:3000 -您将被重定向到使用Google登录。

部署到Vercel

自动部署(推荐)

  1. 将代码推送到GitHub
  2. 将您的存储库连接到Vercel
  3. 在Vercel仪表板中配置环境变量
  4. 自动部署

手动部署

  1. 安装Vercel CLI:

    npm i -g vercel
    
  2. 登录并部署:

    vercel login
    vercel --prod
    

生产所需的环境变量

在Vercel仪表板中,添加以下环境变量:

DATABASE_URL=your-neon-postgresql-connection-string
NEXTAUTH_SECRET=your-production-secret
NEXTAUTH_URL=https://your-vercel-domain.vercel.app
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

重要提示: 更新您的Google OAuth重定向URI以包含您的生产域:

  • 添加: https://your-vercel-domain.vercel.app/api/auth/callback/google

数据库设置

此应用程序使用Neon PostgreSQL进行生产和开发。数据库包括:

  • 人员表:存储具有id、姓名、电子邮件、电话号码、createdAt、updatedAt的人员记录
  • Auth.js表:用于身份验证的用户、帐户、会话和VerificationToken表
  • 样品数据:10份用于测试的预装人员记录

数据库模式

-- Person table for CRUD operations
CREATE TABLE "Person" (
  "id" TEXT NOT NULL PRIMARY KEY,
  "name" TEXT NOT NULL,
  "email" TEXT NOT NULL,
  "phoneNumber" TEXT NOT NULL,
  "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "updatedAt" TIMESTAMP(3) NOT NULL
);

-- Auth.js tables (generated automatically)
-- User, Account, Session, VerificationToken

它是如何工作的(Next.js 15.1和React 19)

关键变化 UserSearch 组件

  1. 服务器组件设计:

    • 这 user-search 组件现在是 服务器组件,利用 searchParams 并在服务器端获取用户详细信息。
    • searchParams 在Next.js 15.1中是异步的,因此 user-search 组件在渲染之前解析它们。
    export default async function UserSearch({ searchParams }: { searchParams: Promise<{ userId?: string }> }) {
      const resolvedSearchParams = await searchParams;
      const selectedUserId = resolvedSearchParams?.userId || null;
      const user = selectedUserId ? await getUserById(selectedUserId) : null;
    
      return (
        <div className="space-y-6">
          <SearchInput />
          {selectedUserId && (
            <Suspense fallback={<p>Loading user...</p>}>
              {user ? <UserCard user={user} /> : <p>User not found</p>}
            </Suspense>
          )}
        </div>
      );
    }
    
  2. 改进的性能:

    • 数据提取已经过优化,以避免冗余调用。用户对象在 user-search 并作为道具传递给子组件,如 UserCard 和 DeleteButton.
    • 这消除了多次获取,提高了性能并减少了服务器负载。
  3. 与...互动 SearchInput:

    • SearchInput 仍然是a 客户端组件,负责通过以下方式与用户交互 react-selects AsyncSelect.
    • 当用户被选中时,URL会使用用户的ID进行更新 window.history.pushState。这会触发重新渲染 user-search 以反映更新的状态。
  4. 改进了错误处理:

    • 通过使用React Hook Form和Zod确保表单中的一致处理,验证和受控/不受控输入警告得到了解决。
  5. 并发和水合:

    • React 19的并发渲染和Next.js 15.1对服务器组件的支持确保了无缝的服务器-客户端水合,减少了潜在的不匹配。

已知问题

  1. 祝酒词:

    • 通知中 DeleteButton 和 MutableDialog 目前没有显示。这需要调试集成 Sonner 吐司图书馆。
  2. 主题支持:

    • 这 theme-provider 用于管理暗模式和亮模式的功能已被暂时删除。Tailwind样式表需要更新,以与新的Next.js配置保持一致。
  3. 水合警告:

    • 由于Grammarly等外部浏览器扩展或运行时环境的差异,可能会出现一些水合警告。已添加抑制标志,但建议进行进一步测试。

更新项目结构

person-search/
├── app/
│   ├── components/
│   │   ├── user-search.tsx
│   │   ├── search-input.tsx
│   │   ├── user-card.tsx
│   │   ├── user-dialog.tsx
│   │   └── user-form.tsx
│   ├── actions/
│   │   ├── actions.ts
│   │   └── schemas.ts
│   └── page.tsx
├── public/
├── .eslintrc.json
├── next.config.js
├── package.json
├── README.md
├── tailwind.config.ts
└── tsconfig.json

使用 MutableDialog

这 MutableDialog 组件是一个可重用的对话框框架,可用于“添加”和“编辑”操作。它将表单验证与Zod和React Hook form集成在一起,并支持为编辑操作传递默认值。

如何 MutableDialog 作品

MutableDialog 接受以下道具:

  • formSchema:定义表单验证规则的Zod模式。
  • FormComponent:一个负责呈现表单字段的React组件。
  • action:处理表单提交的功能(例如,添加或更新用户)。
  • defaultValues:表单字段的初始值,用于编辑现有数据。
  • triggerButtonLabel:触发对话框的按钮的标签。
  • addDialogTitle / editDialogTitle:“添加”和“编辑”模式的标题。
  • dialogDescription:对话框内显示的描述。
  • submitButtonLabel:提交按钮的标签。

示例:添加操作

使用 MutableDialog 用于添加新用户:

import { MutableDialog } from './components/mutable-dialog';
import { userFormSchema, UserFormData } from './actions/schemas';
import { addUser } from './actions/actions';
import { UserForm } from './components/user-form';

export function UserAddDialog() {
  const handleAddUser = async (data: UserFormData) => {
    try {
      const newUser = await addUser(data);
      return {
        success: true,
        message: `User ${newUser.name} added successfully`,
        data: newUser,
      };
    } catch (error) {
      return {
        success: false,
        message: `Failed to add user: ${error instanceof Error ? error.message : 'Unknown error'}`,
      };
    }
  };

  return (
    <MutableDialog<UserFormData>
      formSchema={userFormSchema}
      FormComponent={UserForm}
      action={handleAddUser}
      triggerButtonLabel="Add User"
      addDialogTitle="Add New User"
      dialogDescription="Fill out the form below to add a new user."
      submitButtonLabel="Save"
    />
  );
}

示例:编辑操作

使用 MutableDialog 用于编辑现有用户:

import { MutableDialog } from './components/mutable-dialog';
import { userFormSchema, UserFormData } from './actions/schemas';
import { updateUser } from './actions/actions';
import { UserForm } from './components/user-form';

export function UserEditDialog({ user }: { user: UserFormData }) {
  const handleUpdateUser = async (data: UserFormData) => {
    try {
      const updatedUser = await updateUser(user.id, data);
      return {
        success: true,
        message: `User ${updatedUser.name} updated successfully`,
        data: updatedUser,
      };
    } catch (error) {
      return {
        success: false,
        message: `Failed to update user: ${error instanceof Error ? error.message : 'Unknown error'}`,
      };
    }
  };

  return (
    <MutableDialog<UserFormData>
      formSchema={userFormSchema}
      FormComponent={UserForm}
      action={handleUpdateUser}
      defaultValues={user} // Pre-fill form fields with user data
      triggerButtonLabel="Edit User"
      editDialogTitle="Edit User Details"
      dialogDescription="Modify the details below and click save to update the user."
      submitButtonLabel="Update"
    />
## Credits

**Original Project:** [Callum Bir's Person Search](https://github.com/gocallum/person-search)  
**Enhanced Version:** [barbiefortes04-jpg](https://github.com/barbiefortes04-jpg) - ECA Tech Bootcamp Project  
**Repository:** [https://github.com/barbiefortes04-jpg/person-search-next](https://github.com/barbiefortes04-jpg/person-search-next)

### Key Enhancements
- Added Google OAuth 2.0 authentication with Auth.js v5
- Implemented Prisma ORM with PostgreSQL database (Neon)
- Created protected routes with Edge Runtime middleware
- Added comprehensive security and setup documentation
- Converted from mock data to database-backed CRUD operations
- Integrated Model Context Protocol (MCP) server
- Added sample data seeding and production deployment guides

### ECA Tech Bootcamp Curriculum
This enhanced version was developed as part of the ECA Tech Bootcamp curriculum provided by [AusBiz Consulting](https://ausbizconsulting.com.au). The project demonstrates full-stack Next.js development with modern authentication, database integration, and production deployment practices.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is open source and available under the [MIT License](LICENSE).

## Contact

**Enhanced by:** [barbiefortes04-jpg](https://github.com/barbiefortes04-jpg)  
**Original by:** Callum Bir - [@callumbir](https://twitter.com/callumbir)  
**Project Link:** [https://github.com/barbiefortes04-jpg/person-search-next](https://github.com/barbiefortes04-jpg/person-search-next)

## Contributing

Contributions are welcome! Please submit a Pull Request with your changes.

## License

This project is open source and available under the [MIT License](LICENSE).

## Acknowledgments

- Next.js team for the framework
- Radix UI for accessible components
- All contributors of the open-source libraries used in this project

## Contact

Callum Bir - [@callumbir](https://twitter.com/callumbir)  
Project Link: [https://github.com/gocallum/person-search](https://github.com/gocallum/person-search)