By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
World of SoftwareWorld of SoftwareWorld of Software
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Search
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
Reading: How to Build a Node.js MCP Server for Claude-Salesforce Integration | HackerNoon
Share
Sign In
Notification Show More
Font ResizerAa
World of SoftwareWorld of Software
Font ResizerAa
  • Software
  • Mobile
  • Computing
  • Gadget
  • Gaming
  • Videos
Search
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Have an existing account? Sign In
Follow US
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
World of Software > Computing > How to Build a Node.js MCP Server for Claude-Salesforce Integration | HackerNoon
Computing

How to Build a Node.js MCP Server for Claude-Salesforce Integration | HackerNoon

News Room
Last updated: 2025/06/17 at 11:38 PM
News Room Published 17 June 2025
Share
SHARE

This article will guide you through building a simple yet functional MCP server that integrates with Salesforce, enabling Claude Desktop to directly query and interact with your Salesforce data.

What are we going to build

We’ll create a Node.js-based MCP server that enables Claude to:

  • List all connected Salesforce organizations from your Salesforce CLI
  • Execute SOQL queries through natural language prompts
  • Retrieve and display Salesforce data in a conversational format

Full code for this project is available on GitHub.

What it looks like:

a short demoa short demo

What is MCP

MCP is a protocol developed by Anthropic that allows AI models to extend their capabilities by accessing external systems. In our case, it enables Claude to interact with Salesforce orgs, execute queries, and process data – all through simple conversation.

Let’s build it!

Prerequisites

Before proceeding with the article, make sure you have the following tools installed on your computer:

Also, it’s assumed you have a basic experience with LLMs, like ChatGPT, Gemini, Claude, etc.

Project setup

Create a folder for the project anywhere on your computer. Let’s name it, for example, sf-mcp-server. Open the folder in VS Code.

In VS Code open a terminal and initiate a new npm project by executing the following command:

npm init -y

Install the required dependencies:

npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript

Create a new folder called src inside the root of your project folder, which is the sf-cmp-server one.

Create a new file inside the src folder called index.ts, it should be inside this path ./src/index.ts.

Create a new file called tsconfig.json inside the root of your project folder and populate it with this code:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

There is the package.json file in the root of your project folder, adjust its content to make sure it contains the following code:

{
  "type": "module",
  "bin": {
    "sf-mcp-server": "./build/index.js"
  },
  "scripts": {
    "build": "tsc && chmod 755 build/index.js"
  },
  "files": ["build"]
}

Full code of this file is available in the GitHub repository.

By the end of this part your project folder should have the following structure:

.
├── node_modules
├── src/
│   └── index.ts
├── package-lock.json
├── package.json
└── tsconfig.json

The coding part

Let’s start with importing the packages we are going to use, and setting up the server. Add the following code in the top of the .src/index.ts file:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Importing exec from node:child_process to execute shell commands
import { exec } from "node:child_process"; 

const server = new McpServer({
    name: "sf-mcp-server",
    version: "1.0.0",
    capabilities: {
        tools: {},
    },
});

Now, let’s add some code for fetching the connected Salesforce Orgs. It’s better to create a connected app and set up an authentication flow if you’re planning to work with a single org, but we will use the connected orgs from the Salesforce CLI for simplicity.

Run the sf org list command in your terminal and check whether you have any connected orgs available. If not, then authorize an org which you can use going further.

This code tells the MCP server that you have a tool which can execute the sf org list --json command in shell and pass the result to Claude so it can understand what orgs you have authenticated to. Add this code below to the .src/index.ts file:

const listConnectedSalesforceOrgs = async () => {
    return new Promise((resolve, reject) => {
        exec("sf org list --json", (error, stdout, stderr) => {
            if (error) {
                return reject(error);
            }
            if (stderr) {
                return reject(new Error(stderr));
            }
            try {
                const result = JSON.parse(stdout);
                resolve(result);
            } catch (parseError) {
                reject(parseError);
            }
        });
    });
};

server.tool("list_connected_salesforce_orgs", {}, async () => {
    const orgList = await listConnectedSalesforceOrgs();
    return {
        content: [
            {
                type: "text",
                text: JSON.stringify(orgList, null, 2),
            },
        ],
    };
});

Great! The next step is to add the code for executing SOQL queries in one of the connected orgs.

This code accepts an input schema from the prompt you send to Claude in the Claude for Desktop app, parses it for the separate entities like targetOrg or fields to query and sends this information to the executeSoqlQuery function, which executes the sf command to query records using a SOQL query. After the later function finishes executing, its result is being sent to the Claude, which parses the result and responds to you in a pretty way in the chat.

Now add this code after the previously appended one:

const executeSoqlQuery = async (
    targetOrg: string,
    sObject: string,
    fields: string,
    where?: string,
    orderBy?: string,
    limit?: number
) => {
    let query = `SELECT ${fields} FROM ${sObject}`;

    if (where) query += " WHERE " + where;
    if (limit) query += " LIMIT " + limit;
    if (orderBy) query += " ORDER BY " + orderBy;

    const sfCommand = `sf data query --target-org ${targetOrg} --query "${query}" --json`;

    return new Promise((resolve, reject) => {
        exec(sfCommand, (error, stdout, stderr) => {
            if (error) {
                return reject(error);
            }
            if (stderr) {
                return reject(new Error(stderr));
            }
            try {
                const result = JSON.parse(stdout);
                resolve(result.result.records || []);
            } catch (parseError) {
                reject(parseError);
            }
        });
    });
};

