How to integrate Close MCP with LangChain

Connect LangChain to Close MCP. Create a new sales lead for acme corp, log an outbound call with follow-up notes, and more using natural language, with authentication handled for you.

Close logoClose
Api Key

Close is a CRM platform built for sales teams, combining calling, email automation, and predictive dialers. It streamlines sales workflows and boosts productivity with all-in-one communication tools.

70 Tools45 Triggers

Introduction

This guide walks you through connecting Close to LangChain using the Composio tool router. By the end, you'll have a working Close agent that can create leads and tasks, log calls and emails, send SMS messages, track opportunities, and review activities through natural language commands.

This guide will help you understand how to give your LangChain agent real control over a Close account through Composio's Close MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

Also integrate Close with

TL;DR

Here's what you'll learn:
  • Get and set up your OpenAI and Composio API keys
  • Connect your Close project to Composio
  • Create a Tool Router MCP session for Close
  • Initialize an MCP client and retrieve Close tools
  • Build a LangChain agent that can interact with Close
  • Set up an interactive chat interface for testing

What is LangChain?

LangChain is a framework for developing applications powered by language models. It provides tools and abstractions for building agents that can reason, use tools, and maintain conversation context.

Key features include:

  • Agent Framework: Build agents that can use tools and make decisions
  • MCP Integration: Connect to external services through Model Context Protocol adapters
  • Memory Management: Maintain conversation history across interactions
  • Multi-Provider Support: Works with OpenAI, Anthropic, and other LLM providers

What is the Close MCP server, and what's possible with it?

The Close MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Close account. It provides structured and secure access to your sales pipeline, so your agent can perform actions like creating leads, logging calls, sending SMS, managing tasks, and retrieving notes on your behalf.

  • Lead creation and management: Instantly create new leads with company details and contact information, keeping your CRM fresh and organized without manual entry.
  • Automated call logging: Have your agent log both inbound and outbound calls to specific leads, capturing call notes, durations, and recordings for seamless tracking.
  • SMS communication: Direct your agent to send or log SMS messages with leads, enabling timely follow-ups and improved client engagement.
  • Task management: Let your agent create tasks, set due dates, and track completion, making sure nothing slips through the cracks in your sales workflow.
  • Note retrieval and analysis: Fetch notes by lead or date, so your agent can summarize past interactions, surface important insights, or prepare for upcoming calls.

What is the Composio tool router, and how does it fit here?

What is Composio SDK?

Composio's Composio SDK helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Composio SDK

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Composio SDK works

The Composio SDK follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Step by step10 STEPS
1

Prerequisites

Before starting this tutorial, make sure you have:
  • Python 3.10 or higher installed on your system
  • A Composio account with an API key
  • An OpenAI API key
  • Basic familiarity with Python and async programming
2

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key. You'll need credits to use the models, or you can connect to another model provider.
  • Keep the API key safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Navigate to your API settings and generate a new API key.
  • Store this key securely as you'll need it for authentication.
3

Install dependencies

npm install @composio/langchain @langchain/core @langchain/openai @langchain/mcp-adapters dotenv

Install the required packages for LangChain with MCP support.

What's happening:

  • @composio/langchain provides Composio integration for LangChain
  • @langchain/mcp-adapters enables MCP client connections
  • @langchain/core is the core agent framework
  • dotenv/config loads environment variables
4

Set up environment variables

bash
COMPOSIO_API_KEY=your_composio_api_key_here
COMPOSIO_USER_ID=your_composio_user_id_here
OPENAI_API_KEY=your_openai_api_key_here

Create a .env file in your project root.

What's happening:

  • COMPOSIO_API_KEY authenticates your requests to Composio's API
  • COMPOSIO_USER_ID identifies the user for session management
  • OPENAI_API_KEY enables access to OpenAI's language models
5

Import dependencies

