How to Convert a Lead Using Salesforce MCP

Recently, Salesforce has been making big strides in AI automation and integration including its new framework called Headless 360, which allows AI agents and agentic workflows to access and do user-authorized changes on Salesforce orgs. Users can prompt their agents to create, update and delete records, run Flows and Apex processes and so much more. With the core paradigm of Salesforce, and the tech world at large, shifting from deterministic development to agentic solutions, it is now time to consider using AI models for our daily Salesforce tasks as well.

SurveyVista: Effortless Data Collection to Action

Due to the rapidly shifting nature of this space, a Salesforce admin, developer or user must be ready to adapt, which means to effectively hand over the daily time consuming tasks to AI’s figurative hands. It helps to start small and build intuition with a task most Salesforce users already know by heart: converting a Lead.

Converting Salesforce Leads with Headless 360 & MCPs

We will try to convert a Lead through the use of MCPs presented to us by Salesforce as part of their Headless 360 push. MCP stands for Model Context Protocol, an open standard created by Anthropic in November 2024 to connect AI models safely to external data sources and tools (our Salesforce org in our case). An MCP server works as an interface between the data source and the AI model; it translates the data that the source or the tool provides into a language that the AI model can read and perceive. Luckily for us, basic access to Salesforce MCP servers is free, though usage may consume Flex Credits and therefore be billed.

We will then make Claude act as the intermediary between our requests and Salesforce applications i.e. we will ask Claude to convert our Lead. We can use any AI model we want (ChatGPT, DeepSeek etc.), but Claude is subjectively the easiest to use, and Salesforce itself has already been working together with Claude.

How to Set Up a Salesforce MCP Server in Setup

Navigate to Setup → MCP Servers. You will find a bunch of default MCP servers that Salesforce has already built.

Salesforce MCP Servers: Displaying 12 of 12 Servers, sorted by server status

Free Mentorship With Talent Stacker

For the purposes of this article, we will build one from scratch. Press the “Add MCP Server” button on the upper right corner and pick the “Create Salesforce MCP Server” option. Assign the names of your choice and click Create.

Create Salesforce MCP Server

Navigate to the Tools tab at the top to see what your MCP can currently do, which is (unsurprisingly) nothing. If you try to add a tool, you will not see anything different either unless you have already built custom tools beforehand. There is simply not an MCP tool that will help us convert a Lead. Therefore, we will have to build one from scratch; essentially, we will build an Apex class that takes the Lead we want as a parameter and uses the Database.convertLead() method on it.

Why Lead Conversion in Salesforce Requires Custom Apex MCP Tools

You might be wondering why we have to write Apex code and present it as an MCP tool if all we want to do is to convert a Lead i.e. tick the isConverted flag and create new Account, Contact and Opportunity records. After all, Lead conversion is a well hidden set of compound DML statements, therefore the SObject Mutations MCP should be well equipped to take care of it, right?

Unfortunately, this assumption is not correct. Lead conversion is not a compound DML statement in disguise. It is a distinct platform operation with no DML equivalent. Database.convertLead()resolves record matching against existing Accounts and Contacts. It applies configured Lead Field Mappings and reparents related Activities, Notes, and Cases, and also fires conversion-specific automation atomically as a single guaranteed unit. This avoids stitching together and manually rolling back individual statements.

Handing this to a generic SObject Mutations MCP means reimplementing complex core logic. You would also have to sync every admin’s mapping and deduplication rule changes manually. Salesforce already maintains all of this logic for us. That’s why conversion needs its own purpose-built Apex action rather than a general-purpose DML tool.

Building the Invocable Apex Class for Salesforce MCP Integration

Open your IDE of choice and create the Apex class that you will be using for this application. This Apex class needs:

  • the global or public access modifier, since we want our method to be accessible from outside
  • a method annotated with @InvocableMethod along with its variables annotated with @InvocableVariable. The MCP invocation of a method works similarly to how Flows invoke Apex methods.

Since SObjects cannot be invocable variables, our method cannot accept Leads as parameters. Instead, we need to configure it to work with Lead IDs. Our Apex code should accept a Lead ID and find the corresponding Lead. It should then check whether the Lead can convert to an existing Account using its Company field. Finally, it should use the Database.convertLead() method to convert the Lead. Ideally, we should also control the Opportunity side of the conversion. We should decide whether the Lead creates an Opportunity and what that Opportunity should be named. This would work similarly to the standard Lead conversion process.

Defining Invocable Variables for the Lead Conversion Method

There are three parameters we need: the ID of the Lead we want to convert, a flag to store whether we want to create a new Opportunity or not, and the name of the new Opportunity if we want a new one. All of them will have to be annotated with @InvocableVariable.

global class ConvertLeadRequest {

	@InvocableVariable(Label = 'Lead Id' Required = true)
	public String leadId;

	@InvocableVariable(Label = 'Create Opportunity' Required = true)
	public Boolean createOpp;

	@InvocableVariable(Label = 'Opportunity Name' Required = false)
	public String oppName;

}

