Skip to Content

Make your Next.js app agent-ready.

Universal procedures: one definition is an endpoint, a server call, an MCP tool and a typed client.

  • Node.js24.15+
  • Bun1.4+
  • Deno2.9+

Each endpoint becomes an MCP tool for AI agents, and a typed, documented API for everyone else.

npx skills add finom/vovk
then ask your agent to build your API

Demo: the createTask procedure. Each field you add or rename, and the description, appears at once in the endpoint, the agent's MCP tool call, the TypeScript RPC library and server actions, the Python and Rust types, the OpenAPI request body and the README.

Try it: edit a field or the description.

src/modules/tasks/TaskController.ts
@operation({ description: '' })
@post()
static createTask = procedure({
body: z.object({
: z.string(),
: z.boolean(),
: z.enum(['low', 'high']),
: z.iso.date(),
: z.int(),
}),
}).handle(async (req) =>
TaskService.createTask(
await req.vovk.body()));
vovk devon every save
  • Endpoint
    curl -X POST /api/tasks -d '{"title":"Ship it",​"done":false}'
  • MCP tool
    agent: "Create a task called Ship it"
    → TaskRPC_createTask({ body: { title: "Ship it", done: false } })
  • RPC librarynpm
    TaskRPC.createTask({ body: { title: string; done: boolean } })
  • Server actions
    TaskController.createTask.fn({ body: { title: string; done: boolean } })
  • Python clientPyPI
    class CreateTaskBody(TypedDict):
    title: str; done: bool
  • Rust clientcrates.io
    struct body { title: String, done: bool }
  • OpenAPI 3.1
    description: Create a task
    requestBody: { title: string, done: boolean }
  • README
    ### TaskRPC.createTask
    > Create a task
    POST /api/tasks

One endpoint, every caller

AI agents

GuideTools

Each procedure is an AI tool with execute() and a JSON Schema input, for MCP, AI SDKs or your own agent loop.

const tools = deriveTools({
modules: { TaskRPC },
});

Typed clients

TypeScriptPythonRust

Generated from your procedures as TypeScript, Python and Rust packages, ready to publish.

tsTaskRPC.createTask({ body })
pyTaskRPC.create_task(body=body)
rstask_rpc::create_task(body, (),
(), None, None, false).await?

OpenAPI docs

DocsExample

The OpenAPI spec and a docs page come from the same code, so they match what runs.

/api/tasks:
post:
description: Create a task
x-codeSamples: [ts, python, rust]

Streaming

Docs

An async generator sends JSON Lines, and the client reads them with types.

.handle(async function* () {
yield { token: 'Hello' };
})
for await (const item of stream)

Multitenancy

Docs

multitenant() in the Next.js proxy sends each subdomain to its own pages and API segment.

admin.example.com
→ admin segment
customer.example.com
→ customer segment

Plain Next.js

Docs

It runs in route handlers on Node.js, Bun or Deno, with no custom server, and deploys wherever Next.js does.

// app/api/[[...vovk]]/route.ts
export const { GET, POST } =
initSegment({ controllers });

Build it with your agent

Add the Vovk.ts skills to Claude Code, Cursor, Windsurf, GitHub Copilot or Cline, then ask for the API you need.

npx skills add finom/vovk
or start a new project:
npx vovk-cli@latest init

Examples