Bkend Data logo

Bkend Data

Organization
ww-w-ai
bkend-data

bkend.ai database expert skill. Covers table creation, CRUD operations, 7 column types, constraints, filtering (AND/OR, 10 operators), sorting, pagination, relations, joins, indexing, and schema management via MCP and REST API. Triggers: table, column, CRUD, schema, index, filter, query, data model, 테이블, 컬럼, 스키마, 인덱스, 필터, 쿼리, 데이터 모델, テーブル, カラム, スキーマ, インデックス, フィルター, 数据表, 列, 模式, 索引, 过滤, 查询, tabla, columna, esquema, indice, filtro, consulta, tableau, colonne, schema, index, filtre, requete, Tabelle, Spalte, Schema, Index, Filter, Abfrage, tabella, colonna, schema, indice, filtro, query Do NOT use for: authentication (use bkend-auth), file storage (use bkend-storage), MCP setup (use bkend-mcp), security policies (use bkend-security)

Overview

Publisherww-w-ai
Repositorybkit-gemini
Skill namebkend-data
Stars
66
Forks
16
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by ww-w-ai on GitHub. Read the source before you install it.

Installation

Install the Bkend Data AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ww-w-ai/bkit-gemini.git /tmp/bkit-gemini
mkdir -p .claude/skills
cp -r /tmp/bkit-gemini/skills/bkend-data .claude/skills/bkend-data
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Bkend Data in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Bkend Data on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Bkend Data is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

bkend-data: Database Expert Skill

Complete database management for bkend.ai projects using MongoDB Atlas

1. Overview

bkend.ai provides a fully managed database layer built on MongoDB Atlas. Each project operates in complete data isolation, with built-in schema validation and Row-Level Security (RLS) policies.

Key characteristics:

  • MongoDB Atlas backend with project-level isolation
  • Schema validation enforced at the database level
  • Row-Level Security (RLS) for fine-grained access control
  • Automatic system fields on every record
  • REST API and MCP tools for full database management

2. Data Model

2.1 Column Types (7 Types)

bkend.ai supports exactly 7 column types. There is no generic "number" type.

TypeDescriptionExample
stringText data, UTF-8 encoded"Hello World"
intInteger numbers (no decimals)42
doubleFloating-point numbers3.14
boolBoolean true/falsetrue
dateISO 8601 date-time string"2025-01-15T09:30:00Z"
objectNested JSON object{ "city": "Seoul", "zip": "06000" }
arrayArray of values["tag1", "tag2", "tag3"]

IMPORTANT: Do NOT use "number" as a column type. Use int for integers or double for decimals.

2.2 System Fields (Auto-Generated)

Every record automatically includes these system fields. Do NOT define them manually.

FieldTypeDescription
idstringUnique record identifier (auto-generated)
createdBystringUser ID of the creator (auto-set)
createdAtdateCreation timestamp (auto-set)
updatedAtdateLast update timestamp (auto-set)

2.3 Constraints

Apply constraints to columns for data integrity:

ConstraintDescriptionExample
requiredField must have a valuerequired: true
uniqueValue must be unique across all recordsunique: true
defaultDefault value when not provideddefault: "active"
minMinimum value (int/double) or length (string)min: 0
maxMaximum value (int/double) or length (string)max: 100
enumRestrict to a set of allowed valuesenum: ["active", "inactive", "pending"]

2.4 Default Indexes

Every table is created with these indexes by default:

Index NameFieldsPurpose
_id_idPrimary key lookup
idx_createdAt_desccreatedAt descendingSort by creation date
idx_updatedAt_descupdatedAt descendingSort by update date
idx_createdBycreatedByFilter by owner

3. CRUD REST API

All data endpoints require authentication via the Authorization: Bearer <token> header and the x-project-id header.

3.1 Create Record

Single record:

http
POST /v1/data/:tableName
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30,
  "role": "user"
}

Batch create (multiple records):

http
POST /v1/data/:tableName
Content-Type: application/json

{
  "records": [
    { "name": "Alice", "email": "alice@example.com", "age": 25 },
    { "name": "Bob", "email": "bob@example.com", "age": 28 }
  ]
}

