Shoddy · Picker
The tools level in two steps: install pick, then register it. At the end, an assistant can read your database through the query gate.
This page sets up the tools level, the first of pick's three levels. At this level pick has a connection to one server, checks every query at its gate, and needs you to declare nothing else. The other two levels, guardrails and screenings, come after, and you turn each one on by adding one section to a file.
If you can already reach a SQL Server, skip this section and keep its connection string to hand. A connection string is the text that says which server to reach and how to sign in to it. If you have no server, start LocalDB, the small SQL Server that comes with the Windows development tools:
sqllocaldb start MSSQLLocalDBIf your system says that sqllocaldb is not a command, install SQL Server Express LocalDB and run the line again. Then make a small database with one table in it, so you have something to read:
sqlcmd -S "(localdb)\MSSQLLocalDB" -E -Q "CREATE DATABASE Sales;"
sqlcmd -S "(localdb)\MSSQLLocalDB" -E -d Sales -Q "CREATE TABLE dbo.Customers(id int PRIMARY KEY, name nvarchar(80)); INSERT dbo.Customers VALUES (1, N'Iris Sutcliffe'), (2, N'Harold Wilson');"pick is a single file, and it needs no .NET runtime and no installer. In the commands below, put the version you downloaded in place of X.Y.Z.
$dir = "$env:LOCALAPPDATA\Programs\pick"
New-Item -ItemType Directory -Force $dir | Out-Null
Expand-Archive pick-X.Y.Z-win-x64.zip -DestinationPath $dir -Force
Get-ChildItem $dir -Recurse | Unblock-File
$user = [Environment]::GetEnvironmentVariable('Path', 'User')
if ($user -notlike "*$dir*") {
[Environment]::SetEnvironmentVariable('Path', "$user;$dir", 'User')
}mkdir -p ~/.local/bin
tar -xzf pick-X.Y.Z-osx-arm64.tar.gz -C ~/.local/bin
xattr -d com.apple.quarantine ~/.local/bin/pick # macOS onlyOpen a new terminal, because the one you just used still has the old PATH. That is the list of folders where your system looks for commands. Then check that pick runs:
pick versionYou should see the word pick followed by the version number you downloaded.
PATH has the details.To register pick is to tell it which server to use, and to tell the assistant where pick is. You write two short files and set one value, and you do it by hand, because pick has no setup command.
In your project folder, make a file called .picker.json with this line in it:
{"tools":{"servers":{"main":{"connect":"env:MAIN_SQL"}}}}This file has only a tools section, so it sets up the tools level and nothing more. It names one server, main, and says its connection string is in an environment variable called MAIN_SQL. An environment variable is a named value your system keeps outside any file, so no password sits in the project.
Set MAIN_SQL to your connection string. The Windows line below is for LocalDB, and if you use another server, put its connection string in place of this one.
[Environment]::SetEnvironmentVariable('MAIN_SQL', 'Server=(localdb)\MSSQLLocalDB;Integrated Security=true;TrustServerCertificate=true', 'User')echo 'export MAIN_SQL="Server=myhost;User Id=reader;Password=...;TrustServerCertificate=true"' >> ~/.profileOpen a new terminal again, so that it sees the new value. Then ask pick what it can see:
pick catalogsYou should see the three level lines first, and then the server you named:
levels
tools on, always; settings from C:\github\app\.picker.json
guardrails off
screenings off
main (connect: env:MAIN_SQL)
every database this login can reach; guardrails are off, so none is declared
source: C:\github\app\.picker.jsonNotice the line under main, which says the server is open. Every database the login can enter is there, apart from the four system databases that every SQL Server has. The catalogs verb opens no connection, so it works even when the server is down. To test the connection itself, run pick doctor.
For Claude Code, add one entry to the file .mcp.json in your project folder. If the file does not exist yet, make it and put exactly this in it:
{
"mcpServers": {
"picker": { "command": "pick", "args": ["serve"] }
}
}Other clients take the same command and arguments in a file of their own, and Registering, per client lists each one.
Then restart the assistant, because a client reads its list of servers only when it starts. Ask it to call catalogs, and it should show the same lines you saw above. When you change .picker.json later, you need no restart, because pick reads the file again before every call.
Run one query that works and one describe, which shows a table's columns. Then try the commands in the table below, each of which the gate refuses:
pick select "SELECT TOP 5 * FROM Sales.dbo.Customers"
pick describe Sales.dbo.Customers| Command | Exit | Why it is refused |
|---|---|---|
pick select "DELETE FROM Sales.dbo.Customers" | 8 | It is not a SELECT, and pick has no way to change data. |
pick select "SELECT 1; SELECT 2" | 8 | One call may carry only one statement. |
pick select "SELECT name FROM sys.tables" | 8 | The system catalog is closed, so use describe instead. |
pick select "SELECT * FROM master.dbo.spt_values" | 3 | master is a system database, so pick says it is not there. |
An exit code is the number a command hands back when it ends, so that a script can tell what happened. The reference lists every exit code and what it means.
guardrails section to declare which databases exist and to hide tables or columns, as Guardrails shows.screenings section to refuse any answer that would show regulated data, as Screenings shows.