Imported from Black-Rainbow-Labs/Inillucent (
.claude/skills/inillucent-mcp/SKILL.md). Install upstream withnpx skills add Black-Rainbow-Labs/Inillucent --skill inillucent-mcp. Copyright stays with the author.
Giving an agent a database, over MCP
inillucent-mcp serves 28 of the CLI's commands as MCP tools over standard input and output. They
are generated from the same command table the CLI reads, so the two cannot drift — a test
(command_parity.rs) fails the build if they do — and a tool's description is the same sentence
inillucent help <command> prints.
Wiring it up
{
"mcpServers": {
"inillucent": {
"command": "inillucent-mcp",
"args": ["--db", "app.rdb"]
}
}
}
Tools arrive named inillucent_query, inillucent_exec, inillucent_describe,
inillucent_search, inillucent_migrate, and so on.
The two flags to think about before you hand it over
"args": ["--db", "app.rdb", "--readonly", "--root", "/srv/data"]
-
--readonlyrefuses every statement that changes something. The classification is the binder's — whether the statement binds as a query — not a scan of the text, soSELECT … ; DROP TABLE …does not slip through and aSELECTthat happens to contain the word "delete" is not refused. -
--root DIRrefuses every path that resolves outside a directory. Resolves, not spells: every component is followed through the file system as it is appended, so a Windows junction or a Unix symbolic link placed below the root is replaced by what it points at before the check happens. A path that does not exist yet stops the resolution at its deepest existing ancestor, which is what lets the same check authorise a file about to be created, and the VFS checks the target again at the moment it is opened.The policy covers every file the request causes to be opened, not only the one in the
dbargument:create,import,export,backup,restore,migrate, the database the server was started on, and the two statements that name a file of their own,ATTACH DATABASEandVACUUM INTO. It is enforced in the VFS, which is the only thing in the workspace that opens a file, so a command added later is confined without anybody remembering to add it to a list. Temporary files a confined process makes are made inside the root.
--root also refuses a migration from a server. migrate --kind postgres dials a host and a
port, and the confinement is about reach, not only about paths — a verb that could open a socket
would be a hole straight through it. That refusal is by name, so an agent that hits it is told why
rather than left guessing.
Neither flag is a substitute for filesystem permissions. They are the difference between "this agent can read the reporting database" and "this agent can read everything the user can", which is usually the difference you wanted.
Making a call
{ "name": "inillucent_query",
"arguments": { "sql": "SELECT id, body FROM note WHERE created > ?1",
"params": ["2026-01-01"], "limit": 50 } }
paramsbinds?1,?2… in order. Pasting values intosqlis how an agent produces a quoting bug it cannot see.limitcaps the rows returned, not the count. The result'stotalis the real number andmoresays whether anything was cut.- The result is the same JSON object every surface produces:
ok,columnswith observed storage classes,rows,row_count,total,more,changes,last_insert_rowid,elapsed_ms,text, and on a failurestatusplusmessage.
The order that avoids wasted calls
inillucent_capabilities— what this engine does, checked against the running engine in both directions by a test. Ask before composing anything unusual.inillucent_tables— what is here.inillucent_describe— the one table, with its columns, keys, indexes, row count and DDL. Do this before writing SQL against a table you did not create.inillucent_query, with bound parameters.
Reading a failure
status is one of the driver's fourteen names, and it is what to branch on rather than the message:
| status | what to do |
|---|---|
unsupported |
the engine has not built that construct. Not a typo. Rewording will not help — pick another construct, or ask capabilities |
syntax |
the statement did not parse; the message carries the byte offset |
constraint |
the data was refused, and the message names the constraint |
invalid_state |
the request was not one the surface could carry out — a confined path, a destination that already exists, a write on a read-only server |
not_found |
the file, table or object is not there |
What is not served, and why
shell is CLI-only: it reads a keyboard and writes a screen, and neither exists at the other end of
an MCP call. Use inillucent_run instead, which drives the same shell over a pipe and hands back
what it printed — dot commands included.