KORM Protocol v2 — JSON request/response protocol for dynamic database operations (reference implementation)
Project description
korm
Reference Python implementation of the KORM Protocol v2 — a JSON request/response protocol for dynamic database operations against PostgreSQL, MySQL/MariaDB, and SQLite.
A KORM server receives a JSON request naming a model and an action, executes it via SQLAlchemy Core 2.x, and returns a uniform response envelope. The protocol is fully describable by JSON Schema, so MCP tools, OpenAPI docs, and typed clients can be generated from one source.
import korm
db = korm.initialize_korm(url="postgresql+asyncpg://...", schema="korm.schema.json")
result = await db.process({ # async, v2-native
"korm": 2,
"action": "list",
"model": "users",
"where": {
"is_active": True,
"age": {"gte": 18, "lt": 65},
"email": {"endsWith": "@example.com"},
},
"include": {"profile": True, "posts": {"limit": 5, "orderBy": "-created_at"}},
"orderBy": "-created_at",
"limit": 20,
})
result = db.process_sync(request_dict) # sync engines
Every action returns the same envelope:
{
"ok": true, "action": "list", "model": "users",
"data": [ ... ],
"meta": { "protocol": 2, "count": 20, "limit": 20, "offset": 0, "durationMs": 4 },
"error": null
}
Features (spec v2.0)
- Actions:
create,list,show,update,delete,restore,upsert,replace,sync,aggregate,batch(optionally atomic, with$refchaining). - Structured where grammar — no stringly-typed operator DSL:
eq ne gt gte lt lte in notIn between notBetween like ilike contains startsWith endsWith is not, plus nestableand/or/notboolean trees with fully parenthesized SQL. - Safe by construction — no raw SQL fragments anywhere; all identifiers validated
against the schema;
contains/startsWith/endsWithescape%and_. - Pagination — offset mode and opaque keyset cursors (send
"cursor": nullfor the first page, followmeta.nextCursor); optional HMAC-signed cursors viacursor_secret. - Relations —
hasOne/hasMany/belongsToincludes with per-relationselect/where/orderBy/limit, nested dotted paths, and validated explicit joins.manyToManyis accepted in schemas (syntax v2.0) and executes from v2.1. - Aggregates —
count sum avg min max,groupBy,having, and JSON expression trees ({"add": ["salary", "bonus"]}) replacing v1'ssumFormulastrings. - Soft delete — automatic
deleted_at IS NULLfiltering,withDeleted/onlyDeleted/hardDeleteoptions, first-classrestore. - Hooks —
beforeValidate,afterValidate,before<Action>,after<Action>,onError; sync or async; may mutate the request, short-circuit, or raise. - Policy layer — per-role model/action allowlists,
default_denyproduction mode, mandatory where-scopes for tenant isolation ({"org_id": "$ctx.orgId"}). - v1 compatibility — a deterministic up-converter (on by default,
compat_v1) accepts v1 operator strings (">=18","><18,65","[]a,b","!x","%like%",Or:keys,count/sumactions, string join conditions) and down-converts responses (bare count numbers, bareshowobjects) for v1 clients.strict_v2: trueturns it off. - Errors are codes, not prose:
VALIDATION_FAILED,UNKNOWN_MODEL,UNKNOWN_COLUMN,UNKNOWN_RELATION,UNKNOWN_ACTION,NOT_FOUND,CONFLICT,FK_VIOLATION,POLICY_DENIED,LIMIT_EXCEEDED,TRANSACTION_FAILED,BATCH_ROLLED_BACK,UNSUPPORTED_ON_ENGINE,INTERNAL— with structured per-fielddetails.
Install
pip install korm # SQLite via stdlib driver
pip install korm[postgres] # psycopg + asyncpg
pip install korm[mysql] # PyMySQL + aiomysql
pip install korm[fastapi] # HTTP router
pip install korm[mcp] # MCP server
Schema (korm.schema.json)
One file drives DDL sync, request validation, and generated types:
{
"kormSchema": 2,
"models": {
"users": {
"table": "users",
"primaryKey": ["id"],
"softDelete": { "column": "deleted_at" },
"timestamps": { "createdAt": "created_at", "updatedAt": "updated_at" },
"columns": {
"id": { "type": "increments" },
"username": { "type": "string", "length": 80, "unique": true, "required": true },
"email": { "type": "string", "format": "email", "required": true }
},
"relations": {
"profile": { "type": "hasOne", "model": "user_profiles", "foreignKey": "user_id" },
"posts": { "type": "hasMany", "model": "posts", "foreignKey": "author_id" }
}
}
}
}
FastAPI
from fastapi import FastAPI
from korm.fastapi import crud_router
app = FastAPI()
app.include_router(crud_router(db), prefix="/api")
# POST /api/{model}/crud
CLI
korm init # scaffold korm.schema.json
korm generate-schema --url sqlite:///app.db # introspect a live database
korm sync --url ... --schema korm.schema.json # dev-time DDL sync
korm diff --url ... --schema korm.schema.json # migration skeleton
korm serve-mcp --url ... --schema ... # per-model MCP tools over stdio
sync is a dev/prototyping tool; for production use migration tools (Alembic/Knex)
generated from korm diff output.
Development
pip install -e ".[dev]"
pytest
Status
Implements KORM Protocol v2 draft 0.2 (including v2.1 features: manyToMany include
execution and column-level policy allowlists). meta.prevCursor is currently always
null (forward-only keyset).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file korm-2.0.0a3.tar.gz.
File metadata
- Download URL: korm-2.0.0a3.tar.gz
- Upload date:
- Size: 10.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a844a73b9a1b28c1fd2cd86e9fc381f725495b2503b62e67097db2e39f351907
|
|
| MD5 |
fbd08917952fc567e0e436cf97a2cf81
|
|
| BLAKE2b-256 |
7862b5392a3a9df56e4e7b12f8b66e161e4ab470b1cb1f2a4302ad69609c2ffa
|
File details
Details for the file korm-2.0.0a3-py3-none-any.whl.
File metadata
- Download URL: korm-2.0.0a3-py3-none-any.whl
- Upload date:
- Size: 48.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7db52b28663be917444fcaafc8486ee3684b70e69f9d1600aa102c58497f9644
|
|
| MD5 |
1014a8739f6278159ede16309c6b8854
|
|
| BLAKE2b-256 |
b046c5546ebbf5fd1d57843050787eb69ff33461acac304d216f95183020e745
|