Response:

json
{
  "success": true,
  "data": {
    "id": "rec_abc123",
    "name": "John Doe",
    "email": "john@example.com",
    "age": 30,
    "role": "user",
    "createdBy": "usr_xyz",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  }
}

3.2 Read One Record

http
GET /v1/data/:tableName/:id

Response:

json
{
  "success": true,
  "data": {
    "id": "rec_abc123",
    "name": "John Doe",
    "email": "john@example.com",
    "age": 30,
    "role": "user",
    "createdBy": "usr_xyz",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  }
}

3.3 List Records

http
GET /v1/data/:tableName?filter={...}&sort={...}&limit=20&cursor=last_id&search=keyword&searchType=partial

Query Parameters:

ParameterTypeDescription
filterJSONFilter conditions (see Section 4)
sortJSONSort order (see Section 5)
limitintNumber of records to return (max 100, default 20)
cursorstringCursor for pagination (last record ID)
searchstringFull-text or partial search keyword
searchTypestringSearch mode: "exact" or "partial"

Response:

json
{
  "success": true,
  "data": [
    { "id": "rec_abc123", "name": "John Doe", "age": 30 },
    { "id": "rec_def456", "name": "Jane Smith", "age": 25 }
  ],
  "meta": {
    "total": 150,
    "limit": 20,
    "nextCursor": "rec_def456"
  }
}

3.4 Update Record

http
PUT /v1/data/:tableName/:id
Content-Type: application/json

{
  "name": "John Updated",
  "age": 31
}

Response:

json
{
  "success": true,
  "data": {
    "id": "rec_abc123",
    "name": "John Updated",
    "age": 31,
    "updatedAt": "2025-01-16T10:00:00Z"
  }
}

3.5 Delete Record

http
DELETE /v1/data/:tableName/:id

Response:

json
{
  "success": true,
  "data": {
    "id": "rec_abc123",
    "deleted": true
  }
}

3.6 Table Specification

Retrieve the full schema definition for a table:

http
GET /v1/data/:tableName/spec

Response:

json
{
  "success": true,
  "data": {
    "tableName": "users",
    "fields": [
      { "name": "name", "type": "string", "required": true },
      { "name": "email", "type": "string", "required": true, "unique": true },
      { "name": "age", "type": "int", "min": 0, "max": 150 },
      { "name": "role", "type": "string", "enum": ["user", "admin"], "default": "user" }
    ],
    "indexes": [
      { "name": "_id_", "fields": ["id"] },
      { "name": "idx_createdAt_desc", "fields": [{ "createdAt": -1 }] }
    ]
  }
}

4. Filtering

4.1 AND Filtering (Default)

Multiple conditions in the same filter object are combined with AND logic:

json
{
  "filter": {
    "status": { "$eq": "active" },
    "age": { "$gte": 18 }
  }
}

This returns records where status equals "active" AND age is greater than or equal to 18.

4.2 OR Filtering

Use the $or operator to combine conditions with OR logic:

json
{
  "filter": {
    "$or": [
      { "status": "active" },
      { "role": "admin" }
    ]
  }
}

This returns records where status equals "active" OR role equals "admin".

4.3 Filter Operators (10 Operators)

OperatorDescriptionExample
$eqEqual to{ "status": { "$eq": "active" } }
$neNot equal to{ "status": { "$ne": "deleted" } }
$gtGreater than{ "age": { "$gt": 18 } }
$gteGreater than or equal{ "age": { "$gte": 18 } }
$ltLess than{ "price": { "$lt": 100 } }
$lteLess than or equal{ "price": { "$lte": 99.99 } }
$inIn array of values{ "role": { "$in": ["admin", "editor"] } }
$ninNot in array{ "status": { "$nin": ["deleted", "banned"] } }
$regexRegular expression match{ "name": { "$regex": "^John" } }
$existsField exists or not{ "profileImage": { "$exists": true } }

4.4 Search

Use query parameters for text search:

