AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Vobase

mcp-vobase-vobase · by vobase

The app framework built for AI coding agents. Own every line. Your AI already knows how to build on it.

No reviews yet
0 installs
23 views
0.0% view→install

Install

$ agentstack add mcp-vobase-vobase

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-vobase-vobase)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Vobase? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

English / 中文

vobase

The app framework built for AI coding agents. Own every line. Your AI already knows how to build on it.

what you get · get started · code · harness · compare · docs


A full-stack TypeScript framework that gives you auth, database, storage, jobs, and a first-class AI agent runtime in a single Bun process. Docker Compose Postgres for local dev, managed Postgres in production. Like a self-hosted Supabase — but you own every line of code. Like Pocketbase — but it's TypeScript you can read and modify.

AI coding agents (Claude Code, Cursor, Codex) understand vobase out of the box. Strict conventions and a uniform module shape mean generated code works on the first try — not the third.

You own the code. You own the data. You own the infrastructure.


what you get

One bun create vobase and you have a working full-stack app:

| Primitive | What it does | |---|---| | Runtime | Bun — native TypeScript, ~50ms startup, built-in test runner. One process, one container. | | Database | PostgreSQL via Drizzle. Docker Compose Postgres (pgvector/pg17) for local dev, managed Postgres in production. Full SQL, ACID transactions, pgvector for embeddings. | | Auth | better-auth. Sessions, passwords, email OTP, CSRF. RBAC with role guards, API keys, organizations. SSO/2FA as plugins. | | API | Hono — ~14KB, typed routing, Bun-first. Every AI coding tool already knows Hono. | | Audit | Built-in audit log, record change tracking, and auth event hooks. Every mutation is traceable. | | Sequences | Gap-free business number generation (INV-0001, PO-0042). Transaction-safe, never skips. | | Storage | File storage with virtual buckets. Local or S3/R2 backends. Metadata tracked in Postgres. | | Channels | Multi-channel messaging with pluggable adapters: WhatsApp (Cloud API), email (Resend, SMTP). Inbound webhooks, outbound sends, delivery tracking. All messages logged. | | Integrations | Encrypted credential vault for external services. AES-256-GCM at rest. Platform-aware: opt-in multi-tenant OAuth handoff via HMAC-signed JWT. | | Jobs | Background tasks with retries, cron, and job chains. pg-boss backed — Postgres only, no Redis. | | Realtime | Server-push via PostgreSQL LISTEN/NOTIFY + SSE. No WebSocket. Modules pg_notify after commit; the frontend hook invalidates matching TanStack Query keys. | | Agent harness | First-class AI agent runtime (pi-agent-core + pi-ai). Frozen system prompt per wake, byte-stable provider cache, tool budget spill, steer/abort between turns, journaled events, idle resumption, restart recovery. | | Workspace | Virtual filesystem materialized per-wake from your modules. AGENTS.md is composed from per-module fragments; agents read /staff//profile.md, /contacts//MEMORY.md, etc. RO enforcement at the FS boundary. | | CLI | @vobase/cli — standalone, catalog-driven binary. Modules register verbs via defineCliVerb; the same body runs in-process (agent bash sandbox) and over HTTP-RPC (vobase binary). | | Frontend | React + TanStack Router + shadcn/ui + ai-elements + DiceUI + Tailwind v4. Type-safe routing with codegen, code-splitting. You own the component source. | | MCP | Model Context Protocol server in the same process. AI tools can read your schema, list modules, and view logs before generating code. | | Deploy | Dockerfile + railway.json included. One railway up or docker build and you're live. |

Locally, docker compose up -d starts a pgvector/pg17 Postgres instance. bun run dev and you're building. In production, point DATABASE_URL at any managed Postgres.


quick start

bun create vobase my-app
cd my-app
docker compose up -d
bun run db:reset
bun run dev

Backend on :3001, frontend on :5173. Ships with the agent-native helpdesk template — messaging, channels, contacts, team, drive, agents — already wired up.


what you can build

Every module is a self-contained directory: schema, service, handlers, jobs, pages, and an agent.ts slot that publishes tools, materializers, RO hints, and AGENTS.md fragments to the harness. No plugins, no marketplace. Just TypeScript you own.

| Use Case | What Ships | |---|---| | Agent-native helpdesk | The default template. WhatsApp + email inbox, contact memory, staff-mention fan-out, supervisor coaching, scheduled follow-ups, approval gates, drive overlays. | | SaaS Starter | User accounts, billing integration, subscription management. Auth + jobs + webhooks handle the plumbing. | | Internal Tools | Admin panels, operations dashboards, approval workflows. Status machines enforce business logic. Audit trails track every change. | | CRM & Contacts | Companies, contacts, interaction timelines, deal tracking. Cross-module references via service imports — no FK across module boundaries. | | Project Tracker | Tasks, assignments, status workflows, notifications. Background jobs handle reminders and escalations. | | Billing & Invoicing | Invoices, line items, payments, aging reports. Integer money ensures exact arithmetic. Gap-free numbering via transactions. | | Your Vertical | Property management, fleet tracking, field services — whatever the business needs. Describe it to your AI tool. It generates the module. |

