@apono-io/mcp-mysql 0.1.0 → 0.2.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/dist/__tests__/read-only.test.d.ts +2 -0
- package/dist/__tests__/read-only.test.d.ts.map +1 -0
- package/dist/__tests__/read-only.test.js +65 -0
- package/dist/__tests__/read-only.test.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +22 -8
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/read-only.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
const connection = {
|
|
3
|
+
query: vi.fn(),
|
|
4
|
+
release: vi.fn(),
|
|
5
|
+
};
|
|
6
|
+
const pool = {
|
|
7
|
+
getConnection: vi.fn(async () => connection),
|
|
8
|
+
query: vi.fn(),
|
|
9
|
+
};
|
|
10
|
+
vi.mock('../db.js', () => ({ getPool: () => pool }));
|
|
11
|
+
const { registerTools } = await import('../tools.js');
|
|
12
|
+
function collectTools() {
|
|
13
|
+
const handlers = new Map();
|
|
14
|
+
registerTools({
|
|
15
|
+
tool: (name, _description, _schema, handler) => {
|
|
16
|
+
handlers.set(name, handler);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
return handlers;
|
|
20
|
+
}
|
|
21
|
+
describe('read-only transaction', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
connection.query.mockReset();
|
|
24
|
+
connection.release.mockReset();
|
|
25
|
+
pool.getConnection.mockClear();
|
|
26
|
+
});
|
|
27
|
+
it('wraps query in a read-only transaction and commits', async () => {
|
|
28
|
+
connection.query.mockResolvedValue([[{ id: 1 }]]);
|
|
29
|
+
const result = await collectTools().get('query')({ database: 'apono', sql: 'SELECT 1' });
|
|
30
|
+
const issued = connection.query.mock.calls.map((call) => call[0]);
|
|
31
|
+
expect(issued[0]).toBe('START TRANSACTION READ ONLY');
|
|
32
|
+
expect(issued).toContain('SELECT 1');
|
|
33
|
+
expect(issued).toContain('COMMIT');
|
|
34
|
+
expect(result.isError).toBeUndefined();
|
|
35
|
+
expect(connection.release).toHaveBeenCalledOnce();
|
|
36
|
+
});
|
|
37
|
+
it('surfaces the database rejection when a write is attempted and rolls back', async () => {
|
|
38
|
+
connection.query.mockImplementation(async (sql) => {
|
|
39
|
+
if (sql === 'START TRANSACTION READ ONLY')
|
|
40
|
+
return [[]];
|
|
41
|
+
if (sql === 'ROLLBACK')
|
|
42
|
+
return [[]];
|
|
43
|
+
throw new Error('Cannot execute statement in a READ ONLY transaction');
|
|
44
|
+
});
|
|
45
|
+
const result = await collectTools().get('query')({ database: 'apono', sql: 'DELETE FROM users' });
|
|
46
|
+
expect(result.isError).toBe(true);
|
|
47
|
+
expect(result.content[0].text).toContain('READ ONLY transaction');
|
|
48
|
+
expect(connection.query.mock.calls.map((call) => call[0])).toContain('ROLLBACK');
|
|
49
|
+
expect(connection.release).toHaveBeenCalledOnce();
|
|
50
|
+
});
|
|
51
|
+
it('runs explain_query with analyze inside the read-only transaction', async () => {
|
|
52
|
+
connection.query.mockResolvedValue([[{ EXPLAIN: 'scan' }]]);
|
|
53
|
+
await collectTools().get('explain_query')({ database: 'apono', sql: 'SELECT 1', analyze: true });
|
|
54
|
+
const issued = connection.query.mock.calls.map((call) => call[0]);
|
|
55
|
+
expect(issued[0]).toBe('START TRANSACTION READ ONLY');
|
|
56
|
+
expect(issued).toContain('EXPLAIN ANALYZE SELECT 1');
|
|
57
|
+
});
|
|
58
|
+
it('leaves execute outside the read-only transaction', async () => {
|
|
59
|
+
pool.query.mockResolvedValue([{ affectedRows: 1 }]);
|
|
60
|
+
await collectTools().get('execute')({ database: 'apono', sql: 'DELETE FROM users' });
|
|
61
|
+
expect(pool.getConnection).not.toHaveBeenCalled();
|
|
62
|
+
expect(pool.query).toHaveBeenCalledWith('DELETE FROM users');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=read-only.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.test.js","sourceRoot":"","sources":["../../src/__tests__/read-only.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuCpE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuIrD"}
|
package/dist/tools.js
CHANGED
|
@@ -15,13 +15,29 @@ function formatRows(rows, emptyHint) {
|
|
|
15
15
|
}
|
|
16
16
|
return JSON.stringify(rows, null, 2);
|
|
17
17
|
}
|
|
18
|
+
// Runs sql inside a read-only transaction so MySQL itself rejects any write,
|
|
19
|
+
// including writes reached through EXPLAIN ANALYZE.
|
|
20
|
+
async function queryReadOnly(database, sql) {
|
|
21
|
+
const connection = await getPool(database).getConnection();
|
|
22
|
+
try {
|
|
23
|
+
await connection.query('START TRANSACTION READ ONLY');
|
|
24
|
+
const [rows] = await connection.query(sql);
|
|
25
|
+
await connection.query('COMMIT');
|
|
26
|
+
return rows;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
await connection.query('ROLLBACK').catch(() => undefined);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
connection.release();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
18
36
|
export function registerTools(server) {
|
|
19
|
-
server.tool('query', 'Execute a read-only SQL SELECT query and return results.', { database: z.string().describe('The database to query'), sql: z.string().describe('The SQL SELECT query to execute') }, async ({ database, sql }) => {
|
|
37
|
+
server.tool('query', 'Execute a read-only SQL SELECT query and return results. Runs in a read-only transaction, so any write is rejected by the database.', { database: z.string().describe('The database to query'), sql: z.string().describe('The SQL SELECT query to execute') }, async ({ database, sql }) => {
|
|
20
38
|
log(`Tool called: query on ${database}`);
|
|
21
39
|
try {
|
|
22
|
-
|
|
23
|
-
const [rows] = await pool.query(sql);
|
|
24
|
-
return textContent(formatRows(rows));
|
|
40
|
+
return textContent(formatRows(await queryReadOnly(database, sql)));
|
|
25
41
|
}
|
|
26
42
|
catch (err) {
|
|
27
43
|
return errorContent('query', err);
|
|
@@ -99,14 +115,12 @@ export function registerTools(server) {
|
|
|
99
115
|
server.tool('explain_query', 'Get the execution plan for a SQL query.', {
|
|
100
116
|
database: z.string().describe('The database to explain the query against'),
|
|
101
117
|
sql: z.string().describe('The SQL query to explain'),
|
|
102
|
-
analyze: z.boolean().default(false).describe('Whether to actually execute the query for real timing data'),
|
|
118
|
+
analyze: z.boolean().default(false).describe('Whether to actually execute the query for real timing data. Writes stay rejected because the plan runs in a read-only transaction.'),
|
|
103
119
|
}, async ({ database, sql, analyze }) => {
|
|
104
120
|
log(`Tool called: explain_query on ${database}`);
|
|
105
121
|
try {
|
|
106
|
-
const pool = getPool(database);
|
|
107
122
|
const explainSql = analyze ? `EXPLAIN ANALYZE ${sql}` : `EXPLAIN ${sql}`;
|
|
108
|
-
|
|
109
|
-
return textContent(formatRows(rows));
|
|
123
|
+
return textContent(formatRows(await queryReadOnly(database, explainSql)));
|
|
110
124
|
}
|
|
111
125
|
catch (err) {
|
|
112
126
|
return errorContent('explain_query', err);
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,GAAY;IAClD,GAAG,CAAC,YAAY,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;IAClC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAa,EAAE,CAAC;AACzG,CAAC;AAED,SAAS,UAAU,CAAC,IAA+B,EAAE,SAAkB;IACrE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,SAAS,IAAI,mBAAmB,CAAC;QAC9C,OAAO,GAAG,IAAI,0FAA0F,CAAC;IAC3G,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|