GET /v1/data/users?search=john&searchType=partial
  • search: The keyword to search for
  • searchType: "exact" for exact match, "partial" for contains match

5. Sorting & Pagination

5.1 Sorting

Specify sort order with field name and direction (1 for ascending, -1 for descending):

json
{
  "sort": { "createdAt": -1 }
}

Multiple sort fields:

json
{
  "sort": { "role": 1, "createdAt": -1 }
}

5.2 Pagination

bkend.ai uses cursor-based pagination for optimal performance:

GET /v1/data/users?limit=20&cursor=rec_last_id_value
  • limit: Number of records per page (max 100, default 20)
  • cursor: The id of the last record from the previous page

The response includes meta.nextCursor for fetching the next page. When nextCursor is null, there are no more pages.

Example pagination flow:

# First page
GET /v1/data/users?limit=20

# Next page (use nextCursor from previous response)
GET /v1/data/users?limit=20&cursor=rec_def456

# Continue until nextCursor is null

6. Relations

6.1 One-to-Many (1:N)

Store a reference ID in the child table:

Table: users
  - id (system)
  - name (string)
  - email (string)

Table: posts
  - id (system)
  - title (string)
  - content (string)
  - authorId (string)  ← references users.id

Join query to include related data:

http
GET /v1/data/posts?join=authorId

Response with joined data:

json
{
  "success": true,
  "data": [
    {
      "id": "post_001",
      "title": "My First Post",
      "content": "Hello world",
      "authorId": "usr_abc",
      "author": {
        "id": "usr_abc",
        "name": "John Doe",
        "email": "john@example.com"
      }
    }
  ]
}

6.2 Many-to-Many (N:M)

Use a junction table to model many-to-many relationships:

Table: posts
  - id (system)
  - title (string)

Table: tags
  - id (system)
  - name (string)

Table: post_tags (junction)
  - id (system)
  - postId (string)  ← references posts.id
  - tagId (string)   ← references tags.id

Query posts with their tags:

http
GET /v1/data/post_tags?filter={"postId":{"$eq":"post_001"}}&join=tagId

7. MCP Table Management Tools

Use these MCP tools for schema and table management operations:

7.1 Table Operations

ToolDescription
backend_table_createCreate a new table with field definitions
backend_table_listList all tables in the project
backend_table_getGet table schema and metadata
backend_table_updateUpdate table settings
backend_table_deleteDelete a table and all its data

Example: Create a table

Tool: backend_table_create
Arguments:
  tableName: "users"
  fields:
    - name: "name"
      type: "string"
      required: true
    - name: "email"
      type: "string"
      required: true
      unique: true
    - name: "age"
      type: "int"
      min: 0
      max: 150
    - name: "role"
      type: "string"
      enum: ["user", "admin"]
      default: "user"
    - name: "isActive"
      type: "bool"
      default: true

7.2 Field Management

ToolDescription
backend_field_manageAdd, update, or remove fields from a table

Example: Add a field

Tool: backend_field_manage
Arguments:
  tableName: "users"
  action: "add"
  field:
    name: "bio"
    type: "string"
    max: 500

7.3 Index Management

ToolDescription
backend_index_manageCreate, list, or delete custom indexes

Example: Create a compound index

Tool: backend_index_manage
Arguments:
  tableName: "users"
  action: "create"
  index:
    name: "idx_role_active"
    fields:
      - field: "role"
        direction: 1
      - field: "isActive"
        direction: 1

7.4 Schema Versioning

ToolDescription
backend_schema_version_listList all schema versions for a table
backend_schema_version_getGet a specific schema version

8. Frontend CRUD Pattern (TanStack Query)

Use the Query Key Factory pattern for consistent cache management:

typescript
// lib/queries/users.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { bkendFetch } from '@/lib/bkend';

// Query Key Factory
export const userKeys = {
  all: ['users'] as const,
  lists: () => [...userKeys.all, 'list'] as const,
  list: (filters: Record<string, unknown>) =>
    [...userKeys.lists(), filters] as const,
  details: () => [...userKeys.all, 'detail'] as const,
  detail: (id: string) => [...userKeys.details(), id] as const,
};

