@mokoconsulting/mokomysql-mcp 0.0.0-stage → 2.6.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/README.md CHANGED
@@ -1,3 +1,122 @@
1
- # Temporary Holding Version
1
+ # mokomysql-mcp
2
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.
3
+ A Model Context Protocol (MCP) server for MySQL database management — run queries, inspect
4
+ and modify schema, manage users, perform maintenance, and use Joomla-aware helpers, all
5
+ exposed as MCP tools that AI assistants and MCP clients can call.
6
+
7
+ ## Features
8
+
9
+ - Execute SQL queries against a configured MySQL/MariaDB database
10
+ - Inspect and manage schema (tables, columns, indexes)
11
+ - User and privilege management
12
+ - Maintenance operations (analyze, optimize, repair)
13
+ - Joomla-specific helpers for common CMS database tasks
14
+
15
+ ## Requirements
16
+
17
+ - An MCP-capable client (for example, Claude Code or another MCP host)
18
+ - Network access to a MySQL or MariaDB server
19
+ - Database credentials with the privileges required for the operations you intend to run
20
+
21
+ ## Installation
22
+
23
+ The server is published to npm as `@mokoconsulting/mokomysql-mcp`. No manual clone or
24
+ build is required — your MCP client runs it on demand with `npx`:
25
+
26
+ ```bash
27
+ npx -y @mokoconsulting/mokomysql-mcp
28
+ ```
29
+
30
+ Or install it globally:
31
+
32
+ ```bash
33
+ npm install -g @mokoconsulting/mokomysql-mcp
34
+ ```
35
+
36
+ ## Configuration
37
+
38
+ Connections are read from a JSON config file at `~/.mcp_mokomysql.json` (override the path
39
+ with the `MYSQL_MCP_CONFIG` environment variable). See [`config.example.json`](config.example.json):
40
+
41
+ ```json
42
+ {
43
+ "defaultConnection": "local",
44
+ "connections": {
45
+ "local": {
46
+ "host": "127.0.0.1",
47
+ "port": 3306,
48
+ "user": "dbuser",
49
+ "password": "secret",
50
+ "database": "joomla",
51
+ "ssl": false
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ Full configuration reference is in the wiki — docs are **wiki-first** at MokoConsulting:
58
+
59
+ **→ [Configuration (wiki)](https://git.mokoconsulting.tech/MokoConsulting/mokomysql-mcp/wiki/Configuration)**
60
+
61
+ It covers TLS options, environment variables (`MYSQL_MCP_CONFIG`, `MYSQL_MCP_STATE`), the sidecar
62
+ state file, and **Joomla write safety** — writes to a Joomla database require a two-step
63
+ `confirm_token` (the first call returns a token and does not execute); reads are never gated.
64
+
65
+ The write gate is **operation-aware**. The two-step `confirm_token` is required for *every* Joomla
66
+ write, but the "raw SQL can corrupt the ACL nested set" warning is only shown for the operations
67
+ that can actually cause it. Joomla creates, removes, and renumbers `#__assets` / nested-set rows
68
+ only when a row is **created or deleted** through its Table API (`Table::store()` / `Table::delete()`),
69
+ which raw SQL bypasses — so:
70
+
71
+ - A pure **in-place `UPDATE`** that does not reference a nested-set table (`#__assets`, `#__categories`,
72
+ `#__menu`) gets a lighter message: it still needs the token, but it cannot touch the asset tree.
73
+ - **`INSERT` / `DELETE`** of an asset-bearing row (any table with an `asset_id` column), **DDL**, and
74
+ **any write to a nested-set table** keep the full nested-set/ACL warning and the integrity reminder.
75
+
76
+ ### Exports and the `mysql_export_table_sql` replay foot-gun
77
+
78
+ `mysql_export_table_sql` produces a self-contained SQL dump whose output **begins with
79
+ `DROP TABLE IF EXISTS <table>;`** and whose rows are emitted as hand-quoted `INSERT` statements
80
+ (not parameterized). This is convenient for a one-shot restore, but **replaying the dump drops the
81
+ existing table — and all of its current rows — before recreating it.** Never run the output against
82
+ a database where the target table already holds data you intend to keep, and treat the file as
83
+ destructive input. Values are escaped only for single quotes, not full binary-safe encoding, so for
84
+ authoritative or binary-heavy backups prefer `mysqldump`.
85
+
86
+ ## Usage
87
+
88
+ Register the server with your MCP client. A typical MCP client configuration entry looks like:
89
+
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "mokomysql": {
94
+ "command": "npx",
95
+ "args": ["-y", "@mokoconsulting/mokomysql-mcp"],
96
+ "env": {
97
+ "MYSQL_MCP_CONFIG": "/home/you/.mcp_mokomysql.json",
98
+ "MYSQL_MCP_STATE": "/home/you/.mcp_mokomysql.state.json"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ The `env` block is where the config and sidecar paths belong — server-instance settings, kept out
106
+ of any project repository (both are optional; see the [Configuration wiki](https://git.mokoconsulting.tech/MokoConsulting/mokomysql-mcp/wiki/Configuration)).
107
+ Once connected, the client can call the server's tools to query data, inspect schema, manage
108
+ users, run maintenance, and invoke the Joomla helpers.
109
+
110
+ ## Contributing
111
+
112
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) and follow the
113
+ [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home) for
114
+ coding style, commit conventions, and the pull request process.
115
+
116
+ ## License
117
+
118
+ Licensed under GPL-3.0-or-later — see [LICENSE](LICENSE).
119
+
120
+ ---
121
+
122
+ *[Moko Consulting](https://mokoconsulting.tech)*
@@ -0,0 +1,27 @@
1
+ {
2
+ "_comment": "No-inline-secrets policy (MokoCLI #1043): every password must be a file-backed ref, 'file:~/.ssh/tokens/<name>.token'. The referenced file holds the RAW password (no JSON, no trailing newline). An inline 'password' literal still works but is auto-migrated to a token file on first run (config rewritten, original kept at .bak). Legacy inline form, deprecated: \"password\": \"<raw-password>\".",
3
+ "defaultConnection": "local",
4
+ "connections": {
5
+ "local": {
6
+ "host": "127.0.0.1",
7
+ "port": 3306,
8
+ "user": "root",
9
+ "password": "file:~/.ssh/tokens/mysql-local-password.token",
10
+ "database": "mysql",
11
+ "ssl": false,
12
+ "timezone": "Z",
13
+ "tags": ["localhost", "dev-db"]
14
+ },
15
+ "joomla-site": {
16
+ "host": "db.example.com",
17
+ "port": 3306,
18
+ "user": "joomla",
19
+ "password": "file:~/.ssh/tokens/JOOMLA.db.token",
20
+ "database": "joomla_prod",
21
+ "ssl": true,
22
+ "joomla": true,
23
+ "joomlaPrefix": "vkw4n_",
24
+ "tags": ["prod"]
25
+ }
26
+ }
27
+ }
package/dist/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # dist/
2
+
3
+ Distributable artifacts live here — the packaged installer(s) and release
4
+ bundles emitted by the **mokocli-centric build system** (mokocli clones and runs
5
+ the shared build tooling in CI). Generated output, not source.
6
+
7
+ Only this `README.md` is tracked; everything else under `dist/` is git-ignored.
@@ -0,0 +1,49 @@
1
+ import type { FieldPacket } from 'mysql2/promise';
2
+ import type { MySqlConfig } from './types.js';
3
+ /** Result of probing a (connection, database) pair for Joomla-ness. */
4
+ export interface JoomlaDetection {
5
+ /** Whether this target is treated as a Joomla database. */
6
+ isJoomla: boolean;
7
+ /** The live table prefix (e.g. "jos_", "vkw4n_"), when known. */
8
+ prefix: string | null;
9
+ /** How the verdict was reached — for surfacing in warnings. */
10
+ source: 'config' | 'marker' | 'auto' | 'none';
11
+ }
12
+ export declare class MysqlClient {
13
+ private pools;
14
+ private config;
15
+ /** Memoized Joomla verdicts, keyed by `${connectionKey}::${schema}`. */
16
+ private joomlaCache;
17
+ constructor(config: MySqlConfig);
18
+ /**
19
+ * Resolve the canonical identity of a target for binding/keying: the config
20
+ * connection key and the effective schema (explicit database or the connection
21
+ * default). Keeps callers consistent with how detection and markers are keyed.
22
+ */
23
+ resolveIdentity(connectionName?: string, database?: string): {
24
+ connKey: string;
25
+ schema: string;
26
+ };
27
+ /**
28
+ * Determine whether a target is a Joomla database, so writes can be gated.
29
+ * Resolution order: in-memory cache → explicit per-connection `joomla` flag
30
+ * (authoritative) → persisted sidecar marker (learned on a prior connect) →
31
+ * live schema probe for the Joomla signature (`<prefix>extensions` paired with
32
+ * `<prefix>assets`). A fresh probe result is persisted as a marker so future
33
+ * connects skip the round-trip entirely.
34
+ */
35
+ detectJoomla(connectionName?: string, database?: string): Promise<JoomlaDetection>;
36
+ private cache;
37
+ private poolFor;
38
+ query(sql: string, params?: unknown[], connectionName?: string, database?: string): Promise<{
39
+ rows: Record<string, unknown>[];
40
+ fields: FieldPacket[];
41
+ }>;
42
+ execute(sql: string, params?: unknown[], connectionName?: string, database?: string): Promise<{
43
+ affectedRows: number;
44
+ insertId: number;
45
+ changedRows: number;
46
+ }>;
47
+ closeAll(): Promise<void>;
48
+ }
49
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../source/client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAqB,WAAW,EAAmB,MAAM,gBAAgB,CAAC;AAGtF,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AAE/D,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC/B,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,+DAA+D;IAC/D,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9C;AAED,qBAAa,WAAW;IACvB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,MAAM,CAAc;IAC5B,wEAAwE;IACxE,OAAO,CAAC,WAAW,CAA2C;gBAElD,MAAM,EAAE,WAAW;IAI/B;;;;OAIG;IACH,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAKhG;;;;;;;OAOG;IACG,YAAY,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAqDxF,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,OAAO;IAoCT,KAAK,CACV,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAiBhE,OAAO,CACZ,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAuBrE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/B"}
package/dist/client.js ADDED
@@ -0,0 +1,180 @@
1
+ /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
2
+ *
3
+ * This file is part of a Moko Consulting project.
4
+ *
5
+ * SPDX-License-Identifier: GPL-3.0-or-later
6
+ *
7
+ * FILE INFORMATION
8
+ * DEFGROUP: mokomysql.Client
9
+ * INGROUP: mokomysql
10
+ * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokomysql-mcp
11
+ * PATH: /src/client.ts
12
+ * VERSION: 01.00.00
13
+ * BRIEF: MySQL client with connection pool management
14
+ */
15
+ import mysql from 'mysql2/promise';
16
+ import { getConnection } from './config.js';
17
+ import { getMarker, markerKey, setMarker } from './state.js';
18
+ export class MysqlClient {
19
+ pools = new Map();
20
+ config;
21
+ /** Memoized Joomla verdicts, keyed by `${connectionKey}::${schema}`. */
22
+ joomlaCache = new Map();
23
+ constructor(config) {
24
+ this.config = config;
25
+ }
26
+ /**
27
+ * Resolve the canonical identity of a target for binding/keying: the config
28
+ * connection key and the effective schema (explicit database or the connection
29
+ * default). Keeps callers consistent with how detection and markers are keyed.
30
+ */
31
+ resolveIdentity(connectionName, database) {
32
+ const { key, conn } = getConnection(this.config, connectionName);
33
+ return { connKey: key, schema: database ?? conn.database ?? '' };
34
+ }
35
+ /**
36
+ * Determine whether a target is a Joomla database, so writes can be gated.
37
+ * Resolution order: in-memory cache → explicit per-connection `joomla` flag
38
+ * (authoritative) → persisted sidecar marker (learned on a prior connect) →
39
+ * live schema probe for the Joomla signature (`<prefix>extensions` paired with
40
+ * `<prefix>assets`). A fresh probe result is persisted as a marker so future
41
+ * connects skip the round-trip entirely.
42
+ */
43
+ async detectJoomla(connectionName, database) {
44
+ const { key, conn } = getConnection(this.config, connectionName);
45
+ const schema = database ?? conn.database ?? '';
46
+ const cacheKey = `${key}::${schema}`;
47
+ const cached = this.joomlaCache.get(cacheKey);
48
+ if (cached)
49
+ return cached;
50
+ // Explicit config flag is authoritative — no probe, and it overrides any marker.
51
+ if (conn.joomla === true) {
52
+ return this.cache(cacheKey, { isJoomla: true, prefix: conn.joomlaPrefix ?? null, source: 'config' });
53
+ }
54
+ if (conn.joomla === false) {
55
+ return this.cache(cacheKey, { isJoomla: false, prefix: null, source: 'config' });
56
+ }
57
+ // Without a resolvable target schema we cannot probe or key a marker.
58
+ if (!schema) {
59
+ return this.cache(cacheKey, { isJoomla: false, prefix: null, source: 'none' });
60
+ }
61
+ // Learned marker from a previous connect — instant, no round-trip.
62
+ const mKey = markerKey(conn.host, conn.port ?? 3306, schema);
63
+ const marker = await getMarker(mKey);
64
+ if (marker) {
65
+ return this.cache(cacheKey, { isJoomla: marker.joomla, prefix: marker.prefix, source: 'marker' });
66
+ }
67
+ try {
68
+ const { rows } = await this.query("SELECT TABLE_NAME AS name FROM information_schema.TABLES " +
69
+ "WHERE TABLE_SCHEMA = ? AND TABLE_NAME REGEXP '(extensions|assets)$'", [schema], connectionName);
70
+ const names = new Set(rows.map((r) => String(r.name)));
71
+ let prefix = null;
72
+ for (const name of names) {
73
+ if (!name.endsWith('extensions'))
74
+ continue;
75
+ const candidate = name.slice(0, -'extensions'.length);
76
+ if (names.has(`${candidate}assets`)) {
77
+ prefix = candidate;
78
+ break;
79
+ }
80
+ }
81
+ const verdict = prefix !== null
82
+ ? { isJoomla: true, prefix, source: 'auto' }
83
+ : { isJoomla: false, prefix: null, source: 'auto' };
84
+ // Persist what we learned so the next connect just knows.
85
+ await setMarker(mKey, { joomla: verdict.isJoomla, prefix: verdict.prefix, detectedAt: new Date().toISOString() });
86
+ return this.cache(cacheKey, verdict);
87
+ }
88
+ catch {
89
+ // Probe failed (permissions, missing schema). Degrade to "none" and do
90
+ // not cache or persist, so a later successful probe can still classify it.
91
+ return { isJoomla: false, prefix: null, source: 'none' };
92
+ }
93
+ }
94
+ cache(cacheKey, verdict) {
95
+ this.joomlaCache.set(cacheKey, verdict);
96
+ return verdict;
97
+ }
98
+ poolFor(connectionName) {
99
+ const { key, conn } = getConnection(this.config, connectionName);
100
+ let pool = this.pools.get(key);
101
+ if (!pool) {
102
+ const opts = {
103
+ host: conn.host,
104
+ port: conn.port ?? 3306,
105
+ user: conn.user,
106
+ password: conn.password,
107
+ database: conn.database,
108
+ connectionLimit: 5,
109
+ waitForConnections: true,
110
+ timezone: conn.timezone ?? 'Z',
111
+ multipleStatements: false,
112
+ };
113
+ if (conn.ssl) {
114
+ // Default to verified TLS. A bare `ssl: true` is never silently
115
+ // downgraded — callers who must skip verification (trusted internal
116
+ // hosts with self-signed certs) opt out explicitly via
117
+ // `ssl: { rejectUnauthorized: false }` in their config.
118
+ opts.ssl = typeof conn.ssl === 'object'
119
+ ? conn.ssl
120
+ : { rejectUnauthorized: true };
121
+ }
122
+ pool = mysql.createPool(opts);
123
+ this.pools.set(key, pool);
124
+ // On first connect, learn (and persist) the Joomla verdict for the
125
+ // connection's default database so the write-gate knows immediately.
126
+ // Best-effort and non-blocking — never let it break pool creation.
127
+ if (conn.database) {
128
+ void this.detectJoomla(connectionName, conn.database).catch(() => undefined);
129
+ }
130
+ }
131
+ return pool;
132
+ }
133
+ async query(sql, params, connectionName, database) {
134
+ const pool = this.poolFor(connectionName);
135
+ const p = (params ?? []);
136
+ if (database) {
137
+ const conn = await pool.getConnection();
138
+ try {
139
+ await conn.query(`USE \`${database.replace(/`/g, '``')}\``);
140
+ const [rows, fields] = await conn.query(sql, p);
141
+ return { rows: rows, fields };
142
+ }
143
+ finally {
144
+ conn.release();
145
+ }
146
+ }
147
+ const [rows, fields] = await pool.query(sql, p);
148
+ return { rows: rows, fields };
149
+ }
150
+ async execute(sql, params, connectionName, database) {
151
+ const pool = this.poolFor(connectionName);
152
+ const p = (params ?? []);
153
+ if (database) {
154
+ const conn = await pool.getConnection();
155
+ try {
156
+ await conn.query(`USE \`${database.replace(/`/g, '``')}\``);
157
+ const [result] = await conn.execute(sql, p);
158
+ const r = result;
159
+ return { affectedRows: r.affectedRows ?? 0, insertId: r.insertId ?? 0, changedRows: r.changedRows ?? 0 };
160
+ }
161
+ finally {
162
+ conn.release();
163
+ }
164
+ }
165
+ const [result] = await pool.execute(sql, p);
166
+ const r = result;
167
+ return {
168
+ affectedRows: r.affectedRows ?? 0,
169
+ insertId: r.insertId ?? 0,
170
+ changedRows: r.changedRows ?? 0,
171
+ };
172
+ }
173
+ async closeAll() {
174
+ for (const [, pool] of this.pools) {
175
+ await pool.end();
176
+ }
177
+ this.pools.clear();
178
+ }
179
+ }
180
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../source/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { MySqlConfig, MySqlConnection } from './types.js';
2
+ /** Absolute path to the active config file (`MYSQL_MCP_CONFIG` or ~/.mcp_mokomysql.json). */
3
+ export declare function getConfigPath(): string;
4
+ /**
5
+ * Absolute path to the sidecar state file — the MCP-managed learned-marker store.
6
+ * `MYSQL_MCP_STATE` overrides it outright; otherwise it sits beside the config as
7
+ * `<config>.state.json`, so learned state always follows the config that produced it.
8
+ */
9
+ export declare function getStatePath(): string;
10
+ export declare function loadConfig(): Promise<MySqlConfig>;
11
+ /**
12
+ * Normalize a name for tag matching: lowercase and strip every character
13
+ * that isn't a letter or digit. This makes "moko.live", "moko-live",
14
+ * "Moko Live" and "mokolive" all collapse to the same key.
15
+ */
16
+ export declare function normalizeTag(value: string): string;
17
+ export declare function getConnection(config: MySqlConfig, name?: string): {
18
+ key: string;
19
+ conn: MySqlConnection;
20
+ };
21
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../source/config.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM/D,6FAA6F;AAC7F,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,CA+BvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAoBxG"}
package/dist/config.js ADDED
@@ -0,0 +1,92 @@
1
+ /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
2
+ *
3
+ * This file is part of a Moko Consulting project.
4
+ *
5
+ * SPDX-License-Identifier: GPL-3.0-or-later
6
+ *
7
+ * FILE INFORMATION
8
+ * DEFGROUP: mokomysql.Config
9
+ * INGROUP: mokomysql
10
+ * REPO: https://git.mokoconsulting.tech/MokoConsulting/mokomysql-mcp
11
+ * PATH: /src/config.ts
12
+ * VERSION: 01.00.00
13
+ * BRIEF: Configuration loader for MySQL MCP connections
14
+ */
15
+ import { readFile } from 'node:fs/promises';
16
+ import { resolve } from 'node:path';
17
+ import { homedir } from 'node:os';
18
+ import { resolveSecretRefs } from './secrets.js';
19
+ import { migrateInlineSecrets } from './migrate.js';
20
+ const CONFIG_FILENAME = '.mcp_mokomysql.json';
21
+ /** Absolute path to the active config file (`MYSQL_MCP_CONFIG` or ~/.mcp_mokomysql.json). */
22
+ export function getConfigPath() {
23
+ return process.env.MYSQL_MCP_CONFIG
24
+ ? resolve(process.env.MYSQL_MCP_CONFIG)
25
+ : resolve(homedir(), CONFIG_FILENAME);
26
+ }
27
+ /**
28
+ * Absolute path to the sidecar state file — the MCP-managed learned-marker store.
29
+ * `MYSQL_MCP_STATE` overrides it outright; otherwise it sits beside the config as
30
+ * `<config>.state.json`, so learned state always follows the config that produced it.
31
+ */
32
+ export function getStatePath() {
33
+ if (process.env.MYSQL_MCP_STATE)
34
+ return resolve(process.env.MYSQL_MCP_STATE);
35
+ return getConfigPath().replace(/\.json$/i, '') + '.state.json';
36
+ }
37
+ export async function loadConfig() {
38
+ const config_path = getConfigPath();
39
+ try {
40
+ const raw = await readFile(config_path, 'utf-8');
41
+ const parsed = JSON.parse(raw);
42
+ // Self-heal: migrate any INLINE secret (no-inline-secrets policy) to a
43
+ // file-backed ref and rewrite the config. Warn-only on failure — never
44
+ // crashes, never loses the credential. Runs before resolveSecretRefs so
45
+ // the freshly written "file:" refs are resolved below.
46
+ await migrateInlineSecrets(parsed, config_path);
47
+ // Resolve any "file:<path>" secret references (e.g. passwords in ~/.ssh/tokens).
48
+ await resolveSecretRefs(parsed);
49
+ if (!parsed.connections || Object.keys(parsed.connections).length === 0) {
50
+ throw new Error('No connections defined in config');
51
+ }
52
+ return {
53
+ connections: parsed.connections,
54
+ defaultConnection: parsed.defaultConnection ?? Object.keys(parsed.connections)[0],
55
+ };
56
+ }
57
+ catch (err) {
58
+ const message = err instanceof Error ? err.message : String(err);
59
+ throw new Error(`Failed to load config from ${config_path}: ${message}\n` +
60
+ `Create ${config_path} — see config.example.json for format.`);
61
+ }
62
+ }
63
+ /**
64
+ * Normalize a name for tag matching: lowercase and strip every character
65
+ * that isn't a letter or digit. This makes "moko.live", "moko-live",
66
+ * "Moko Live" and "mokolive" all collapse to the same key.
67
+ */
68
+ export function normalizeTag(value) {
69
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, '');
70
+ }
71
+ export function getConnection(config, name) {
72
+ const requested = name ?? config.defaultConnection;
73
+ // 1. Exact key match — fast path, preserves prior behavior exactly.
74
+ const direct = config.connections[requested];
75
+ if (direct)
76
+ return { key: requested, conn: direct };
77
+ // 2. Normalized match against connection keys and their tag shortcuts.
78
+ // Returns the canonical key, never the alias/tag the caller typed.
79
+ const target = normalizeTag(requested);
80
+ for (const [key, conn] of Object.entries(config.connections)) {
81
+ if (normalizeTag(key) === target)
82
+ return { key, conn };
83
+ if (conn.tags?.some((tag) => normalizeTag(tag) === target))
84
+ return { key, conn };
85
+ }
86
+ // 3. Not found — list keys plus their tags so the caller can self-correct.
87
+ const available = Object.entries(config.connections)
88
+ .map(([key, conn]) => (conn.tags?.length ? `${key} [${conn.tags.join(', ')}]` : key))
89
+ .join(', ');
90
+ throw new Error(`Connection "${requested}" not found. Available: ${available}`);
91
+ }
92
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../source/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { MysqlClient } from './client.js';
3
+ import type { MySqlConfig } from './types.js';
4
+ export declare let config: MySqlConfig;
5
+ export declare let client: MysqlClient;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";AAqBA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,IAAI,MAAM,EAAE,WAAW,CAAC;AAC/B,eAAO,IAAI,MAAM,EAAE,WAAW,CAAC"}