Are you looking at all the new AI tools and wondering how you can connect them to your powerful, battle-tested APIs? You’re in the right place!

In this walkthrough, we’ll enhance an existing Salesforce System API by implementing the Dual-Exposure Pattern. This is a fancy way of saying we’ll make your API “AI-ready” by adding a new, smart entry point for AI agents without breaking your existing RESTful interface.

We will expose three core operations—create a case, get case details, and update a case—as discoverable AI tools, all from the comfort of Anypoint Code Builder.

🎥 See It in Action!

Want to watch the process? Check out the full video walkthrough right here:

The “Why”: The Dual-Exposure Pattern 🚪🚪

Our main goal is to use the Dual-Exposure Pattern.

Think of it this way: your API is a secure building. Right now, it has one “front door” for traditional applications (the REST API). We’re going to add a second “front door” (an MCP Server) specifically for AI agents.

The best part? Both doors lead to the same underlying business logic. This means you ensure consistency, save a ton of development time, and don’t have to manage two different codebases!

✅ What You’ll Need

  • An existing MuleSoft API project (We’ll use a salesforce-system-api).
  • Anypoint Code Builder (VS Code).

Ready? Let’s get building!


Step 1: Get Your Project Ready

First, we need to add the MuleSoft MCP Connector to our project.

  1. Open your pom.xml file.
  2. Add this dependency inside your <dependencies> section. This gives you the MCP components you’ll need.
<dependency>
    <groupId>com.mulesoft.connectors</groupId>
    <artifactId>mule-mcp-connector</artifactId>
    <version>1.2.0</version>
    <classifier>mule-plugin</classifier>
</dependency>

Next, let’s create a new, separate config file to keep our MCP flows nice and organized.

  1. In the Explorer, right-click the src/main/mule directory.
  2. Select Mule: Create Configuration File.
  3. Name it salesforce-system-mcp.xml.

Step 2: The Secret Sauce – Refactor for Reusability 💡

This is the most important step for making your logic reusable.

Our original API flow for “get case” probably uses data that only comes from an HTTP listener, like attributes.uriParams.caseNumber. An AI tool won’t send a URI parameter!

We need to “decouple” our logic from the HTTP trigger. We’ll use a flow variable as the common, shared piece of data.

  1. Open your original salesforce-system-api.xml file.
  2. In the get:\cases\(caseNumber):api-config flow, add a Transform Message component right at the beginning.
  3. Use this DataWeave expression. It cleverly checks for the HTTP parameter first, but if it’s not there, it uses a variable we’ll set later (vars.caseNumber).
%dw 2.0
output application/java
vars.caseNumber default attributes.uriParams.caseNumber
  1. Now, find the next transform in that same flow (e.g., Mock IncidentDetails Response) and update it to use our new variable: vars.caseNumber (instead of attributes.uriParams.caseNumber).
  2. Repeat this process for your patch:\cases\(caseNumber):api-config flow, too.

Awesome! Our core logic is now independent and can be called from anywhere—HTTP or AI!

Step 3: Build Your AI ‘Front Door’ with MCP Tools

Let’s switch to our new salesforce-system-mcp.xml file and build our AI tools.

🔧 Tool 1: Get Case Details (get_case_details)

  1. Drag an MCP Tool Listener onto the canvas to start a new flow.
  2. Click the + icon to create a new MCP Server Configuration:
    • Name: mule-mcp-server
    • Connection: Select Streamable HTTP Server.
    • Listener config: Select your existing http-listener-config. (This is the magic that makes the Dual-Exposure pattern work! ✨)
    • Server Name: mule-mcp-server
    • Server Version: 1.0.0
  3. Back in the Tool Listener properties, define what the AI agent will see:
    • Name: get_case_details
    • Description: Retrieves the details of a specific Salesforce case.
    • Parameters Schema: This JSON tells the AI what inputs it needs.
      {
        "$schema": "[http://json-schema.org/draft-07/schema#](http://json-schema.org/draft-07/schema#)",
        "type": "object",
        "properties": { "caseNumber": { "type": "string" } },
        "required": ["caseNumber"]
      }
      
  4. Inside the flow, add a Transform Message to create the caseNumber variable that our refactored flow expects.
  5. Add a Flow Reference component and set its Flow name to get:\cases\(caseNumber):api-config.

🔧 Tool 2: Create a New Case (create_case)

  1. Drag another Tool Listener onto the canvas.
  2. Configure it:
    • Configuration: Select your existing mule-mcp-server.
    • Name: create_case
    • Description: Creates a new case in Salesforce.
    • Parameters Schema:
      {
        "$schema": "[http://json-schema.org/draft-07/schema#](http://json-schema.org/draft-07/schema#)",
        "type": "object",
        "properties": {
          "subject": { "type": "string" },
          "description": { "type": "string" }
        },
        "required": ["subject", "description"]
      }
      
  3. Add a Flow Reference and point it to post:\cases:api-config. (This one is simple; the original flow already expects the right payload!)

🔧 Tool 3: Update an Existing Case (update_case)

  1. Drag one final Tool Listener onto the canvas.
  2. Configure it:
    • Configuration: Select mule-mcp-server.
    • Name: update_case
    • Description: Updates an existing Salesforce case.
    • Parameters Schema:
      {
        "$schema": "[http://json-schema.org/draft-07/schema#](http://json-schema.org/draft-07/schema#)",
        "type": "object",
        "properties": {
          "caseNumber": { "type": "string" },
          "newStatus": { "type": "string" }
        },
        "required": ["caseNumber", "newStatus"]
      }
      
  3. Add a Transform Message to set the caseNumber variable (from payload.caseNumber) and also set the payload for the newStatus.
  4. Add a Flow Reference and point it to patch:\cases\(caseNumber):api-config.

Step 4: The Grand Finale – Run and Test! 🚀

You’ve done all the hard work. Time for the payoff!

  1. Run the Application: Hit “Run and Debug” in Anypoint Code Builder.
  2. Configure the MCP Client:
    • Follow the steps to Add an MCP Server in VS Code.
    • Paste this JSON into your mcp.json file. This tells the VS Code chat agent where to find your local server.
      {
        "servers": {
          "salesforce-system-mcp": {
            "url": "http://localhost:8081/mcp",
            "type": "http"
          }
        },
        "inputs": []
      }
      
  3. Verify Discovery: Save the mcp.json file. Look at the status bar at the bottom of VS Code. You should see the MCP status update to “start | 3 tools”. This confirms it found your three new AI tools! 🥳
  4. Test in the Chat:
    • Open the Chat view in VS Code.
    • At the top of the chat input, click the dropdown and select Agent.
    • Now, talk to your API using natural language!
      • create a new case with subject "Printer Offline" and description "The main office printer is not responding"
      • get details for case INC1C23456
      • update case INC123456 to status "Resolved"

The chat agent will understand your request, find the right tool, and ask for your permission to run it. You’ll see the response from your Mule app right in the chat.

Congratulations! You now have a true dual-exposure API, ready for both traditional and AI-driven integration! 🎉