// List users with filters
export function useUsers(filters: Record<string, unknown> = {}) {
  return useQuery({
    queryKey: userKeys.list(filters),
    queryFn: async () => {
      const params = new URLSearchParams();
      if (filters.filter) params.set('filter', JSON.stringify(filters.filter));
      if (filters.sort) params.set('sort', JSON.stringify(filters.sort));
      if (filters.limit) params.set('limit', String(filters.limit));
      if (filters.cursor) params.set('cursor', String(filters.cursor));

      const res = await bkendFetch(`/v1/data/users?${params.toString()}`);
      return res.json();
    },
  });
}

// Get single user
export function useUser(id: string) {
  return useQuery({
    queryKey: userKeys.detail(id),
    queryFn: async () => {
      const res = await bkendFetch(`/v1/data/users/${id}`);
      return res.json();
    },
    enabled: !!id,
  });
}

// Create user mutation
export function useCreateUser() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (data: Record<string, unknown>) => {
      const res = await bkendFetch('/v1/data/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
      });
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: userKeys.lists() });
    },
  });
}

// Update user mutation
export function useUpdateUser() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async ({ id, data }: { id: string; data: Record<string, unknown> }) => {
      const res = await bkendFetch(`/v1/data/users/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
      });
      return res.json();
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: userKeys.detail(variables.id) });
      queryClient.invalidateQueries({ queryKey: userKeys.lists() });
    },
  });
}

// Delete user mutation
export function useDeleteUser() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (id: string) => {
      const res = await bkendFetch(`/v1/data/users/${id}`, {
        method: 'DELETE',
      });
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: userKeys.lists() });
    },
  });
}

9. Error Codes

Error CodeHTTP StatusDescription
TABLE_NOT_FOUND404The specified table does not exist
VALIDATION_ERROR400Request data fails schema validation
DUPLICATE_KEY400A unique constraint violation occurred
PERMISSION_DENIED403User lacks permission for this operation
INVALID_FILTER400The filter syntax is malformed or invalid
RECORD_NOT_FOUND404The specified record ID does not exist
LIMIT_EXCEEDED400The requested limit exceeds the maximum (100)

Error response format:

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Field 'email' is required",
    "details": [
      { "field": "email", "message": "This field is required" }
    ]
  }
}

Quick Reference

Common Workflows

  1. Create a table -> Use backend_table_create MCP tool
  2. Add fields later -> Use backend_field_manage MCP tool
  3. Insert data -> POST /v1/data/:tableName
  4. Query with filters -> GET /v1/data/:tableName?filter={...}&sort={...}&limit=20
  5. Join related data -> GET /v1/data/:tableName?join=fieldName
  6. Paginate results -> Use cursor from meta.nextCursor
  7. Search records -> GET /v1/data/:tableName?search=keyword&searchType=partial
  8. Manage indexes -> Use backend_index_manage MCP tool

Frequently asked questions

What does the Bkend Data AI skill do?

bkend.ai database expert skill. Covers table creation, CRUD operations, 7 column types, constraints, filtering (AND/OR, 10 operators), sorting, pagination, relations, joins, indexing, and schema management via MCP and REST API. Triggers: table, column, CRUD, schema, index, filter, query, data model, 테이블, 컬럼, 스키마, 인덱스, 필터, 쿼리, 데이터 모델, テーブル, カラム, スキーマ, インデックス, フィルター, 数据表, 列, 模式, 索引, 过滤, 查询, tabla, columna, esquema, indice, filtro, consulta, tableau, colonne, schema, index, filtre, requete, Tabelle, Spalte, Schema, Index, Filter, Abfrage, tabella, colonna, schema, indice, filtro, query Do NOT...

Why use Bkend Data on TypingMind?

Because you install it once and use it with any model. Bkend Data is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Bkend Data in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ww-w-ai/bkit-gemini/tree/main/skills/bkend-data. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Bkend Data?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Bkend Data?

As many as you like. As long as a model supports skills, you can use Bkend Data with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Bkend Data AI skill free?

Yes. It is published on GitHub by ww-w-ai under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