AI coding agents generate modules from your conventions. Like npx shadcn add button — files get copied, you own the code.


how it works

Vobase makes itself legible to every AI coding tool on the market.

The framework ships with one canonical module shape, one write-path discipline, and a harness that AI agents drive at runtime. When you need a new capability:

  1. Open your AI tool and describe the requirement
  2. The AI reads your existing schema, the canonical module shape, and the relevant .claude/skills/ packs
  3. It generates a complete module — schema, service, handlers, jobs, pages, agent slot, tests, seed data
  4. You review the diff, run bun run dev, and it works

Skill packs cover the parts where apps get tricky: money stored as integer cents (never floats), status transitions as explicit state machines (not arbitrary string updates), gap-free business numbers generated inside database transactions, single-write-path enforcement via check:shape, frontend bundle isolation via check:bundle.

These conventions are what make AI-generated modules work on the first try.

The thesis: your specs and domain knowledge are the asset. AI tools are the compiler. The compiler improves every quarter. Your skills compound forever.


what a module looks like

Every module is a thin aggregator over sibling files. module.ts declares the contract; everything else lives next to the code that owns the side-effect.

// modules/projects/module.ts
import type { ModuleDef } from '~/runtime'
import { projectsAgent } from './agent'
import { projectListVerb } from './verbs/project-list'
import { createProjectsService, installProjectsService } from './service/projects'
import * as web from './web'

const projects: ModuleDef = {
  name: 'projects',
  requires: ['team'],
  web: { routes: web.routes },
  jobs: [],
  agent: projectsAgent,
  init(ctx) {
    installProjectsService(createProjectsService({ db: ctx.db }))
    ctx.cli.registerAll([projectListVerb])
  },
}

