@ifx_zieglchr/oracle-sqlcl-mcp-wrapper 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christoph Ziegler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,103 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # Oracle SQLcl MCP wrapper for VS Code (Windows)
2
+
3
+ Unofficial, dependency-free stdio launcher for the MCP server bundled with
4
+ Oracle SQL Developer for VS Code. It finds the locally installed extension and
5
+ starts its MCP server without hardcoding your username or extension version.
6
+
7
+ This package is not affiliated with or endorsed by Oracle. It does not contain,
8
+ download or install Oracle binaries, Java, database credentials or connection
9
+ files. Oracle software remains subject to its own licenses.
10
+
11
+ ## Requirements
12
+
13
+ - Windows with Node.js 22 or later on PATH.
14
+ - The official Oracle SQL Developer extension installed in the same user's
15
+ VS Code environment, including its `dbtools.exe` runtime.
16
+ - The extension architecture must match the Node.js process architecture for
17
+ automatic discovery. macOS, Linux and remote extension hosts are unsupported.
18
+
19
+ ## Check your installation
20
+
21
+ ```powershell
22
+ npx --yes @ifx_zieglchr/oracle-sqlcl-mcp-wrapper@0.1.0 --check
23
+ ```
24
+
25
+ `--check` reports the resolved executable, arguments and extension version to
26
+ stderr. It does not start Oracle or connect to a database. stdout is reserved
27
+ for MCP traffic.
28
+
29
+ ## MCP client configuration
30
+
31
+ For a client supporting local stdio servers, such as VS Code:
32
+
33
+ ```json
34
+ {
35
+ "servers": {
36
+ "oracle-sqlcl-wrapper": {
37
+ "type": "stdio",
38
+ "command": "npx",
39
+ "args": [
40
+ "--yes",
41
+ "@ifx_zieglchr/oracle-sqlcl-mcp-wrapper@0.1.0"
42
+ ]
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ Use your client's stdio-server configuration mechanism. Enterprise clients may
49
+ require separate approval of this exact server command and arguments.
50
+ Installing this package does not grant database access or bypass client policy.
51
+ Do not use `npm start` as the MCP command: npm lifecycle banners can interfere
52
+ with the protocol.
53
+
54
+ ## Extension discovery
55
+
56
+ The launcher searches `.vscode\extensions` in the current user's home directory.
57
+ It ignores versions marked for removal in `.obsolete` and selects the numerically
58
+ newest stable Windows Oracle extension matching the Node process architecture.
59
+ It checks the extension manifest identity and the existence of `dbtools.exe`.
60
+ These checks are not a cryptographic authenticity guarantee; installed
61
+ extensions must be trusted.
62
+
63
+ If the newest installation is incomplete, startup fails explicitly instead of
64
+ silently switching to an older runtime. Discovery runs again on each server
65
+ start; the wrapper does not update Oracle software.
66
+
67
+ For custom extension directories, portable VS Code, Insiders or a pinned version,
68
+ set `ORACLE_SQLDEV_EXTENSION_DIR` to the absolute extension directory, not the
69
+ executable:
70
+
71
+ ```powershell
72
+ $env:ORACLE_SQLDEV_EXTENSION_DIR = 'C:\path\to\oracle.sql-developer-26.3.0-win32-x64'
73
+ npx --yes @ifx_zieglchr/oracle-sqlcl-mcp-wrapper@0.1.0 --check
74
+ ```
75
+
76
+ For an MCP client, set the override through that client's server environment
77
+ configuration. The default installation needs no override.
78
+
79
+ ## Runtime behavior and limitations
80
+
81
+ The launcher runs the discovered `dbtools.exe` with:
82
+
83
+ ```text
84
+ --jvm-option -Duser.language=en sql -mcp
85
+ ```
86
+
87
+ The child inherits stdin, stdout, stderr and the calling environment. There is
88
+ no shell, protocol translation, added stdout logging, or change to Oracle's tools
89
+ and authorization. The wrapper does not load workspace `.env` files.
90
+ Database connections and credentials are handled by Oracle's normal runtime;
91
+ they are neither collected nor packaged by this launcher.
92
+
93
+ Verified with Windows x64, Oracle extension 26.3.0 and Node.js 24:
94
+ MCP initialization, listing ten tools without invoking database tools, and clean
95
+ exit after closing stdin. Actual connection workflows, extension updates and
96
+ client-driven forced termination of JVM subprocesses require testing in your
97
+ environment. Windows ARM64 discovery is implemented but has not been validated
98
+ with an actual ARM64 Oracle installation.
99
+
100
+ ## License
101
+
102
+ MIT, copyright 2026 Christoph Ziegler. See [LICENSE](LICENSE).
103
+ This license covers only this wrapper, not Oracle software.
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import { resolveServer, startServer } from '../src/launcher.js';
3
+
4
+ try {
5
+ const args = process.argv.slice(2);
6
+ if (args.length > 1 || (args.length === 1 && args[0] !== '--check')) {
7
+ throw new Error('Usage: oracle-sqlcl-mcp-wrapper [--check]');
8
+ }
9
+ const server = await resolveServer();
10
+ if (args[0] === '--check') {
11
+ process.stderr.write(`${JSON.stringify(server, null, 2)}\n`);
12
+ } else {
13
+ process.exitCode = await startServer(server);
14
+ }
15
+ } catch (error) {
16
+ process.stderr.write(`[oracle-sqlcl-mcp-wrapper] ${error.message}\n`);
17
+ process.exitCode = 1;
18
+ }
package/package.json CHANGED
@@ -1,6 +1,32 @@
1
- {
2
- "name": "@ifx_zieglchr/oracle-sqlcl-mcp-wrapper",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "@ifx_zieglchr/oracle-sqlcl-mcp-wrapper",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "publishConfig": {
6
+ "registry": "https://registry.npmjs.org/",
7
+ "access": "public"
8
+ },
9
+ "description": "Windows stdio launcher for the locally installed Oracle SQL Developer VS Code extension",
10
+ "type": "module",
11
+ "bin": {
12
+ "oracle-sqlcl-mcp-wrapper": "bin/oracle-sqlcl-mcp-wrapper.js"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "src/",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "engines": {
21
+ "node": ">=22"
22
+ },
23
+ "os": [
24
+ "win32"
25
+ ],
26
+ "scripts": {
27
+ "check": "node bin/oracle-sqlcl-mcp-wrapper.js --check",
28
+ "probe": "node scripts/probe.js",
29
+ "start": "node bin/oracle-sqlcl-mcp-wrapper.js",
30
+ "test": "node --test"
31
+ }
32
+ }
@@ -0,0 +1,101 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readFile, readdir, stat } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ export const MCP_ARGS = ['--jvm-option', '-Duser.language=en', 'sql', '-mcp'];
7
+
8
+ export async function resolveServer({
9
+ env = process.env,
10
+ home = homedir(),
11
+ platform = process.platform,
12
+ arch = process.arch,
13
+ } = {}) {
14
+ if (platform !== 'win32') {
15
+ throw new Error('This prototype supports Windows only. Run it on the PC with the Oracle extension installed.');
16
+ }
17
+
18
+ let extensionDir = env.ORACLE_SQLDEV_EXTENSION_DIR;
19
+ if (extensionDir && !path.isAbsolute(extensionDir)) {
20
+ throw new Error('ORACLE_SQLDEV_EXTENSION_DIR must be an absolute extension directory path.');
21
+ }
22
+
23
+ if (!extensionDir) {
24
+ const root = path.join(home, '.vscode', 'extensions');
25
+ let entries;
26
+ try {
27
+ entries = await readdir(root, { withFileTypes: true });
28
+ } catch (error) {
29
+ throw new Error(`Cannot read VS Code extensions at ${root}. Install Oracle SQL Developer or set ORACLE_SQLDEV_EXTENSION_DIR.`, { cause: error });
30
+ }
31
+
32
+ let obsolete = {};
33
+ try {
34
+ obsolete = JSON.parse(await readFile(path.join(root, '.obsolete'), 'utf8'));
35
+ } catch (error) {
36
+ if (error.code !== 'ENOENT') {
37
+ throw new Error(`Cannot read extension removal metadata at ${root}: ${error.message}`, { cause: error });
38
+ }
39
+ }
40
+ if (!obsolete || typeof obsolete !== 'object' || Array.isArray(obsolete)) {
41
+ throw new Error(`Invalid extension removal metadata at ${root}.`);
42
+ }
43
+
44
+ const candidates = entries.flatMap((entry) => {
45
+ const match = /^oracle\.sql-developer-(\d+)\.(\d+)\.(\d+)-win32-(x64|arm64)$/.exec(entry.name);
46
+ if (!entry.isDirectory() || !match || match[4] !== arch || obsolete[entry.name]) {
47
+ return [];
48
+ }
49
+ return [{ name: entry.name, version: match.slice(1, 4).map(Number) }];
50
+ });
51
+ candidates.sort((a, b) => {
52
+ for (let i = 0; i < 3; i += 1) {
53
+ if (a.version[i] !== b.version[i]) {
54
+ return b.version[i] - a.version[i];
55
+ }
56
+ }
57
+ return 0;
58
+ });
59
+ if (!candidates.length) {
60
+ throw new Error(`No active Windows ${arch} Oracle SQL Developer extension found in ${root}. Install it or set ORACLE_SQLDEV_EXTENSION_DIR.`);
61
+ }
62
+ extensionDir = path.join(root, candidates[0].name);
63
+ }
64
+
65
+ const manifest = JSON.parse(await readFile(path.join(extensionDir, 'package.json'), 'utf8'));
66
+ if (manifest.name !== 'sql-developer' || manifest.publisher?.toLowerCase() !== 'oracle') {
67
+ throw new Error(`Not an Oracle SQL Developer extension: ${extensionDir}`);
68
+ }
69
+ const command = path.join(extensionDir, 'dbtools', 'bin', 'dbtools.exe');
70
+ if (!(await stat(command)).isFile()) {
71
+ throw new Error(`Oracle MCP executable is not a file: ${command}`);
72
+ }
73
+ return { command, args: [...MCP_ARGS], extensionDir, extensionVersion: manifest.version };
74
+ }
75
+
76
+ export function startServer({ command, args }) {
77
+ const child = spawn(command, args, {
78
+ stdio: 'inherit',
79
+ shell: false,
80
+ windowsHide: true,
81
+ });
82
+ const onSignal = (signal) => child.kill(signal);
83
+ const onInterrupt = () => onSignal('SIGINT');
84
+ const onTerminate = () => onSignal('SIGTERM');
85
+ process.on('SIGINT', onInterrupt);
86
+ process.on('SIGTERM', onTerminate);
87
+
88
+ return new Promise((resolve, reject) => {
89
+ let spawnError;
90
+ child.once('error', (error) => { spawnError = error; });
91
+ child.once('close', (code, signal) => {
92
+ process.removeListener('SIGINT', onInterrupt);
93
+ process.removeListener('SIGTERM', onTerminate);
94
+ if (spawnError) {
95
+ reject(spawnError);
96
+ } else {
97
+ resolve(code ?? (signal === 'SIGINT' ? 130 : 143));
98
+ }
99
+ });
100
+ });
101
+ }