@tejasanik/postgres-mcp-server 2.2.1 → 2.3.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 +72 -13
- package/dist/db-manager.js +157 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -150,12 +150,15 @@ export POSTGRES_SERVERS='{
|
|
|
150
150
|
|
|
151
151
|
**Note:** If both formats are used, individual `PG_*` variables take precedence over `POSTGRES_SERVERS`.
|
|
152
152
|
|
|
153
|
-
####
|
|
153
|
+
#### Access Mode Configuration
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
Access modes control whether write operations are allowed. You can configure access at three levels with the following priority:
|
|
156
156
|
|
|
157
|
-
-
|
|
158
|
-
|
|
157
|
+
**Priority:** Database-level > Server-level > Global > default (full)
|
|
158
|
+
|
|
159
|
+
##### Global Access Mode (POSTGRES_ACCESS_MODE)
|
|
160
|
+
|
|
161
|
+
Sets the default access mode for all servers and databases:
|
|
159
162
|
|
|
160
163
|
```bash
|
|
161
164
|
# For read-only access (recommended for production)
|
|
@@ -165,6 +168,59 @@ export POSTGRES_ACCESS_MODE="readonly"
|
|
|
165
168
|
export POSTGRES_ACCESS_MODE="full"
|
|
166
169
|
```
|
|
167
170
|
|
|
171
|
+
**Supported values:**
|
|
172
|
+
- `full` / `rw` / `readwrite`: Full access - allows all SQL operations
|
|
173
|
+
- `readonly` / `ro` / `read-only`: Read-only mode - only SELECT and read operations allowed
|
|
174
|
+
|
|
175
|
+
##### Server-Level Access Mode (PG_ACCESS_MODE_*)
|
|
176
|
+
|
|
177
|
+
Override global access mode for specific servers:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Server 1: read-only (production)
|
|
181
|
+
export PG_ACCESS_MODE_1="readonly"
|
|
182
|
+
|
|
183
|
+
# Server 2: full access (development)
|
|
184
|
+
export PG_ACCESS_MODE_DEV="full"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
##### Database-Level Access Mode (PG_DB_ACCESS_MODES_*)
|
|
188
|
+
|
|
189
|
+
Override server access mode for specific databases. Format: `dbname:mode,dbname:mode`
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# For server 1: production db is readonly, analytics has full access
|
|
193
|
+
export PG_DB_ACCESS_MODES_1="production:readonly,analytics:full,staging:rw"
|
|
194
|
+
|
|
195
|
+
# For server PROD: specific database overrides
|
|
196
|
+
export PG_DB_ACCESS_MODES_PROD="users_db:ro,logs:readonly,dev_db:full"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
##### JSON Configuration (POSTGRES_SERVERS)
|
|
200
|
+
|
|
201
|
+
Access modes can also be configured in the JSON format:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"production": {
|
|
206
|
+
"host": "prod.example.com",
|
|
207
|
+
"username": "user",
|
|
208
|
+
"password": "pass",
|
|
209
|
+
"accessMode": "readonly",
|
|
210
|
+
"databaseAccessModes": {
|
|
211
|
+
"analytics": "full",
|
|
212
|
+
"reporting": "readonly"
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"development": {
|
|
216
|
+
"host": "dev.example.com",
|
|
217
|
+
"username": "user",
|
|
218
|
+
"password": "pass",
|
|
219
|
+
"accessMode": "full"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
168
224
|
### Claude Desktop Configuration
|
|
169
225
|
|
|
170
226
|
Add the server to your Claude Desktop MCP configuration (`claude_desktop_config.json`):
|
|
@@ -176,15 +232,16 @@ Add the server to your Claude Desktop MCP configuration (`claude_desktop_config.
|
|
|
176
232
|
"command": "npx",
|
|
177
233
|
"args": ["@tejasanik/postgres-mcp-server"],
|
|
178
234
|
"env": {
|
|
179
|
-
"PG_NAME_1": "
|
|
180
|
-
"PG_HOST_1": "
|
|
235
|
+
"PG_NAME_1": "prod",
|
|
236
|
+
"PG_HOST_1": "prod.example.com",
|
|
181
237
|
"PG_PORT_1": "5432",
|
|
182
238
|
"PG_USERNAME_1": "user",
|
|
183
239
|
"PG_PASSWORD_1": "pass",
|
|
184
240
|
"PG_DATABASE_1": "mydb",
|
|
185
241
|
"PG_SSL_1": "true",
|
|
186
242
|
"PG_DEFAULT_1": "true",
|
|
187
|
-
"
|
|
243
|
+
"PG_ACCESS_MODE_1": "readonly",
|
|
244
|
+
"PG_DB_ACCESS_MODES_1": "analytics:full,staging:rw"
|
|
188
245
|
}
|
|
189
246
|
}
|
|
190
247
|
}
|
|
@@ -200,20 +257,22 @@ claude mcp add-json postgres_dbs --scope user '{
|
|
|
200
257
|
"command": "npx",
|
|
201
258
|
"args": ["-y","@tejasanik/postgres-mcp-server"],
|
|
202
259
|
"env": {
|
|
203
|
-
"PG_NAME_1": "
|
|
204
|
-
"PG_HOST_1": "
|
|
260
|
+
"PG_NAME_1": "prod",
|
|
261
|
+
"PG_HOST_1": "prod.example.com",
|
|
205
262
|
"PG_PORT_1": "5432",
|
|
206
263
|
"PG_USERNAME_1": "user",
|
|
207
264
|
"PG_PASSWORD_1": "pass",
|
|
208
265
|
"PG_DATABASE_1": "mydb",
|
|
209
266
|
"PG_SSL_1": "true",
|
|
210
267
|
"PG_DEFAULT_1": "true",
|
|
211
|
-
"
|
|
212
|
-
"
|
|
268
|
+
"PG_ACCESS_MODE_1": "readonly",
|
|
269
|
+
"PG_DB_ACCESS_MODES_1": "analytics:full",
|
|
270
|
+
"PG_NAME_2": "dev",
|
|
271
|
+
"PG_HOST_2": "dev.example.com",
|
|
213
272
|
"PG_USERNAME_2": "user",
|
|
214
273
|
"PG_PASSWORD_2": "pass",
|
|
215
274
|
"PG_SSL_2": "true",
|
|
216
|
-
"
|
|
275
|
+
"PG_ACCESS_MODE_2": "full"
|
|
217
276
|
}
|
|
218
277
|
}'
|
|
219
278
|
```
|
|
@@ -955,7 +1014,7 @@ When `execute_sql_file` or multi-statement execution encounters errors, line num
|
|
|
955
1014
|
|
|
956
1015
|
## Security
|
|
957
1016
|
|
|
958
|
-
- **Access Mode**: By default, the server runs in **full access mode**.
|
|
1017
|
+
- **Access Mode**: By default, the server runs in **full access mode**. Configure access at global (`POSTGRES_ACCESS_MODE`), server (`PG_ACCESS_MODE_*`), or database (`PG_DB_ACCESS_MODES_*`) levels. Database-level settings override server-level, which override global. Recommended: set production servers/databases to `readonly`.
|
|
959
1018
|
- **SQL Injection Protection**: All user inputs are validated and parameterized queries are used where possible.
|
|
960
1019
|
- **Query Timeout**: Default 30-second timeout prevents runaway queries.
|
|
961
1020
|
- **Credentials**: Managed via environment variables and never logged or exposed through the MCP interface.
|
package/dist/db-manager.js
CHANGED
|
@@ -36,12 +36,66 @@ function getSslConfig(ssl) {
|
|
|
36
36
|
return undefined;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Parses access mode from a string value.
|
|
40
|
+
* Accepts: 'readonly', 'read-only', 'ro' for readonly mode
|
|
41
|
+
* 'full', 'readwrite', 'read-write', 'rw' for full mode
|
|
42
|
+
* Returns undefined if the value is not a valid access mode.
|
|
43
|
+
*/
|
|
44
|
+
function parseAccessMode(value) {
|
|
45
|
+
if (!value)
|
|
46
|
+
return undefined;
|
|
47
|
+
const mode = value.toLowerCase().trim();
|
|
48
|
+
if (mode === "readonly" || mode === "read-only" || mode === "ro") {
|
|
49
|
+
return "readonly";
|
|
50
|
+
}
|
|
51
|
+
if (mode === "full" || mode === "readwrite" || mode === "read-write" || mode === "rw") {
|
|
52
|
+
return "full";
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parses database access modes from a comma-separated string.
|
|
58
|
+
* Format: "dbname:readonly,otherdb:full" or "mydb:ro,staging:rw"
|
|
59
|
+
* Supported mode values: readonly, read-only, ro, full, readwrite, read-write, rw
|
|
60
|
+
*/
|
|
61
|
+
function parseDatabaseAccessModes(value) {
|
|
62
|
+
if (!value)
|
|
63
|
+
return undefined;
|
|
64
|
+
const result = {};
|
|
65
|
+
const pairs = value.split(",");
|
|
66
|
+
for (const pair of pairs) {
|
|
67
|
+
const trimmed = pair.trim();
|
|
68
|
+
if (!trimmed)
|
|
69
|
+
continue;
|
|
70
|
+
const colonIndex = trimmed.lastIndexOf(":");
|
|
71
|
+
if (colonIndex === -1) {
|
|
72
|
+
console.error(`Warning: Invalid database access mode format '${trimmed}', expected 'dbname:mode'`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const dbName = trimmed.substring(0, colonIndex).trim();
|
|
76
|
+
const modeStr = trimmed.substring(colonIndex + 1).trim();
|
|
77
|
+
if (!dbName) {
|
|
78
|
+
console.error(`Warning: Empty database name in '${trimmed}'`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const parsedMode = parseAccessMode(modeStr);
|
|
82
|
+
if (parsedMode) {
|
|
83
|
+
result[dbName] = parsedMode;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.error(`Warning: Invalid access mode '${modeStr}' for database '${dbName}', ` +
|
|
87
|
+
`expected: readonly, ro, full, rw`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Determines the global access mode from environment variable.
|
|
40
94
|
* POSTGRES_ACCESS_MODE can be 'readonly' or 'full' (default).
|
|
41
95
|
*/
|
|
42
|
-
function
|
|
43
|
-
const mode = process.env.POSTGRES_ACCESS_MODE
|
|
44
|
-
return mode === "readonly"
|
|
96
|
+
function getGlobalAccessModeFromEnv() {
|
|
97
|
+
const mode = parseAccessMode(process.env.POSTGRES_ACCESS_MODE);
|
|
98
|
+
return mode === "readonly";
|
|
45
99
|
}
|
|
46
100
|
/**
|
|
47
101
|
* Parses SSL configuration from environment variable string.
|
|
@@ -77,7 +131,8 @@ function parseSslFromEnv(sslValue) {
|
|
|
77
131
|
/**
|
|
78
132
|
* Loads server configurations from individual PG_* environment variables.
|
|
79
133
|
* Pattern: PG_NAME_1, PG_HOST_1, PG_PORT_1, PG_USERNAME_1, PG_PASSWORD_1,
|
|
80
|
-
* PG_DATABASE_1, PG_SCHEMA_1, PG_SSL_1, PG_DEFAULT_1, PG_CONTEXT_1
|
|
134
|
+
* PG_DATABASE_1, PG_SCHEMA_1, PG_SSL_1, PG_DEFAULT_1, PG_CONTEXT_1,
|
|
135
|
+
* PG_ACCESS_MODE_1, PG_DB_ACCESS_MODES_1
|
|
81
136
|
*/
|
|
82
137
|
function loadServersFromEnvVars() {
|
|
83
138
|
const servers = {};
|
|
@@ -115,6 +170,8 @@ function loadServersFromEnvVars() {
|
|
|
115
170
|
isDefault: process.env[`PG_DEFAULT${suffix}`]?.toLowerCase() === "true",
|
|
116
171
|
ssl: parseSslFromEnv(process.env[`PG_SSL${suffix}`]),
|
|
117
172
|
context: process.env[`PG_CONTEXT${suffix}`],
|
|
173
|
+
accessMode: parseAccessMode(process.env[`PG_ACCESS_MODE${suffix}`]),
|
|
174
|
+
databaseAccessModes: parseDatabaseAccessModes(process.env[`PG_DB_ACCESS_MODES${suffix}`]),
|
|
118
175
|
};
|
|
119
176
|
servers[name] = config;
|
|
120
177
|
}
|
|
@@ -122,7 +179,7 @@ function loadServersFromEnvVars() {
|
|
|
122
179
|
}
|
|
123
180
|
/**
|
|
124
181
|
* Loads server configurations from POSTGRES_SERVERS JSON environment variable.
|
|
125
|
-
*
|
|
182
|
+
* Supports accessMode and databaseAccessModes for per-server and per-database access control.
|
|
126
183
|
*/
|
|
127
184
|
function loadServersFromJson() {
|
|
128
185
|
const configEnv = process.env.POSTGRES_SERVERS;
|
|
@@ -143,6 +200,45 @@ function loadServersFromJson() {
|
|
|
143
200
|
if (!serverConfig.host || typeof serverConfig.host !== "string") {
|
|
144
201
|
throw new Error(`Server '${name}' must have a valid 'host' string`);
|
|
145
202
|
}
|
|
203
|
+
// Validate accessMode if provided
|
|
204
|
+
if (serverConfig.accessMode !== undefined) {
|
|
205
|
+
const validModes = ["full", "readonly"];
|
|
206
|
+
if (!validModes.includes(serverConfig.accessMode)) {
|
|
207
|
+
console.error(`Warning: Invalid accessMode '${serverConfig.accessMode}' for server '${name}', ` +
|
|
208
|
+
`must be 'full' or 'readonly'. Using default.`);
|
|
209
|
+
delete serverConfig.accessMode;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Validate databaseAccessModes if provided
|
|
213
|
+
if (serverConfig.databaseAccessModes !== undefined) {
|
|
214
|
+
// Support both string format ("db:mode,db2:mode") and object format
|
|
215
|
+
if (typeof serverConfig.databaseAccessModes === "string") {
|
|
216
|
+
const parsed = parseDatabaseAccessModes(serverConfig.databaseAccessModes);
|
|
217
|
+
if (parsed) {
|
|
218
|
+
serverConfig.databaseAccessModes = parsed;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
delete serverConfig.databaseAccessModes;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const dbModes = serverConfig.databaseAccessModes;
|
|
226
|
+
if (typeof dbModes !== "object" || dbModes === null) {
|
|
227
|
+
console.error(`Warning: Invalid databaseAccessModes for server '${name}', must be an object or string. Ignoring.`);
|
|
228
|
+
delete serverConfig.databaseAccessModes;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
const validModes = ["full", "readonly"];
|
|
232
|
+
for (const [dbName, mode] of Object.entries(dbModes)) {
|
|
233
|
+
if (!validModes.includes(mode)) {
|
|
234
|
+
console.error(`Warning: Invalid accessMode '${mode}' for database '${dbName}' on server '${name}', ` +
|
|
235
|
+
`must be 'full' or 'readonly'. Ignoring.`);
|
|
236
|
+
delete dbModes[dbName];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
146
242
|
}
|
|
147
243
|
return parsed;
|
|
148
244
|
}
|
|
@@ -420,15 +516,16 @@ export class DatabaseManager {
|
|
|
420
516
|
}
|
|
421
517
|
getConnectionInfo() {
|
|
422
518
|
const currentServer = this.connectionState.currentServer;
|
|
519
|
+
const currentDatabase = this.connectionState.currentDatabase;
|
|
423
520
|
const serverConfig = currentServer
|
|
424
521
|
? this.serversConfig[currentServer]
|
|
425
522
|
: null;
|
|
426
523
|
return {
|
|
427
524
|
isConnected: this.isConnected(),
|
|
428
525
|
server: currentServer,
|
|
429
|
-
database:
|
|
526
|
+
database: currentDatabase,
|
|
430
527
|
schema: this.connectionState.currentSchema,
|
|
431
|
-
accessMode: this.
|
|
528
|
+
accessMode: this.getEffectiveAccessMode(currentServer, currentDatabase),
|
|
432
529
|
context: serverConfig?.context,
|
|
433
530
|
user: serverConfig?.username,
|
|
434
531
|
};
|
|
@@ -474,7 +571,7 @@ export class DatabaseManager {
|
|
|
474
571
|
throw new Error("SQL query is required and must be a string");
|
|
475
572
|
}
|
|
476
573
|
// Check for read-only mode violations using improved validation
|
|
477
|
-
if (this.
|
|
574
|
+
if (this.isReadOnlyFor()) {
|
|
478
575
|
const { isReadOnly, reason } = isReadOnlySql(sql);
|
|
479
576
|
if (!isReadOnly) {
|
|
480
577
|
throw new Error(`Read-only mode violation: ${reason}`);
|
|
@@ -761,8 +858,10 @@ export class DatabaseManager {
|
|
|
761
858
|
if (!sql || typeof sql !== "string") {
|
|
762
859
|
throw new Error("SQL query is required and must be a string");
|
|
763
860
|
}
|
|
764
|
-
// Check for read-only mode violations
|
|
765
|
-
|
|
861
|
+
// Check for read-only mode violations using the target server/database
|
|
862
|
+
const targetServer = override?.server ?? this.connectionState.currentServer;
|
|
863
|
+
const targetDatabase = override?.database ?? this.connectionState.currentDatabase;
|
|
864
|
+
if (this.isReadOnlyFor(targetServer, targetDatabase)) {
|
|
766
865
|
const { isReadOnly, reason } = isReadOnlySql(sql);
|
|
767
866
|
if (!isReadOnly) {
|
|
768
867
|
throw new Error(`Read-only mode violation: ${reason}`);
|
|
@@ -980,12 +1079,51 @@ export class DatabaseManager {
|
|
|
980
1079
|
}
|
|
981
1080
|
return false;
|
|
982
1081
|
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Returns whether global read-only mode is enabled.
|
|
1084
|
+
* For context-aware access mode, use getEffectiveAccessMode().
|
|
1085
|
+
*/
|
|
983
1086
|
isReadOnly() {
|
|
984
1087
|
return this.readOnlyMode;
|
|
985
1088
|
}
|
|
986
1089
|
setReadOnlyMode(readOnly) {
|
|
987
1090
|
this.readOnlyMode = readOnly;
|
|
988
1091
|
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Gets the effective access mode for a specific server/database combination.
|
|
1094
|
+
* Priority: Database-level > Server-level > Global env > default (full)
|
|
1095
|
+
*
|
|
1096
|
+
* @param serverName The server name (or null to use current server)
|
|
1097
|
+
* @param database The database name (or null to use current database)
|
|
1098
|
+
* @returns The effective access mode ('full' or 'readonly')
|
|
1099
|
+
*/
|
|
1100
|
+
getEffectiveAccessMode(serverName, database) {
|
|
1101
|
+
const server = serverName ?? this.connectionState.currentServer;
|
|
1102
|
+
const db = database ?? this.connectionState.currentDatabase;
|
|
1103
|
+
if (server) {
|
|
1104
|
+
const serverConfig = this.serversConfig[server];
|
|
1105
|
+
if (serverConfig) {
|
|
1106
|
+
// Check database-level access mode first
|
|
1107
|
+
if (db && serverConfig.databaseAccessModes?.[db]) {
|
|
1108
|
+
return serverConfig.databaseAccessModes[db];
|
|
1109
|
+
}
|
|
1110
|
+
// Fall back to server-level access mode
|
|
1111
|
+
if (serverConfig.accessMode) {
|
|
1112
|
+
return serverConfig.accessMode;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
// Fall back to global mode
|
|
1117
|
+
return this.readOnlyMode ? "readonly" : "full";
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Checks if access mode is read-only for a specific server/database combination.
|
|
1121
|
+
* @param serverName The server name (or null to use current server)
|
|
1122
|
+
* @param database The database name (or null to use current database)
|
|
1123
|
+
*/
|
|
1124
|
+
isReadOnlyFor(serverName, database) {
|
|
1125
|
+
return this.getEffectiveAccessMode(serverName, database) === "readonly";
|
|
1126
|
+
}
|
|
989
1127
|
setQueryTimeout(timeoutMs) {
|
|
990
1128
|
this.queryTimeoutMs = Math.min(Math.max(1000, timeoutMs), MAX_QUERY_TIMEOUT_MS);
|
|
991
1129
|
}
|
|
@@ -1067,8 +1205,8 @@ export class DatabaseManager {
|
|
|
1067
1205
|
if (!transaction) {
|
|
1068
1206
|
throw new Error(`Transaction not found: ${transactionId}`);
|
|
1069
1207
|
}
|
|
1070
|
-
// Check for read-only mode violations
|
|
1071
|
-
if (this.
|
|
1208
|
+
// Check for read-only mode violations using the transaction's server/database
|
|
1209
|
+
if (this.isReadOnlyFor(transaction.info.server, transaction.info.database)) {
|
|
1072
1210
|
const { isReadOnly, reason } = isReadOnlySql(sql);
|
|
1073
1211
|
if (!isReadOnly) {
|
|
1074
1212
|
throw new Error(`Read-only mode violation: ${reason}`);
|
|
@@ -1116,15 +1254,18 @@ export class DatabaseManager {
|
|
|
1116
1254
|
let dbManager = null;
|
|
1117
1255
|
/**
|
|
1118
1256
|
* Gets the singleton DatabaseManager instance.
|
|
1119
|
-
* The access mode is determined by the POSTGRES_ACCESS_MODE environment variable:
|
|
1257
|
+
* The global access mode is determined by the POSTGRES_ACCESS_MODE environment variable:
|
|
1120
1258
|
* - 'readonly', 'read-only', 'ro': Read-only mode (prevents write operations)
|
|
1121
1259
|
* - 'full' (default): Full access mode (allows all operations)
|
|
1260
|
+
*
|
|
1261
|
+
* Note: Server-level and database-level access modes can override the global setting.
|
|
1262
|
+
* Use PG_ACCESS_MODE_{suffix} for server-level and PG_DB_ACCESS_MODES_{suffix} for database-level.
|
|
1122
1263
|
*/
|
|
1123
1264
|
export function getDbManager() {
|
|
1124
1265
|
if (!dbManager) {
|
|
1125
|
-
const readOnlyMode =
|
|
1266
|
+
const readOnlyMode = getGlobalAccessModeFromEnv();
|
|
1126
1267
|
dbManager = new DatabaseManager(readOnlyMode);
|
|
1127
|
-
console.error(`PostgreSQL MCP:
|
|
1268
|
+
console.error(`PostgreSQL MCP: Global access mode = ${readOnlyMode ? "readonly" : "full"}`);
|
|
1128
1269
|
}
|
|
1129
1270
|
return dbManager;
|
|
1130
1271
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tejasanik/postgres-mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "A Model Context Protocol (MCP) server for PostgreSQL database management and analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lint": "eslint src --ignore-pattern '__tests__'",
|
|
17
17
|
"lint:fix": "eslint src --ignore-pattern '__tests__' --fix",
|
|
18
18
|
"prepare": "npm run build",
|
|
19
|
-
"prepublishOnly": "npm run build && npm test"
|
|
19
|
+
"prepublishOnly": "npm i && npm run build && npm test"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"mcp",
|