Chapter 22: Interacting with the Host Database
TL;DR
- Define your schema: Create a
sql/directory in your pack's root. Add.sqlfiles withCREATE TABLEstatements (e.g.,001_my_table.sql). The files are executed alphabetically on install. - No direct database access: Packs do not connect to the host DB directly. All access is via the
worka/dbvirtual pack. - Query from your backend: Use the in‑process MCP client to call
execute_queryonworka/db. - Use
execute_query: Providesqlandparams; the host runs it against your private schema and returns rows.
Many packs need to store their own data—user settings, created items, session information, etc. Worka provides a robust, secure, and isolated persistence model for every pack using the central PostgreSQL database managed by the Host.
Step 1: Defining Your Pack's Schema
To create your own private tables, you start by creating a sql/ directory in the root of your pack.
Inside this directory, you place standard .sql files containing your CREATE TABLE statements and any other DDL (Data Definition Language) commands.
There is a critical convention you must follow: the Host executes these files alphabetically during pack installation. Therefore, you must name your files with a numeric prefix to control their execution order.
Example Structure:
my-pack/
└── sql/
├── 001_create_authors_table.sql
├── 002_create_posts_table.sql
└── 003_add_indexes.sql
When your pack is installed, Worka will automatically create a private schema for your pack in the database and then execute these files in order, setting up your tables.
Step 2: The worka/db Virtual Pack
For security, packs never connect to the host database directly. All access is brokered through worka/db, which enforces schema isolation. This prevents a compromised pack from accessing data outside its own schema.
The interface for this brokered access is the worka/db virtual pack.
Step 3: Querying from Your Backend
To run a query from your pack’s backend, call worka/db using the in‑process MCP client.
let client = McpClient::inproc();
let response = client.call(
"worka/db",
"execute_query",
json!({
"sql": "SELECT id, title, content FROM my_posts WHERE id = $1",
"params": [123]
})
).await?;
This secure flow ensures that your pack can only ever run queries against its own, isolated schema, providing a powerful yet safe persistence model for all packs in the ecosystem.