export default projects
modules/projects/
  module.ts            ← thin aggregator (above)
  schema.ts            ← Drizzle table definitions
  state.ts             ← status transitions, state machine
  service/             ← transactional write-path (sole writer of this module's tables)
  handlers/            ← Hono routes (HTTP API)
  web.ts               ← route barrel mounted under /api/projects
  pages/               ← React pages — list, detail, create
  components/          ← React components owned by this module
  hooks/               ← TanStack Query hooks
  jobs.ts              ← pg-boss handlers
  agent.ts             ← agent slot: tools, materializers, roHints, AGENTS.md fragments
  tools/               ← defineAgentTool — colocated with the service
  verbs/               ← defineCliVerb — runs in agent bash and the CLI binary
  cli.ts               ← barrel exporting Verbs
  seed.ts              ← demo data
  defaults/            ← *.agent.yaml, *.schedule.yaml — opt-in starter content
  skills/              ← inline skill bodies the agent reads via drive overlay
  *.test.ts            ← colocated bun test

schema example — Drizzle + PostgreSQL with typed columns, timestamps, status enums

// modules/projects/schema.ts
import { pgTable, text, integer, timestamp, check } from 'drizzle-orm/pg-core'
import { sql } from 'drizzle-orm'
import { nanoidPrimaryKey } from '@vobase/core'

export const projects = pgTable('projects', {
  id: nanoidPrimaryKey(),
  name: text('name').notNull(),
  description: text('description'),
  status: text('status').notNull().default('active'),
  ownerId: text('owner_id').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
}, (t) => [
  check('projects_status_chk', sql`${t.status} in ('active','archived','deleted')`),
])

export const tasks = pgTable('tasks', {
  id: nanoidPrimaryKey(),
  projectId: text('project_id').references(() => projects.id),
  title: text('title').notNull(),
  status: text('status').notNull().default('todo'),
  assigneeId: text('assignee_id'),
  priority: integer('priority').notNull().default(0),
}, (t) => [
  check('tasks_status_chk', sql`${t.status} in ('todo','in_progress','done')`),
])

check:shape enforces that only service/projects.ts writes to projects — handlers and jobs go through the service.

handler example — Hono routes with Zod validation, typed RPC client

// modules/projects/handlers/list.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import { getCtx } from '~/runtime'
import { projectsService } from '../service/projects'

export const listRoute = new Hono().get(
  '/',
  zValidator('query', z.object({ status: z.enum(['active','archived']).optional() })),
  async (c) => {
    const ctx = getCtx(c)
    const { status } = c.req.valid('query')
    const items = await projectsService().list({ ownerId: ctx.user.id, status })
    return c.json(items)
  },
)

The frontend gets fully typed API calls via the Hono RPC client (src/lib/api-client.ts):

import { useQuery } from '@tanstack/react-query'
import { api } from '@/lib/api-client'

export function useProjects() {
  return useQuery({
    queryKey: ['projects'],
    queryFn: async () => {
      const res = await api.projects.$get({ query: {} })
      return await res.json() // fully typed
    },
  })
}

use-realtime-invalidation.ts maps pg_notify table payloads onto the first element of TanStack queryKey — services emit notifies after commit and the UI re-fetches automatically.

job example — background tasks via pg-boss, no Redis

// modules/projects/jobs.ts
import { defineJob } from '@vobase/core'
import { projectsService } from './service/projects'

export const sendReminder = defineJob('projects:send-reminder',
  async (data: { taskId: string }) => {
    await projectsService().notifyAssignee(data.taskId)
  },
)

Schedule from handlers or services: ctx.scheduler.add('projects:send-reminder', { taskId }, { delay: '1d' }). Retries, cron scheduling, and priority queues — all Postgres-backed via pg-boss.

agent slot example — tools, materializers, AGENTS.md fragments

// modules/projects/agent.ts
import { defineAgentTool, defineIndexContributor } from '@vobase/core'
import { projectsService } from './service/projects'

const createTask = defineAgentTool({
  name: 'create_task',
  audience: 'internal',
  lane: 'standalone',
  // schema: zod input/output…
  async handler({ input, ctx }) {
    return await projectsService().createTask(input)
  },
})

export const projectsAgent = {
  agentsMd: [defineIndexContributor({
    file: 'AGENTS.md',
    priority: 50,
    name: 'projects.overview',
    render: () => '## Projects\n\n- `create_task` to add a task to a project.',
  })],
  materializers: [/* WorkspaceMaterializerFactory[] */],
  roHints: [/* explain why /projects//* paths are read-only */],
  tools: [createTask],
}

The wake builder filters tools by lane and audience, runs each materializer factory against the wake context, chains roHints, and feeds the AGENTS.md contributors into the harness. One agent slot per module — no central registry to update.


the ctx object

Every HTTP handler gets a context object with runtime capabilities. Current surface:

| Property | What it does | |---|---| | ctx.db | Drizzle instance. Full PostgreSQL — reads, writes, transactions. | | ctx.user | { id, email, name, role, activeOrganizationId? }. From better-auth session. RBAC middlewares: requireRole(), requirePermission(), requireOrg(). | | ctx.scheduler | Job queue. add(jobName, data, options) to schedule background work. | | ctx.storage | StorageService — virtual buckets with local/S3/R2 backends. | | ctx.channels | ChannelsService — email and WhatsApp sends. All messages logged. | | ctx.integrations | Encrypted credential vault. ctx.integrations.getActive(provider) returns decrypted config or null. | | ctx.http | Typed HTTP client with retries, timeouts, and circuit breakers. | | ctx.realtime | RealtimeServicenotify({ table, id?, action? }, tx?) after mutations. SSE subscribers receive the event; the frontend hook invalidates matching TanStack queries. |

Modules can declare an init(ctx: ModuleInitCtx) hook that runs at boot with { db, realtime, jobs, scheduler, auth, cli }. Cross-module callers import from @modules//service/* directly — no port shim, no plugin system. Unconfigured services use throw-proxies that produce descriptive errors if accessed.

App-level config:

// vobase.config.ts
export default defineConfig({
  database: process.env.DATABASE_URL,
  integrations: { enabled: true },      // opt-in: encrypted credential store
  storage: {                            // opt-in: file storage
    provider: { type: 'local', basePath: './data/files' },
    buckets: { avatars: { maxSize: 5_000_000 }, documents: {} },
  },
  channels: {                           // opt-in: email + WhatsApp
    email: { provider: 'resend', from: 'noreply@example.com', resend: { apiKey: '...' } },
  },
  http: {
    timeout: 10_000,
    retries: 3,
    circuitBreaker: { threshold: 5, resetTimeout: 30_000 },
  },
  webhooks: {
    'stripe-events': {
      path: '/webhooks/stripe',
      secret: process.env.STRIPE_WEBHOOK_SECRET,
      handler: 'system:processWebhook',
      signatureHeader: 'stripe-signature',
      dedup: true,
    },
  },
})

Credentials stay in .env. Config declares the shape.


agent harness

The harness is the AI runtime in core. It runs on top of @mariozechner/pi-agent-core + @mariozechner/pi-ai and ships as createHarness({...}) from @vobase/core. Each "wake" is one bounded run of an agent over a frozen system prompt.

Lanes — the template ships two:

  • Conversation — bound to (contactId, channelInstanceId, conversationId). Triggered by inbound_message, supervisor, approval_resumed, scheduled_followup, manual.
  • Standalone — operator threads + heartbeats. Triggered by operator_thread, heartbeat. Customer-facing tools are filtered out.

Invariants baked into core:

  • Frozen snapshot. System prompt computed once at agent_start; the systemHash is identical every turn so the provider's prefix cache stays warm. Mid-wake writes surface in the next turn's side-load.
  • Steer/abort between turns. Customer messages append to

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.