import { Composio } from '@composio/core';
import { LangchainProvider } from '@composio/langchain';
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";
import * as readline from 'readline';
import 'dotenv/config';

dotenv.config();
What's happening:
  • We're importing LangChain's MCP adapter and Composio SDK
  • The dotenv/config import loads environment variables from your .env file
  • This setup prepares the foundation for connecting LangChain with Close functionality through MCP
6

Initialize Composio client

const composioApiKey = process.env.COMPOSIO_API_KEY;
const userId = process.env.COMPOSIO_USER_ID;

if (!composioApiKey) throw new Error('COMPOSIO_API_KEY is not set');
if (!userId) throw new Error('COMPOSIO_USER_ID is not set');

async function main() {
    const composio = new Composio({
        apiKey: composioApiKey as string,
        provider: new LangchainProvider()
    });
What's happening:
  • We're loading the COMPOSIO_API_KEY from environment variables and validating it exists
  • Creating a Composio instance that will manage our connection to Close tools
  • Validating that COMPOSIO_USER_ID is also set before proceeding
7

Create a Tool Router session

const session = await composio.create(
    userId as string,
    {
        toolkits: ['close']
    }
);

const url = session.mcp.url;
What's happening:
  • We're creating a Tool Router session that gives your agent access to Close tools
  • The create method takes the user ID and specifies which toolkits should be available
  • The returned session.mcp.url is the MCP server URL that your agent will use
  • This approach allows the agent to dynamically load and use Close tools as needed
8

Configure the agent with the MCP URL

const client = new MultiServerMCPClient({
    "close-agent": {
        transport: "http",
        url: url,
        headers: {
            "x-api-key": process.env.COMPOSIO_API_KEY
        }
    }
});

const tools = await client.getTools();

const agent = createAgent({ model: "gpt-5", tools });
What's happening:
  • We're creating a MultiServerMCPClient that connects to our Close MCP server via HTTP
  • The client is configured with a name and the URL from our Tool Router session
  • getTools() retrieves all available Close tools that the agent can use
  • We're creating a LangChain agent using the GPT-5 model
9

Set up interactive chat interface

let conversationHistory: any[] = [];

console.log("Chat started! Type 'exit' or 'quit' to end the conversation.\n");
console.log("Ask any Close related question or task to the agent.\n");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: 'You: '
});

rl.prompt();

rl.on('line', async (userInput: string) => {
    const trimmedInput = userInput.trim();

    if (['exit', 'quit', 'bye'].includes(trimmedInput.toLowerCase())) {
        console.log("\nGoodbye!");
        rl.close();
        process.exit(0);
    }

    if (!trimmedInput) {
        rl.prompt();
        return;
    }

    conversationHistory.push({ role: "user", content: trimmedInput });
    console.log("\nAgent is thinking...\n");

    const response = await agent.invoke({ messages: conversationHistory });
    conversationHistory = response.messages;

    const finalResponse = response.messages[response.messages.length - 1]?.content;
    console.log(`Agent: ${finalResponse}\n`);
        
        rl.prompt();
    });

    rl.on('close', () => {
        console.log('\n👋 Session ended.');
        process.exit(0);
    });
What's happening:
  • We initialize an empty conversationHistory list to maintain context across interactions
  • A readline interface is used to continuously accept user input from the command line
  • When a user types a message, it's added to the conversation history and sent to the agent
  • The agent processes the request using the invoke() method with the full conversation history
  • Users can type 'exit', 'quit', or 'bye' to end the chat session gracefully
10

Run the application

main().catch((err) => {
    console.error('Fatal error:', err);
    process.exit(1);
});
What's happening:
  • We call the main() function to start the application

Complete Code

Here's the complete code to get you started with Close and LangChain:

import { Composio } from '@composio/core';
import { LangchainProvider } from '@composio/langchain';
import { MultiServerMCPClient } from "@langchain/mcp-adapters";  
import { createAgent } from "langchain";
import * as readline from 'readline';
import 'dotenv/config';

