DB2 CLP Runner
Run Db2 SQL scripts from VS Code, keep your connections and credentials organized, and — optionally — let an
AI agent query Db2 through an MCP server without ever handing it your credentials.
Features
- Run from the editor — run the whole file, the selection, or several files at once. Output is parsed into
the DB2 CLP output channel, with SQL errors surfaced as diagnostics.
- Connections panel — an activity-bar tree of your connections and their saved users. Switch the active
connection, add or edit databases and users, and test a connection without leaving the tree. A connection
shows green only when it has a password that can actually be used.
- Credentials in Secret Storage — passwords are never written to settings. Enter them once; they persist
after they authenticate.
- MCP server — expose selected connections to MCP-capable agents (Claude Code, Codex, and others). The
agent sends an alias and SQL; the extension resolves the user and password itself. See below.
Requirements
The extension runs SQL through db2cli from the IBM Data Server Driver (clidriver) or a Db2 client install.
It does not bundle the driver, and it no longer uses the interactive db2 command-line processor.
Discovery checks db2clp.db2cliPath, IBM_DB_HOME, DB2_HOME, CLIDRIVER_HOME, DB2PATH on Windows,
local node_modules/ibm_db/installer/clidriver folders, PATH, and conventional Db2 install roots such as
~/sqllib, /opt/ibm/clidriver, and C:\IBM\SQLLIB.
If db2cli is still not found, point the extension at your driver:
"db2clp.db2cliPath": "/opt/ibm/clidriver"
Either the clidriver root or the db2cli / db2cli.exe binary itself is accepted.
Getting started
- Open the DB2 panel in the activity bar and choose Add Connection (
+ in the panel title bar).
- Fill in alias, host, port, and database, then add a user and password.
- Open a
.db2, .sql, or .ddl file and run it — the run button sits in the editor title bar by default.
Statement terminators are per file type: .db2 uses @, .sql and .ddl use ;. Change this with
db2clp.fileExtensions.
MCP server
An agent gets an alias and a SQL string. It never receives a username, a password, or a connection string —
those are resolved inside the extension from Secret Storage and passed to db2cli directly.
Access is denied by default and granted per saved user, not per connection. The level says what an
agent may do; the user says who it does it as. Different users of one database can hold different levels —
reader may be ReadOnly while admin is Full, or the reverse. Nothing is inferred from the username.
Set db2clp.connectionMode to singleShot. The server refuses to start in persistent mode, which puts
the connection string in a visible terminal and would defeat the point.
Save credentials for the user you want to expose.
Open Edit User on that user and set MCP Access to ReadOnly or Full. This writes
db2clp.mcpAccess to your user settings, which is machine-scoped — a cloned repository cannot grant
itself database access, and a value placed in workspace settings is ignored:
"db2clp.mcpAccess": { "testdb": { "db2inst1": "ReadOnly" } }
Only the exact values ReadOnly and Full grant. Anything else — a typo, wrong case, a missing entry —
denies. Setting the level back to None removes the grant.
Run DB2: Start MCP Server, or use the plug icon in the connections panel. With
db2clp.mcp.autoStart left at its default the server also comes up on its own every time the
window opens, so this step is only needed after an explicit Stop.
That is the whole setup. The first successful start registers the server in the workspace
.mcp.json by itself, so clients that read that file — Claude Code among them — find it without
any further step; restart the client once so it notices the new server. DB2: Write MCP Config
(.mcp.json) is still there for writing the entry on demand, for instance into a workspace where
the server has never started. The file contains no secrets: the transport is a user-private local
socket, so there is no token to leak. Set db2clp.mcp.autoWriteConfig to false if you would
rather the extension never wrote to the workspace.
.mcp.json is machine-specific — do not commit it. The entry records the absolute path of the
VS Code binary, of the bridge inside the installed extension directory, and of the local endpoint.
None of the three is portable, and the bridge path changes every time the extension updates, because
the install directory carries the version number. To keep it working the extension re-checks the
db2clp entry on every activation and silently rewrites it when it no longer matches this build —
so an update never leaves you with a config pointing at a directory that is gone. Activation only
repairs an entry that is already there; creating one is reserved for a successful server start,
so a workspace that never runs MCP never gets the file. Other servers in
the file, and every other key in it, are left untouched. Add .mcp.json to .gitignore.
Where the server can be reached from
The transport is a unix socket (a named pipe on Windows) with 0600 permissions in a 0700
directory. A client can connect only if it runs on the same machine, as the same user. In
particular it does not reach across containers: if VS Code runs in a dev container and the agent
runs in a different one, the endpoint does not exist for the agent no matter how .mcp.json is
written. Run the agent in the same container as the extension host.
The endpoint name is derived from the workspace path, so two windows on the same workspace compete
for one endpoint. The second window reports that another window is already serving it and leaves the
first one alone; different workspaces never collide.
Two tools are exposed: list_connections and run_sql. list_connections reports one entry per granted
user, identified by a handle of the form alias/user — that handle is what run_sql takes as its alias.
Results are db2cli text with the copyright banner removed and the echoed statement laid out one
clause per line — unreliable to parse mechanically, but perfectly readable to a language model. The
same presentation is applied to the DB2 CLP output channel when you run a file from the editor.
Grants are re-checked on every call, so revoking access or deleting a password takes effect immediately rather
than at the next restart.
What ReadOnly actually guarantees
ReadOnly is enforced by DB2, not by this extension. Grant it to a DB2 user that DB2 itself restricts to
SELECT. The extension inspects SQL before running it, but that check is defence in depth and error
messaging — it is not the security boundary.
It cannot be, and the limits are worth stating plainly:
- A function declared
MODIFIES SQL DATA can be invoked from an ordinary SELECT and will write. No
statement-level inspection can catch that.
- Data-change-table-references (
SELECT ... FROM FINAL TABLE (INSERT ...)) are caught, along with OLD TABLE and NEW TABLE, but that is a specific pattern, not a general guarantee.
- Anything the inspector cannot classify is denied, including
CALL, COMMIT and LOCK TABLE. Common
table expressions are classified by the statement that follows the CTE list, so WITH ... SELECT reads and
WITH ... INSERT writes.
If the granted user has write privileges in DB2, ReadOnly will stop the obvious cases and cannot promise
more than that.
Commands
| Command |
Description |
DB2: Run / DB2: Run File / DB2: Run Selection / DB2: Run Files |
Run the current file, the selection, or several selected files |
DB2: Connect / DB2: Disconnect |
Open or close a persistent session |
DB2: Select Connection |
Switch the active alias |
DB2: Add Connection / DB2: Refresh Connections |
Manage the connections panel |
DB2: Forget Saved Credentials for Active Connection |
Clear stored credentials for the active alias |
DB2: Start MCP Server / DB2: Stop MCP Server |
Control the MCP server |
DB2: Write MCP Config (.mcp.json) |
Register the server with MCP clients in this workspace |
Per-connection actions — add or edit a user, set the active user, edit or delete a connection, test a
connection — live on the right-click menu and inline buttons of the connections panel.
Settings
| Setting |
Default |
Description |
db2clp.db2cliPath |
"" |
Path to the clidriver root or the db2cli binary |
db2clp.fileExtensions |
{".db2": "@", ".sql": ";", ".ddl": ";"} |
Runnable file types and their statement terminators |
db2clp.connectionMode |
persistent |
persistent session, or singleShot per run. MCP requires singleShot |
db2clp.rememberCredentials |
true |
Save a password typed at a prompt once it authenticates. Credentials added through the panel are always saved and always used, regardless of this setting |
db2clp.currentSchema |
"" |
Schema applied to each run |
db2clp.runButtonLocation |
titleBar |
titleBar, statusBar, or hidden |
db2clp.mcpAccess |
{} |
Machine-scoped. Alias → user → "ReadOnly" or "Full" grants MCP access. Set it from Edit User. Ignored in workspace settings by design |
db2clp.mcp.autoStart |
true |
Start the MCP server when the extension activates. A no-op without grants |
db2clp.mcp.autoWriteConfig |
true |
Keep the db2clp entry in the workspace .mcp.json current. Other servers in the file are never touched |
db2clp.db2profilePath |
~/sqllib/db2profile |
Legacy; retained for compatibility and not used by the db2cli execution path |
db2clp.connections, db2clp.activeConnection, and db2clp.currentSchema are written by the extension —
manage connections through the panel rather than by editing settings.
Notes
- Results are raw
db2cli output in the DB2 CLP channel. This is a script runner, not a result grid or
schema browser — see the companion DB2 ODBC extension for those.
persistent mode sends the connection string, including the password, to a visible terminal. Prefer
singleShot if that matters to you; MCP requires it.
License
See the repository's LICENSE.