Mandu Create API

SkillDev tools

REST API creation. CRUD/auth/upload endpoints. Automatically triggered on 'API', 'endpoint', 'CRUD'

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Mandu Create API skill

What this skill tells your AI

The instructions your AI receives, as published by konamgil/mandu in docs/archive/skills/package-v0/mandu-create-api/SKILL.md and read by ahel’s review.

REST API 엔드포인트를 생성하는 워크플로우. Route + Contract + Slot + Test 파이프라인으로 완전한 API를 스캐폴딩합니다.

Workflow: Route -> Contract -> Slot -> Test

Step 1: Route 생성

// app/api/posts/route.ts
import { Mandu } from "@mandujs/core";

export default Mandu.filling()
  .get((ctx) => ctx.ok({ posts: [] }))
  .post(async (ctx) => {
    const body = await ctx.body<CreatePostInput>();
    return ctx.created({ post: body });
  });

Step 2: Contract 정의

// src/shared/contracts/post.contract.ts
import { z } from "zod";

export const CreatePostInput = z.object({
  title: z.string().min(1).max(200),
  content: z.string().min(1),
  tags: z.array(z.string()).optional(),
});

export const PostResponse = z.object({
  id: z.string(),
  title: z.string(),
  content: z.string(),
  createdAt: z.string().datetime(),
});

export type CreatePostInput = z.infer<typeof CreatePostInput>;
export type PostResponse = z.infer<typeof PostResponse>;

Step 3: Slot (서버 데이터 로더)

// spec/slots/posts.slot.ts
import { Mandu } from "@mandujs/core";
import { CreatePostInput } from "@/shared/contracts/post.contract";

export default Mandu.filling()
  .guard(async (ctx) => {
    const token = ctx.headers.get("authorization");
    if (!token) return ctx.error(401, "Unauthorized");
    ctx.set("userId", await verifyToken(token));
  })
  .post(async (ctx) => {
    const body = await ctx.body<CreatePostInput>();
    const validated = CreatePostInput.parse(body);
    const post = await db.posts.create({ ...validated, userId: ctx.get("userId") });
    return ctx.created({ post });
  });

Step 4: Test 작성

// tests/api/posts.test.ts
import { describe, test, expect } from "bun:test";

describe("POST /api/posts", () => {
  test("creates a post with valid input", async () => {
    const res = await fetch("http://localhost:3333/api/posts", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer test-token",
      },
      body: JSON.stringify({ title: "Test", content: "Hello" }),
    });
    expect(res.status).toBe(201);
    const data = await res.json();
    expect(data.post.title).toBe("Test");
  });

  test("returns 401 without auth", async () => {
    const res = await fetch("http://localhost:3333/api/posts", {
      method: "POST",
      body: JSON.stringify({ title: "Test", content: "Hello" }),
    });
    expect(res.status).toBe(401);
  });
});

CRUD Pattern

app/api/{resource}/route.ts          GET (list), POST (create)
app/api/{resource}/[id]/route.ts     GET (read), PATCH (update), DELETE (remove)
src/shared/contracts/{resource}.contract.ts
spec/slots/{resource}.slot.ts
tests/api/{resource}.test.ts

MCP Tools

ToolPurpose
mandu_add_routeCreate route file at correct path
mandu_create_contractGenerate Zod contract schema
mandu_negotiateAnalyze API requirements
mandu_generateFull scaffold generation

Auth Patterns

// Bearer token guard
.guard(async (ctx) => {
  const token = ctx.headers.get("authorization")?.replace("Bearer ", "");
  if (!token) return ctx.error(401, "Missing token");
  ctx.set("user", await verifyToken(token));
})

// API key guard
.guard((ctx) => {
  const key = ctx.headers.get("x-api-key");
  if (key !== process.env.API_KEY) return ctx.error(403, "Invalid API key");
})

Key Rules

  1. 모든 API route는 Mandu.filling() 체인으로 export
  2. 반드시 Contract를 먼저 정의하고 validation에 사용
  3. .guard()로 인증/인가 처리 (인라인 체크 금지)
  4. 에러는 ctx.error(status, message) 사용
  5. ctx.body()는 반드시 await

See also

  • mandu-mcp-create-flow — Track C (single route) 레시피로 이 워크플로우를 MCP 도구 순서로 정리
  • mandu-mcp-verify — API 추가 직후 ate.auto_pipeline + guard_check 병렬 검증

Signals

GitHub stars
46
Forks
3
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
mandu-create-api
Source
github.com/konamgil/mandu