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.ddlfile 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.connectionModetosingleShot. The server refuses to start inpersistentmode, 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
ReadOnlyorFull. This writesdb2clp.mcpAccessto 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
ReadOnlyandFullgrant. Anything else — a typo, wrong case, a missing entry — denies. Setting the level back toNoneremoves the grant. -
Run DB2: Start MCP Server, or use the plug icon in the connections panel. With
db2clp.mcp.autoStartleft 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.jsonby 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. Setdb2clp.mcp.autoWriteConfigtofalseif 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 DATAcan be invoked from an ordinarySELECTand will write. No statement-level inspection can catch that. - Data-change-table-references (
SELECT ... FROM FINAL TABLE (INSERT ...)) are caught, along withOLD TABLEandNEW TABLE, but that is a specific pattern, not a general guarantee. - Anything the inspector cannot classify is denied, including
CALL,COMMITandLOCK TABLE. Common table expressions are classified by the statement that follows the CTE list, soWITH ... SELECTreads andWITH ... INSERTwrites.
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
db2clioutput 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. persistentmode sends the connection string, including the password, to a visible terminal. PrefersingleShotif that matters to you; MCP requires it.
License
See the repository's LICENSE.