Implementing the Invocable Apex Logic

Our method, which will have to work with MCPs, needs to be annotated with @InvocableMethod and take List as its parameter. First, it will fetch the Leads with the given IDs, which usually consists of only one Lead ID. It will then check their respective Company fields and fetch the Accounts based on those Company values. If it finds a match, it will need to attach the newly created Contact to the existing Account that matches. Otherwise, it will create a new Account. It will also take our parameters createOpp and oppName into consideration during conversion to a new Opportunity. All things considered, our method will look like this:

@InvocableMethod(
        Label = 'Convert Lead'
        Description = 'Converts a Lead'
        Callout = false
)
global static void convertLead(List<ConvertLeadRequest> requests) {
    System.debug('ConvertLeadInvocable.convertLead start');
    List<Boolean> isSuccessful = new List<Boolean>();

    Set<Id> leadSet = new Set<Id>();
    for (ConvertLeadRequest clr : requests) {
        leadSet.add(clr.leadId);
    }

    Map<Id, Lead> leadMap = new Map<Id, Lead>([
            SELECT Id, Name, Company
            FROM Lead
            WHERE Id IN :leadSet
    ]);

    Set<String> accountSet = new Set<String>();
    for (Lead ld : leadMap.values()) {
        accountSet.add(ld.Company);
    }

    Map<String, Account> accountMap = new Map<String, Account>([
            SELECT Id, Name
            FROM Account
            WHERE Name IN :accountSet
    ]);

    System.debug('accountMap: ' + accountMap);

    List<Database.LeadConvert> leadContexts = new List<Database.LeadConvert>();
    for (ConvertLeadRequest clr : requests) {
        Lead leadTemp = leadMap.get(clr.leadId);

        Database.LeadConvert lc = new Database.LeadConvert();
        lc.setLeadId(clr.leadId);
        lc.setConvertedStatus(LEAD_CONVERSION_STATUS);
        lc.setDoNotCreateOpportunity(!clr.createOpp);
        lc.setOpportunityName(clr.oppName);
        lc.setBypassAccountDedupeCheck(false);
        lc.setBypassContactDedupeCheck(false);

        Account companyTemp = accountMap.get(leadTemp.Company);
        if (companyTemp != null && companyTemp.Id != null) {
            System.debug('Found a company for ' + leadTemp.Name + ': ' + companyTemp.Id);
            lc.setAccountId(companyTemp.Id);
        }

        leadContexts.add(lc);
    }

    System.debug('leadContexts: ' + leadContexts);
    List<Database.LeadConvertResult> results = Database.convertLead(leadContexts, true);
    // allOrNothing is set as true so that the agent will return an error in case of failure

    for (Database.LeadConvertResult res : results) {
        if (!res.isSuccess()) {
            System.debug('Conversion failed: ' + String.valueOf(res.getErrors()));
        }
        isSuccessful.add(res.isSuccess());
    }

    System.debug('ConvertLeadInvocable.convertLead end');
}

You may have noticed the variable named LEAD_CONVERSION_STATUS. This is intentionally left there — you can replace it with the customized Lead Converted status on your org or assign it as a static variable in class context, above the method.

global static final String LEAD_CONVERSION_STATUS = 'Closed - Converted';

It’s also worth noting that Lead conversion will fail if the Lead is owned by a queue. Therefore, if your org can have such a case, it is worth running the setOwnerId(Id) method when values are being set for the Database.LeadConvert object.

This will take care of the Apex side of our mechanism. However, our work on Salesforce is not done; our MCP is still not capable of using the method we just built, we need to introduce it manually.

(In a production environment, our Apex class would have to be accompanied by a test class, which is out of our scope for this article)

Adding Your Invocable Apex Action to the Salesforce MCP Server

Go back to Setup → MCP Servers and navigate to the MCP server mentioned. Click the Add Server Assets button and pick the “Add Tools” option. You should be able to see the method there. Click the Add Tool button and then click Save.

Add Tools: Convert Lead Invocable Action

Since our conversion method works with Lead IDs, we also need our MCP to run SOQL queries to fetch those IDs when the name of a Lead is given. Hence, we should also add the SOQL tool. Click the Add Server Assets button and pick the “Add from Server” option. Go to the SObject All MCP server and pick the Query Records (SOQL) tool. Click Done.

Add Assets from an MCP Server: Select tools and prompts to import from your connected MCP server.

Finally, activate your MCP through the Activate button on the top right.

Lead Conversion Test Type: Custom Server Status: Inactive

We have now successfully introduced our method to the MCP and are now halfway there towards our three-way party.

How to Connect Claude Desktop to Salesforce via MCP

Now, let us move to the other side of the equation: the AI agent. To connect our Salesforce org with our agent, we need to introduce our MCP to the model. We will use Salesforce’s External Client App functionality for this integration.