const composioApiKey = process.env.COMPOSIO_API_KEY;
const userId = process.env.COMPOSIO_USER_ID;

if (!composioApiKey) throw new Error('COMPOSIO_API_KEY is not set');
if (!userId) throw new Error('COMPOSIO_USER_ID is not set');

async function main() {
    const composio = new Composio({
        apiKey: composioApiKey as string,
        provider: new LangchainProvider()
    });

    const session = await composio.create(
        userId as string,
        {
            toolkits: ['close']
        }
    );

    const url = session.mcp.url;
    
    const client = new MultiServerMCPClient({
        "close-agent": {
            transport: "http",
            url: url,
            headers: {
                "x-api-key": process.env.COMPOSIO_API_KEY
            }
        }
    });
    
    const tools = await client.getTools();
  
    const agent = createAgent({ model: "gpt-5", tools });
    
    let conversationHistory: any[] = [];
    
    console.log("Chat started! Type 'exit' or 'quit' to end the conversation.\n");
    console.log("Ask any Close related question or task to the agent.\n");
    
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
        prompt: 'You: '
    });

    rl.prompt();

    rl.on('line', async (userInput: string) => {
        const trimmedInput = userInput.trim();
        
        if (['exit', 'quit', 'bye'].includes(trimmedInput.toLowerCase())) {
            console.log("\nGoodbye!");
            rl.close();
            process.exit(0);
        }
        
        if (!trimmedInput) {
            rl.prompt();
            return;
        }
        
        conversationHistory.push({ role: "user", content: trimmedInput });
        console.log("\nAgent is thinking...\n");
        
        const response = await agent.invoke({ messages: conversationHistory });
        conversationHistory = response.messages;
        
        const finalResponse = response.messages[response.messages.length - 1]?.content;
        console.log(`Agent: ${finalResponse}\n`);
        
        rl.prompt();
    });

    rl.on('close', () => {
        console.log('\nSession ended.');
        process.exit(0);
    });
}

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

Conclusion

You've successfully built a LangChain agent that can interact with Close through Composio's Tool Router.

Key features of this implementation:

  • Dynamic tool loading through Composio's Tool Router
  • Conversation history maintenance for context-aware responses
  • Async Python provides clean, efficient execution of agent workflows
You can extend this further by adding error handling, implementing specific business logic, or integrating additional Composio toolkits to create multi-app workflows.
TOOLS & TRIGGERS

Supported Tools and Triggers

Every Close action and event your agent gets out of the box.

Create Call

Creates a new call record in Close.

Create Contact

Create a contact on an existing Close lead, or create a new lead named after the contact when lead_id is omitted.

Create Custom Activity

Create a draft or published custom activity instance on a Close lead.

Create Custom Field

Create a custom-field definition for Close leads or opportunities.

Create Email

Create or log a Close email activity.

Create Lead

Creates a new lead in Close CRM.

Create Note

Create a plaintext or rich-text note activity on a Close lead.

Create Opportunity

Create a Close sales opportunity on an existing lead, or create an Untitled lead for it when lead_id is omitted.

Create Sequence

Create a Close sales sequence with ordered call or email steps.

Create SMS Message

Create an SMS activity on a Close lead to log received, sent, or draft messages, or to send or schedule a message.

Create Task

Create a Close task associated with a lead, using task text and an actionable date, with optional completion status and assignment.

Delete Activity Custom Field

Permanently delete one Close activity custom-field definition by ID.

Delete Call

This tool allows you to delete a specific call activity in Close.

Delete Custom Activity

Permanently delete one Close custom activity instance by ID.

Delete Email

This tool allows you to permanently delete a specific email activity in Close.

Delete Lead

Permanently delete one Close lead by ID.

Delete Lead Custom Field

Permanently delete a Close lead custom-field definition and its values.

Delete Note

Permanently delete one Close note activity by ID.

