Skip to content

Commit 6c5f296

Browse files
committed
Allow different columns for ReadData and UpdateData
1 parent 058eacb commit 6c5f296

File tree

2 files changed

+51
-25
lines changed

2 files changed

+51
-25
lines changed

MssqlMcp/NodejsMcpServer/src/tools/ReadDataTool.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,42 @@ import { Tool } from "@modelcontextprotocol/sdk/types.js";
44
export class ReadDataTool implements Tool {
55
[key: string]: any;
66
name = "read_data";
7-
description = "Retrieves data from an MSSQL Database table by its ID";
7+
description = "Executes a SELECT query on an MSSQL Database table. The query must start with SELECT for security.";
88
inputSchema = {
99
type: "object",
1010
properties: {
11-
tableName: { type: "string", description: "Name of the table" },
12-
id: { type: "string", description: "ID of the data to retrieve" },
11+
query: {
12+
type: "string",
13+
description: "SQL SELECT query to execute (must start with SELECT). Example: SELECT * FROM movies WHERE genre = 'comedy'"
14+
},
1315
},
14-
required: ["tableName", "id"],
16+
required: ["query"],
1517
} as any;
1618

1719
async run(params: any) {
1820
try {
19-
const { tableName, id } = params;
21+
const { query } = params;
22+
23+
// Basic validation: ensure query starts with SELECT (case insensitive)
24+
const trimmedQuery = query.trim();
25+
if (!trimmedQuery.toUpperCase().startsWith('SELECT')) {
26+
throw new Error("Query must start with SELECT for security reasons");
27+
}
28+
2029
const request = new sql.Request();
21-
request.input("id", sql.VarChar, id);
22-
const query = `SELECT * FROM ${tableName} WHERE id = @id`;
23-
const result = await request.query(query);
30+
const result = await request.query(trimmedQuery);
31+
2432
return {
2533
success: true,
26-
message: `Data retrieved successfully`,
27-
data: result.recordset[0],
34+
message: `Query executed successfully. Retrieved ${result.recordset.length} record(s)`,
35+
data: result.recordset,
36+
recordCount: result.recordset.length,
2837
};
2938
} catch (error) {
30-
console.error("Error retrieving data:", error);
39+
console.error("Error executing query:", error);
3140
return {
3241
success: false,
33-
message: `Failed to retrieve data: ${error}`,
42+
message: `Failed to execute query: ${error}`,
3443
};
3544
}
3645
}

MssqlMcp/NodejsMcpServer/src/tools/UpdateDataTool.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,53 @@ import { Tool } from "@modelcontextprotocol/sdk/types.js";
44
export class UpdateDataTool implements Tool {
55
[key: string]: any;
66
name = "update_data";
7-
description = "Updates data in an MSSQL Database table by its ID";
7+
description = "Updates data in an MSSQL Database table using a WHERE clause. The WHERE clause must be provided for security.";
88
inputSchema = {
99
type: "object",
1010
properties: {
11-
tableName: { type: "string", description: "Name of the table" },
12-
id: { type: "string", description: "ID of the data to update" },
11+
tableName: {
12+
type: "string",
13+
description: "Name of the table to update"
14+
},
1315
updates: {
1416
type: "object",
15-
description: "Key-value pairs of columns to update",
17+
description: "Key-value pairs of columns to update. Example: { 'status': 'active', 'last_updated': '2025-01-01' }",
18+
},
19+
whereClause: {
20+
type: "string",
21+
description: "WHERE clause to identify which records to update. Example: \"genre = 'comedy' AND created_date <= '2025-07-05'\""
1622
},
1723
},
18-
required: ["tableName", "id", "updates"],
24+
required: ["tableName", "updates", "whereClause"],
1925
} as any;
2026

2127
async run(params: any) {
2228
try {
23-
const { tableName, id, updates } = params;
29+
const { tableName, updates, whereClause } = params;
30+
31+
// Basic validation: ensure whereClause is not empty
32+
if (!whereClause || whereClause.trim() === '') {
33+
throw new Error("WHERE clause is required for security reasons");
34+
}
35+
2436
const request = new sql.Request();
25-
request.input("id", sql.VarChar, id);
37+
38+
// Build SET clause with parameterized queries for security
2639
const setClause = Object.keys(updates)
27-
.map((key) => {
28-
request.input(key, updates[key]);
29-
return `${key} = @${key}`;
40+
.map((key, index) => {
41+
const paramName = `update_${index}`;
42+
request.input(paramName, updates[key]);
43+
return `[${key}] = @${paramName}`;
3044
})
3145
.join(", ");
32-
const query = `UPDATE ${tableName} SET ${setClause} WHERE id = @id`;
33-
await request.query(query);
46+
47+
const query = `UPDATE [${tableName}] SET ${setClause} WHERE ${whereClause}`;
48+
const result = await request.query(query);
49+
3450
return {
3551
success: true,
36-
message: `Data updated successfully`,
52+
message: `Update completed successfully. ${result.rowsAffected[0]} row(s) affected`,
53+
rowsAffected: result.rowsAffected[0],
3754
};
3855
} catch (error) {
3956
console.error("Error updating data:", error);

0 commit comments

Comments
 (0)