Before doing so, we need to configure our OAuth settings. Navigate to Setup → OAuth and OpenID Connect Settings and enable Require Proof Key for Code Exchange (PKCE) Extension for Supported Authorization Flows. This strengthens our org’s OAuth configuration and allows Claude to connect successfully.

Next, open your Claude client and navigate to Settings → Connectors. Click Add in the top-right corner to create a custom connector. As of September 2026, Claude does not offer an out-of-the-box Salesforce connector. The setup screen will ask for a name and your MCP server URL, which you can find under your MCP details. Choose a name that clearly distinguishes this connector from your others, then paste your MCP URL into the appropriate field.

Add custom connector: Connect Claude to your data and tools

Configuring Salesforce OAuth for Claude

If the connector setup also asks you for a Client ID and Client Secret, or if you are receiving an error with the reference code “ofid_e99841b04f01022e” after creating your connector, go to Setup → External Client App Manager. Create a new External Client App and give it a name of your choosing. Make sure that:

  • the Enable OAuth checkbox is checked
  • selected OAuth scopes include Access Salesforce hosted MCP servers (mcp_api) and Perform requests at any time (refresh_token, offline_access)
  • Require secret for Web Server Flow and Require secret for Refresh Token Flow are unchecked under the Security subsection
  • Require Proof Key for Code Exchange (PKCE) extension for Supported Authorization Flows is checked
  • Issue JSON Web Token (JWT)-based access tokens for named users is checked

Go to the Tools tab and then the OAuth Settings section of the External Client App. Click the Consumer Key and Secret button. Verify yourself when prompted, and copy the Consumer Key and Secret. Paste them to the input boxes on the Claude client.

If you are not prompted for a Client ID and Client Secret, you can skip to the part ahead.

Completing Claude Authentication and MCP Connection

You will then be asked to self-authenticate, both on Claude and on Salesforce. Do both, and if everything goes smoothly, your MCP will be connected.

Salesforce Lead Conversion Tool Permissions Choose When Claude is allowed to use these tools

Now let’s put our code to test by converting a Lead of our choosing. I will convert Mike Braund from the standard Salesforce record data that is present on all Developer Edition orgs (hence no distinguishing PII is given below).

Lead Object: Mr Mike Braund

Testing the Lead Conversion Prompt in Claude

We will try to convert our Lead with a simple prompt: “Convert the lead named "Mike Braund" on my Salesforce org. Make sure that the opportunity name is "Mike Braund 2026"“. This way we will also test if Claude can fetch the parameters it has been given and assign them accordingly.

To achieve its task, Claude will occasionally ask for permissions. Make sure to give them to it by pressing any option that starts with “Allow”. The screenshot below notifies us that Claude is ready to run our Apex method.

Claude Desktop chat interface showing a prompt to convert a Salesforce lead named "Mike Braund" into an opportunity named "Mike Braund 2026". Below the prompt, a confirmation box titled "Claude wants to use ConvertLeadInvocable from Salesforce Lead Conversion" displays a JSON input payload containing createOpp: true, leadId: "00Qfj00000d7BumEAE", and oppName: "Mike Braund 2026". At the bottom, action buttons show options to "Deny", "Allow for this task", or "Allow once".

Once all necessary permissions are given, and all tasks are done, Claude will notify you that the task is completed successfully. It will even run a second SOQL query to ensure that the IsConverted flag of the Lead is checked.

Claude Desktop chat interface displaying a prompt to convert the lead "Mike Braund" with an opportunity named "Mike Braund 2026". Below the prompt, metadata indicates 2 tools were used via the Salesforce Lead Conversion integration, followed by Claude's response: "Done — the lead Mike Braund has been converted successfully, creating an Account, Contact, and an Opportunity named 'Mike Braund 2026'."

Claude isn’t lying. If we navigate to the page of Mike Braund on our org, we will see that the Lead is converted successfully; there is now a Contact in its place which is linked to a new Account and an Opportunity.

Therefore, our experiment is successful; we can now do one of our most basic tasks through our AI agents instead of clicking, effectively saving time which can then be spent on actually getting the Leads that are to be converted.

Start Automating Your Salesforce Workflows with AI Agents Today

AI agents are becoming smarter and more capable with every passing day. Salesforce users and developers should hand repetitive, time-consuming tasks over to these AI tools. Developers must ensure these tools support people rather than replace their jobs. The goal is to help people work more efficiently and with less effort. A good approach is to start small and build confidence with familiar, repetitive Salesforce tasks.

Explore related content:

AIforce: Salesforce’s New AI Interface Layer for Slack, Claude, and Lightning

Agentforce Agent Flow Action Best Practices

Accounts and Contacts in Salesforce: The Foundation Every Admin Needs to Get Right

Sinan Kırım

I am a Salesforce Administrator and Developer with 6+ years of experience building customized solutions across various Salesforce products. I have expertise and interest in software development and support, imperative programming including Apex, system integration and data modeling.

Leave a Reply

Back to top button

Discover more from Salesforce Break

Subscribe now to keep reading and get access to the full archive.

Continue reading