Delete Opportunity

Permanently delete one Close opportunity by ID.

Delete Opportunity Status

Permanently delete an unused Close opportunity status; this cannot be undone.

Delete SMS

Permanently delete one Close SMS activity by ID.

Download File

Download bytes from a provider-issued Close Files API URL.

Get Activity Custom Field

Retrieve one Close activity custom-field definition by ID.

Get Call

Retrieve one Close call activity by ID with optional field projection.

Get Contact

Retrieve one Close contact by ID, optionally limiting returned fields.

Get Created Activity

Retrieve one Close lead-creation activity with optional field projection.

Get Email

Retrieve one Close email activity by ID with optional field projection.

Get Event

Retrieve one Close event-log record by event ID.

Get Lead

Retrieve one Close lead by ID with optional field projection.

Get Lead Custom Field

Retrieve one Close lead custom-field definition by ID.

Get Notes

This tool retrieves a list of note activities from Close.

Get Note by ID

Retrieve one Close note activity by ID with optional field projection.

Get Opportunity

Retrieve one Close opportunity by ID with optional field projection.

Get Sequence

Retrieve one Close sequence by ID with its workflow configuration.

Get Shared Custom Field

Retrieve one Close shared custom-field definition by ID.

Get SMS

Retrieve one Close SMS activity by ID with optional field projection.

Get Task

Retrieve one Close task by ID with optional field projection.

Get User

Retrieve one Close organization user by ID with optional field projection.

List Activities

Lists one page of Close email or call activities using documented filters.

List Contacts

List Close contacts with lead filtering, projection, and offset pagination.

List Custom Activities

List Close custom activity instances with filters and offset pagination.

List Custom Activity Types

This tool lists the custom activity types defined in a Close organization, returning each type's id and name.

List Custom Objects

List custom object instances attached to a Close lead, optionally by type.

List Custom Object Types

This tool lists the custom object types defined in a Close organization, returning each type's id and name.

List Events

List Close change events with filters, projection, and cursor pagination.

List Lead Custom Fields

List Close lead custom-field definitions with projection and pagination.

List Leads

List or text-search Close leads with field projection and offset pagination.

List Lead Statuses

List the configured lead statuses for the connected organization.

List Opportunities

List a page of Close opportunities with offset pagination.

List Opportunity Custom Fields

List Close opportunity custom-field definitions with projection and pagination.

List Opportunity Statuses

List the configured opportunity statuses for the connected organization.

List Outcomes

List Close call and meeting outcomes with projection and offset pagination.

List Pipelines

List pipelines and their ordered opportunity statuses.

List Sequences

List Close sales sequences with offset pagination.

List Sequence Subscriptions

List Close sequence subscriptions.

List Tasks

List Close tasks using task, assignee, lead, date, and pagination filters.

List Unified Activities

List one page of Close activities across all types and matching filters.

List Users

List users in the connected Close organization with offset pagination.

List Webhook Subscriptions

List webhook subscriptions configured for the Close organization.

Search Data

Search Close objects using the structured Advanced Filtering query language.

Update Activity Custom Field

Update mutable settings of one Close activity custom-field definition.

Update Contact

Update standard and custom fields on one existing Close contact.

Update Custom Activity

Update standard and custom fields on one Close custom activity instance.

Update Email

Update an existing Close email activity.

Update Lead Custom Field

Update a Close lead custom-field definition.

Update Note

Update the mutable content and metadata of one Close note activity.

Update Opportunity

Update standard and custom fields on one Close opportunity.

Update Sequence

Update a Close sequence name or replace its entire ordered step list.

Update Task

Update assignment, actionable date, or completion state on a Close task; lead tasks can also update text.

Who Am I

Return the identity (email, name) of the connected Close account.

FAQ

Frequently asked questions

Start with Close.It takes 30 seconds.

Managed auth, hosted MCP servers, and every Close tool your agent needs.Free to start.

Start building