server.tool(
    "query_records",
    "Execute a SOQL query in Salesforce Org",
    {
        input: z.object({
            targetOrg: z
                .string()
                .describe("Target Salesforce Org to execute the query against"),
            sObject: z.string().describe("Salesforce SObject to query from"),
            fields: z
                .string()
                .describe("Comma-separated list of fields to retrieve"),
            where: z
                .string()
                .optional()
                .describe("Optional WHERE clause for the query"),
            orderBy: z
                .string()
                .optional()
                .describe("Optional ORDER BY clause for the query"),
            limit: z
                .number()
                .optional()
                .describe("Optional limit for the number of records returned"),
        }),
    },
    async ({ input }) => {
        const { targetOrg, sObject, fields, where, orderBy, limit } = input;
        const result = await executeSoqlQuery(
            targetOrg,
            sObject,
            fields,
            where,
            orderBy,
            limit
        );

        return {
            content: [
                {
                    type: "text",
                    text: JSON.stringify(result, null, 2),
                },
            ],
        };
    }
);

We’re done with the code for basic functionality of this MCP server, now let’s add the code to initialize server and setup connection. Append this code to the end of the .src/index.ts file:

async function main() {
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.error("Salesforce MCP Server running on stdio");
}

main().catch((error) => {
    console.error("Fatal error in main():", error);
    process.exit(1);
});

The whole .src/index.ts file should look like this.

Making sure it works

Let’s start testing the MCP server by building our project, it’s an important step, don’t skip it. A build folder will be created inside the sf-cmp-server, along with the index.js file, which will be used by MCP server. Execute the following command in your terminal to perform the build:

npm run build

Now, the Claude for Desktop app should be configured to work with the MCP it’s going to be used as a client. In your computer, navigate to the path where the Claude’s config file is located. Create it if it’s not present.

For MacOS/Linux:

~/Library/Application Support/Claude/claude_desktop_config.json

For Windows:

C:UsersYOUR_USERNAMEAppDataRoamingClaudeclaude_desktop_config.json

Open the claude_desktop_config.json file in VS Code and add the following code to make the MCP server be displayed in the Claude for Desktop app’s UI:

{
  "mcpServers": {
    "sf-mcp-server": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/PARENT/FOLDER/sf-mcp-server/build/index.js"]
    }
  }
}

Save the file and restart the Claude for Desktop app. You should see the the sf-mcp-server in the tools UI in the app:

Try writing a prompt to get your connected orgs, for example:

list connected orgs

You should see a similar result:

Copy org’s alias or username and write the next prompt to actually query the records, for example:

query 5 account names and websites from the ORG_YOU_COPIED org

Then you will see something like this:

Conclusion

Congratulations! You’ve successfully built an MCP server that connects Claude Desktop with Salesforce. You can now query your Salesforce data using natural language, making data exploration more intuitive and efficient.

What we’ve accomplished

  • Built a Node.js MCP server with TypeScript
  • Implemented tools to list Salesforce orgs and execute SOQL queries
  • Configured Claude Desktop to use the custom server
  • Tested the integration with real queries

Next steps

While this tutorial used Salesforce CLI for simplicity, you can unlock the full power of Salesforce by implementing proper authentication with Connected Apps and directly using Salesforce APIs. This approach enables:

  • OAuth 2.0 authentication flows
  • Direct REST, SOAP, and Bulk API access
  • Real-time streaming with Platform Events
  • Metadata API for configuration management
  • Complete CRUD operations and complex business logic

The skills you’ve learned here apply to integrating Claude with any system or API. Whether building internal tools or automating workflows, MCP provides a solid foundation for creating AI-powered experiences.

Complete code for this project is available on GitHub.

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Twitter Email Print
Share
What do you think?
Love0
Sad0
Happy0
Sleepy0
Angry0
Dead0
Wink0
Previous Article Yet Another Study Finds That AI Is Making Us Dumb
Next Article NAACP planning to sue Musk AI company over supercomputer pollution
Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Stay Connected

248.1k Like
69.1k Follow
134k Pin
54.3k Follow

Latest News

BYD to launch full-electric cars in South Korea in mid-Jan · TechNode
Computing
Streaming services are now more popular than cable and broadcast TV combined
News
Forget students; Nigerian lecturers are using AI too |
Computing
Go Beyond 20/20 With These WIRED-Tested Smart Glasses
Gadget

You Might also Like

Computing

BYD to launch full-electric cars in South Korea in mid-Jan · TechNode

1 Min Read
Computing

Forget students; Nigerian lecturers are using AI too |

11 Min Read
Computing

Addicted to Your AI? New Research Warns of ‘Social Reward Hacking’ | HackerNoon

12 Min Read
Computing

Updated AMD ISP4 Driver For Linux Benefits The HP ZBook Ultra G1a, Future Ryzen Laptops

3 Min Read
//

World of Software is your one-stop website for the latest tech news and updates, follow us now to get the news that matters to you.

Quick Link

  • Privacy Policy
  • Terms of use
  • Advertise
  • Contact

Topics

  • Computing
  • Software
  • Press Release
  • Trending

Sign Up for Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

World of SoftwareWorld of Software
Follow US
Copyright © All Rights Reserved. World of Software.
Welcome Back!

Sign in to your account

Lost your password?