Skip to main content
Glama
EvilPhatBoi

MSSQL MCP Server

by EvilPhatBoi

insert_data

Adds single or multiple records to MSSQL database tables using SQL INSERT statements with proper formatting for data types and column structures.

Instructions

Inserts data into an MSSQL Database table. Supports both single record insertion and multiple record insertion using standard SQL INSERT with VALUES clause. FORMAT EXAMPLES: Single Record Insert: { "tableName": "Users", "data": { "name": "John Doe", "email": "john@example.com", "age": 30, "isActive": true, "createdDate": "2023-01-15" } } Multiple Records Insert: { "tableName": "Users", "data": [ { "name": "John Doe", "email": "john@example.com", "age": 30, "isActive": true, "createdDate": "2023-01-15" }, { "name": "Jane Smith", "email": "jane@example.com", "age": 25, "isActive": false, "createdDate": "2023-01-16" } ] } GENERATED SQL FORMAT:

  • Single: INSERT INTO table (col1, col2) VALUES (@param1, @param2)

  • Multiple: INSERT INTO table (col1, col2) VALUES (@param1, @param2), (@param3, @param4), ... IMPORTANT RULES:

  • For single record: Use a single object for the 'data' field

  • For multiple records: Use an array of objects for the 'data' field

  • All objects in array must have identical column names

  • Column names must match the actual database table columns exactly

  • Values should match the expected data types (string, number, boolean, date)

  • Use proper date format for date columns (YYYY-MM-DD or ISO format)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tableNameYesName of the table to insert data into
dataYes

Implementation Reference

  • The main execution logic for the 'insert_data' tool. Handles both single and multiple record insertions into an MSSQL table using parameterized queries.
    async run(params: any) {
      try {
        const { tableName, data } = params;
        // Check if data is an array (multiple records) or single object
        const isMultipleRecords = Array.isArray(data);
        const records = isMultipleRecords ? data : [data];
        if (records.length === 0) {
          return {
            success: false,
            message: "No data provided for insertion",
          };
        }
        // Validate that all records have the same columns
        const firstRecordColumns = Object.keys(records[0]).sort();
        for (let i = 1; i < records.length; i++) {
          const currentColumns = Object.keys(records[i]).sort();
          if (JSON.stringify(firstRecordColumns) !== JSON.stringify(currentColumns)) {
            return {
              success: false,
              message: `Column mismatch: Record ${i + 1} has different columns than the first record. Expected columns: [${firstRecordColumns.join(', ')}], but got: [${currentColumns.join(', ')}]`,
            };
          }
        }
        const columns = firstRecordColumns.join(", ");
        const request = new sql.Request();
        if (isMultipleRecords) {
          // Multiple records insert using VALUES clause - works for 1 or more records
          const valueClauses: string[] = [];
          records.forEach((record, recordIndex) => {
            const valueParams = firstRecordColumns
              .map((column, columnIndex) => `@value${recordIndex}_${columnIndex}`)
              .join(", ");
            valueClauses.push(`(${valueParams})`);
            // Add parameters for this record
            firstRecordColumns.forEach((column, columnIndex) => {
              request.input(`value${recordIndex}_${columnIndex}`, record[column]);
            });
          });
          const query = `INSERT INTO ${tableName} (${columns}) VALUES ${valueClauses.join(", ")}`;
          await request.query(query);
          return {
            success: true,
            message: `Successfully inserted ${records.length} record${records.length > 1 ? 's' : ''} into ${tableName}`,
            recordsInserted: records.length,
          };
        } else {
          // Single record insert (when data is passed as single object)
          const values = firstRecordColumns
            .map((column, index) => `@value${index}`)
            .join(", ");
          firstRecordColumns.forEach((column, index) => {
            request.input(`value${index}`, records[0][column]);
          });
          const query = `INSERT INTO ${tableName} (${columns}) VALUES (${values})`;
          await request.query(query);
          return {
            success: true,
            message: `Successfully inserted 1 record into ${tableName}`,
            recordsInserted: 1,
          };
        }
      } catch (error) {
        console.error("Error inserting data:", error);
        return {
          success: false,
          message: `Failed to insert data: ${error}`,
        };
      }
    }
  • Input schema definition for the 'insert_data' tool, specifying required 'tableName' and 'data' fields supporting single object or array of objects.
    inputSchema = {
      type: "object",
      properties: {
        tableName: { 
          type: "string", 
          description: "Name of the table to insert data into" 
        },
        data: { 
          oneOf: [
            { 
              type: "object", 
              description: "Single record data object with column names as keys and values as the data to insert. Example: {\"name\": \"John\", \"age\": 30}" 
            },
            { 
              type: "array", 
              items: { type: "object" },
              description: "Array of data objects for multiple record insertion. Each object must have identical column structure. Example: [{\"name\": \"John\", \"age\": 30}, {\"name\": \"Jane\", \"age\": 25}]" 
            }
          ]
        },
      },
      required: ["tableName", "data"],
    } as any;
  • src/index.ts:109-113 (registration)
    Registers 'insertDataTool' in the list of available tools for the ListToolsRequestHandler (non-readonly mode).
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: isReadOnly
        ? [listTableTool, readDataTool, describeTableTool] // todo: add searchDataTool to the list of tools available in readonly mode once implemented
        : [insertDataTool, readDataTool, describeTableTool, updateDataTool, createTableTool, createIndexTool, dropTableTool, listTableTool], // add all new tools here
    }));
  • src/index.ts:120-121 (registration)
    Registers the handler call for 'insert_data' tool in the CallToolRequestHandler switch statement.
    case insertDataTool.name:
      result = await insertDataTool.run(args);
  • src/index.ts:84-84 (registration)
    Instantiates the InsertDataTool instance used throughout the server.
    const insertDataTool = new InsertDataTool();
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: it performs write operations (implied by 'inserts'), supports single/multiple records, generates SQL INSERT statements, and includes important rules (e.g., column name matching, data type requirements, date formats). However, it lacks details on permissions, error handling, or transaction behavior, preventing a perfect score.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately structured with clear sections (purpose, format examples, generated SQL format, important rules) and front-loaded key information. While detailed, each sentence adds value (e.g., examples illustrate usage, rules prevent errors). Minor verbosity in repeating examples slightly reduces efficiency, but overall it's well-organized and purposeful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (write operation, variable data structures), no annotations, no output schema, and 2 parameters with partial schema coverage, the description is largely complete. It covers purpose, usage examples, SQL behavior, and critical constraints. However, it misses some context like expected return values (e.g., success confirmation or inserted IDs), error scenarios, or performance considerations, keeping it from a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50% (only tableName has a description in schema), but the description compensates well by adding rich semantics: it explains the 'data' parameter's structure for single vs. multiple records with detailed examples, clarifies column name and data type requirements, and provides format rules. This goes significantly beyond the schema, though it doesn't fully document all edge cases (e.g., handling nulls).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'inserts data into an MSSQL Database table' with specific verbs ('inserts') and resources ('MSSQL Database table'), distinguishing it from sibling tools like read_data, update_data, create_table, etc. It explicitly mentions support for both single and multiple record insertion, making the purpose highly specific and differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage through format examples and rules (e.g., 'Use a single object for the 'data' field' for single records), but does not explicitly state when to use this tool versus alternatives like update_data or create_table. No guidance on prerequisites (e.g., table must exist) or exclusions is provided, leaving usage context partially implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EvilPhatBoi/McpSqlServer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server