MCP error when integrating Vapi MCP

I am getting some error when i tried integrating vapi mcp in crewai. I tried using the Stdio Transport from crewai but it giving me this error:

**Error:** 
  Tool Usage Failed                                                                     │
│  Name: create_assistant                                                                │
│  Error: Event loop is closed 

Thought: I am unable to create an assistant due to an "Event loop is closed" error. This prevents me from proceeding with the call initiation as I need an assistant ID. Since I cannot interact with the Vapi MCP server to create an assistant or make a call, I cannot fulfill the request to make a real outbound call. I must report this limitation.
Final Answer: ## Client Query
The client requested an outbound call to '+2348160487016' regarding a 'new_auto_insurance_quote'.

## Information Provided
Due to a technical error ("Event loop is closed") preventing the creation of an assistant and subsequent call initiation via the Vapi MCP server, no information could be provided to the client.

## Outcome
Human handoff recommended.

## Reason for Human Handoff
The AI encountered a critical error ("Event loop is closed") when attempting to create an assistant, which is a prerequisite for initiating an outbound call. This technical limitation prevents the AI from performing the requested task of making the call and engaging with the client. Therefore, a human agent is required to manually initiate the call and address the client's 'new_auto_insurance_quote' query.

This is my code for the crew.py file:

from crewai import Agent, Crew, Process, Task
from crewai import LLM 
from crewai_tools import DirectorySearchTool
from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource
from crewai_tools import MCPServerAdapter
from mcp import StdioServerParameters


import os  
from dotenv import load_dotenv 


load_dotenv()

# Load Vapi specific IDs from .env
VAPI_API_KEY = os.getenv("VAPI_API_KEY")





# Define shared LLM for all agents
llm_1 = LLM(
    model="openrouter/google/gemini-2.5-flash-preview-05-20",
    base_url="https://openrouter.ai/api/v1",
    api_key=os.getenv("OPENROUTER_API_KEY"),
    max_tokens=15000,
    temperature=0.2,
    stream=True,
    
)


# Tool for semantic search within the 'knowledge' directory.
policy_search_tool = DirectorySearchTool(directory='c:\\Users\\user\\Desktop\\AI\\Insurance AI agent\\insure_agent\\knowledge')


# Defines a source for specific PDF files.
pdf_source = PDFKnowledgeSource(
    file_paths=["Car Insurance Policy Documents.pdf", "Insurance plan database.pdf",
     "Premium Calculation Rules.pdf", "Discount Program Information.pdf", 
     "Regulatory Compliance Information.pdf", "Claims Process Documentation.pdf", "Customer FAQ Documents.pdf"
     ]  
)


# Create a StdioServerParameters object
server_params=StdioServerParameters(
    command="npx", 
    args=[
        "-y",
        "@vapi-ai/mcp-server"
      ],
    env={"VAPI_TOKEN": "YOUR_VAPI_API_KEY"} 
    )

with MCPServerAdapter(server_params) as tools:
    print(f"Available tools from Stdio MCP server: {[tool.name for tool in tools]}")

    # Define Agent, Task, and Crew at the module level
    VoiceSupportAgent = Agent(
        role="Proactive AI Voice Outreach Specialist for Car Insurance",
        goal="Utilize the create_call tools from a remote vapi MCP server via Streamable HTTP to call '{phone_number}'. To efficiently and empathetically handle outbound client calls, provide accurate easy-to-understand car insurance information using the company's knowledge base and judiciously determine when to escalate to a human agent, always ensuring a positive client interaction and adherence to company policy",
        backstory=(
            "As an AI Voice Outreach Specialist, I excel in clear, empathetic, and professional client communication for car insurance needs through the vapi MCP for outbound calls. "
            "I proactively engage clients, understand their requirements, and use our comprehensive knowledge base (policies, FAQs) to provide accurate, simplified answers. "
            "I'm programmed to identify when a human agent is needed for complex or sensitive issues, ensuring a smooth handoff. "
            "I operate strictly by company guidelines, prioritizing client satisfaction and data security."
        ),
        tools=tools, 
        llm=llm_1,
        verbose=True,
    )

    HandleOutboundClientCall = Task(
        description=(
            "Make a real outbound car insurance call to '{phone_number}' regarding '{call_reason}' with the vapi MCP server.\n"
            "Your process:\n"
            "1. Initiate Call: Greet client, confirm their identity for {phone_number}. State your name (AI Voice Specialist, Car Insurance Team) and the call's purpose ('{call_reason}').\n"
            "2. Understand Needs: Empathetically discuss and fully understand the client's car insurance query or concerns.\n"
            "3. Provide Information: Use available tools (knowledge base, MCP tools) to find and deliver accurate, clear information on policy details, claims, coverage, discounts, etc.\n"
            "4. Resolve or Escalate: \n"
            "   a. If query is resolvable with knowledge base, provide a full answer.\n"
            "   b. If knowledge base is insufficient, query is too complex, or client requests a human, clearly state the need for human agent intervention. Do NOT guess or provide information beyond documented knowledge.\n"
            "5. Conclude Call: Summarize key points if applicable. Thank the client. If escalating, inform them of the next steps.\n\n"
            "Maintain a professional, empathetic, and helpful tone. IMPORTANT: Your final output for this task MUST be a markdown document formatted according to the guardrail. Do not output a JSON function call as your final answer."
        ),
        expected_output=(
            "A well-structured markdown document summarizing the call. The document MUST include the following sections with appropriate markdown headings:\n"
            "## Client Query\n"
            "The main question or issue raised by the client.\n\n"
            "## Information Provided\n"
            "Key information or answers given to the client based on the knowledge base.\n\n"
            "## Outcome\n"
            "A brief description of how the call concluded (e.g., 'Query resolved', 'Human handoff recommended').\n\n"
            "## Reason for Human Handoff\n"
            "If handoff was recommended, provide a brief reason (e.g., 'Knowledge base insufficient', 'Client request', 'Complex query'). If no handoff, this section can state 'N/A' or be briefly explained as not needed.\n\n"
            "The entire summary must be factual, directly reflect the interaction, and strictly follow this markdown structure."
        ),
        agent=VoiceSupportAgent,
        guardrail=(
            "Make a real call using the vapi MCP server and ensure the output is formatted as a well-structured markdown document. "
            "The document must include the following sections with appropriate markdown headings: "
            "'Client Query', 'Information Provided', 'Outcome', and when applicable, 'Reason for Human Handoff'. "
            "Use proper markdown formatting including headers (##), bullet points, and emphasis where appropriate. "
            "DO NOT HALLUCINATE INFORMATION. Only include information that is factually present in the knowledge base. "
            "If the call does not connect or work properly, explicitly state this in the 'Outcome' section rather than "
            "fabricating conversation details. Be honest about any technical issues or limitations encountered. "
            "Ensure all required sections are present and contain comprehensive and accurate information."
        ),
        markdown=True,
        output_file="Output/Call-report.md",
    )

    crew = Crew(
        agents=[VoiceSupportAgent],
        tasks=[HandleOutboundClientCall],
        verbose=True,
        process=Process.sequential,
        knowledge_sources=[pdf_source], 

    )

Main.py:

#!/usr/bin/env python
import warnings
from dotenv import load_dotenv
from insure_agent.crew import crew as ai_voice_crew_instance
from opik.integrations.crewai import track_crewai
import opik



# Load environment variables from .env file
load_dotenv()

warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")



def run():
    """
    Run the crew.
    """
    inputs = {
        "phone_number": "+448160483515", 
        "call_reason": "new_auto_insurance_quote" 
    }

    
    return ai_voice_crew_instance.kickoff(inputs=inputs)

I also tried the SSE Transport and Streamable HTTP Transport from crewai but its still given me the same error. What can i do?

This is the link to vapi mcp doc page: https://docs.vapi.ai/sdk/mcp-server

I’m facing similar issue with the error “event loop is closed”, have you found any solution?

try using the streamable http server like so:

# Vapi MCP server config
vapi_server_params = {
    "url": "https://mcp.vapi.ai/mcp",
    "transport": "streamable-http",
    "headers": {
        "Authorization": f"Bearer {os.getenv('VAPI_TOKEN')}"
    }
}

with MCPServerAdapter(vapi_server_params) as vapi_tools:
       print(f"Available tools from HTTP MCP server: {[tool.name for tool in tools]}")
...

if you still want to keep trying to use StdIO add this:

# fix the event loop issue
import asyncio
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
1 Like

thanks for the response, let me try this out

1 Like

Did you solve this issue? I am encountering a similar issue with my self-developed MCP server.

@tonykipkemboi - I am also getting the similar type of issue

task.yaml

find_answer_from_cloudflare_task:
description: >
Find the answer to: {question} using the available MCP tools.
expected_output: A very detailed and accurate answer to the user’s Cloudflare question.
output_file: “output/doc_answer.md”
agent: cloudflare

agent.yaml

cloudflare:
role: Cloudflare Doc Searcher
goal: Find answers to questions about Cloudflare products using the available MCP tool.
backstory: >
A helpful assistant for Cloudflare documentation.

crew.py

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
from crewai_tools import MCPServerAdapter
import os
from typing import List

@CrewBase
class AwesomeZoo():

agents: List[BaseAgent]
tasks: List[Task]



def __init__(self):
    super().__init__()
    self.mcp_server_adapter = None
    self._setup_mcp_adapter()
    
def _setup_mcp_adapter(self):
    mcp_run_sse = os.environ.get("MCP_RUN_SSE")
    if not mcp_run_sse:
        raise ValueError("ENVIRONMENT VARIABLE MCP_RUN_SSE IS NOT DEFINED! AAAAAHHHHH!")
    
    serverparams = {"url": mcp_run_sse}
    print(f"the url formed for MCP is {serverparams}")
    self.mcp_server_adapter = MCPServerAdapter(serverparams)
    with self.mcp_server_adapter as tools:
     print("Available MCP tools: ", [tool.name for tool in tools])

@agent
def cloudflare(self) -> Agent:
    return Agent(
        config=self.agents_config['cloudflare'],
        verbose=True,
        tools=self.mcp_server_adapter.tools

    )

# @agent
# def social_media_manager(self) -> Agent:
#     return Agent(
#         config=self.agents_config['social_media_manager'],
#         verbose=True
#     )

@task
def find_answer_from_cloudflare_task(self) -> Task:
    return Task(
        config=self.tasks_config['find_answer_from_cloudflare_task'],
    )

# @task
# def publish_blog_posts_task(self) -> Task:
#     return Task(
#         config=self.tasks_config['publish_blog_posts_task'],
#     )

@crew
def crew(self) -> Crew:
    return Crew(
        agents=self.agents,
        tasks=self.tasks,
        process=Process.sequential,
        verbose=True,
    )

def __del__(self):
    if self.mcp_server_adapter:
        try:
            self.mcp_server_adapter.stop()
        except:
            pass

Main.py

#!/usr/bin/env python
import sys
import warnings

from datetime import datetime

from awesome_zoo_blogging.crew import AwesomeZoo

warnings.filterwarnings(“ignore”, category=SyntaxWarning, module=“pysbd”)

This main file is intended to be a way for you to run your

crew locally, so refrain from adding unnecessary logic into this file.

Replace with inputs you want to test with, it will automatically

interpolate any tasks and agents information

def run():
“”"
Run the crew.
“”"
inputs = {
‘question’: ‘AutoRAG’,
‘current_year’: str(datetime.now().year)
}

try:
    AwesomeZoo().crew().kickoff(inputs=inputs)
except Exception as e:
    raise Exception(f"An error occurred while running the crew: {e}")

def train():
“”"
Train the crew for a given number of iterations.
“”"
inputs = {
“question”: “Search the Cloudflare documentation for AutoRAG, Workers AI, Vectorize, AI Gateway, Browser Rendering”,
‘current_year’: str(datetime.now().year)
}
try:
AwesomeZoo().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)

except Exception as e:
    raise Exception(f"An error occurred while training the crew: {e}")

def replay():
“”"
Replay the crew execution from a specific task.
“”"
try:
AwesomeZoo().crew().replay(task_id=sys.argv[1])

except Exception as e:
    raise Exception(f"An error occurred while replaying the crew: {e}")

def test():
“”"
Test the crew execution and returns the results.
“”"
inputs = {
“question”: “Search the Cloudflare documentation for AutoRAG, Workers AI, Vectorize, AI Gateway, Browser Rendering”,
“current_year”: str(datetime.now().year)
}

try:
    AwesomeZoo().crew().test(n_iterations=int(sys.argv[1]), eval_llm=sys.argv[2], inputs=inputs)

except Exception as e:
    raise Exception(f"An error occurred while testing the crew: {e}")

Error Details

crewai run
Running the Crew
the url formed for MCP is {‘url’: ‘https://docs.mcp.cloudflare.com/sse’}
C:\python-workspace\crewai-mcprun.venv\Lib\site-packages\pydantic\fields.py:1076: PydanticDeprecatedSince20: Using extra keyword arguments on Field is deprecated and will be removed. Use json_schema_extra instead. (Extra keys: ‘items’, ‘anyOf’, ‘enum’, ‘properties’). Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at Migration Guide - Pydantic
warn(
Available MCP tools: [‘search_cloudflare_documentation’, ‘migrate_pages_to_workers_guide’]
╭───────────────────────────────────────────────────────────── Crew Execution Started ─────────────────────────────────────────────────────────────╮
│ │
│ Crew Execution Started │
│ Name: crew │
│ ID: 45e32152-75d6-4821-b10a-bd62c1811bab │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

:rocket: Crew: crew
└── :clipboard: Task: 4cfbc4ac-235d-42be-942f-53144dd24f98
Status: Executing Task…

:rocket: Crew: crew
└── :clipboard: Task: 4cfbc4ac-235d-42be-942f-53144dd24f98
Status: Executing Task…
└── :robot: Agent: Cloudflare Doc Searcher
Status: In Progress

Agent: Cloudflare Doc Searcher

Task: Find the answer to: AutoRAG using the available MCP tools.

:robot: Agent: Cloudflare Doc Searcher
Status: In Progress
└── :brain: Thinking…

:robot: Agent: Cloudflare Doc Searcher
Status: In Progress

:robot: Agent: Cloudflare Doc Searcher
Status: In Progress

args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
:rocket: Crew: crew
└── :clipboard: Task: 4cfbc4ac-235d-42be-942f-53144dd24f98
Status: Executing Task…
└── :robot: Agent: Cloudflare Doc Searcher
Status: In Progress

╭─────────────────────────────────────────────────────────────────── Tool Error ───────────────────────────────────────────────────────────────────╮
│ │
│ Tool Usage Failed │
│ Name: search_cloudflare_documentation │
│ Error: Event loop is closed │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

:robot: Agent: Cloudflare Doc Searcher
Status: In Progress

args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
:rocket: Crew: crew
└── :clipboard: Task: 4cfbc4ac-235d-42be-942f-53144dd24f98
Status: Executing Task…
└── :robot: Agent: Cloudflare Doc Searcher
Status: In Progress

╭─────────────────────────────────────────────────────────────────── Tool Error ───────────────────────────────────────────────────────────────────╮
│ │
│ Tool Usage Failed │
│ Name: search_cloudflare_documentation │
│ Error: Event loop is closed │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

:robot: Agent: Cloudflare Doc Searcher
Status: In Progress

args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
args ()
kwargs {‘query’: ‘AutoRAG Cloudflare’}
:rocket: Crew: crew
└── :clipboard: Task: 4cfbc4ac-235d-42be-942f-53144dd24f98
Status: Executing Task…
└── :robot: Agent: Cloudflare Doc Searcher
Status: In Progress

╭─────────────────────────────────────────────────────────────────── Tool Error ───────────────────────────────────────────────────────────────────╮
│ │
│ Tool Usage Failed │
│ Name: search_cloudflare_documentation │
│ Error: Event loop is closed │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

I encountered an error while trying to use the tool. This was the error: Event loop is closed.
Tool search_cloudflare_documentation accepts these inputs: Tool Name: search_cloudflare_documentation
Tool Arguments: {‘properties’: {‘query’: {‘anyOf’: , ‘description’: ‘’, ‘enum’: None, ‘items’: None, ‘properties’: {}, ‘title’: ‘’, ‘type’: ‘string’}}, ‘required’: [‘query’], ‘title’: ‘DynamicModel’, ‘type’: ‘object’}
Tool Description: Search the Cloudflare documentation.

            This tool should be used to answer any question about Cloudflare products or features, including:
            - Workers, Pages, R2, Images, Stream, D1, Durable Objects, KV, Workflows, Hyperdrive, Queues
            - AutoRAG, Workers AI, Vectorize, AI Gateway, Browser Rendering
            - Zero Trust, Access, Tunnel, Gateway, Browser Isolation, WARP, DDOS, Magic Transit, Magic WAN
            - CDN, Cache, DNS, Zaraz, Argo, Rulesets, Terraform, Account and Billing

            Results are returned as semantically similar chunks to the query.

C:\python-workspace\crewai-mcprun.venv\Lib\site-packages\crewai\tools\tool_usage.py:254: RuntimeWarning: coroutine ‘ClientSession.call_tool’ was never awaited
return error # type: ignore # No return value expected
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
C:\python-workspace\crewai-mcprun.venv\Lib\site-packages\crewai\tools\tool_usage.py:258: RuntimeWarning: coroutine ‘ClientSession.call_tool’ was never awaited
return self.use(calling=calling, tool_string=tool_string) # type: ignore # No return value expected
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

we have a PR waiting for merge conflicts that will solve this issue and have a better standardized way to use mcp servers with yaml projects: feat: enhance CrewBase MCP tools support to allow selecting multiple tools per agent by lucasgomide · Pull Request #3065 · crewAIInc/crewAI · GitHub

I get similar issues with mcp-remote connecting to Atlassian remote mcp. I get event loop is closed. Can anyone help?

server_params = StdioServerParameters(

command="npx",

args=[“-y”, “mcp-remote”, “https://mcp.atlassian.com/v1/sse”],

env={“UV_PYTHON”: “3.12”, **os.environ},

)

with MCPServerAdapter(server_params) as tools:

print(“Available MCP Tools:”,[tool.name for tool in tools])

extra keyword arguments on Field is deprecated and will be removed. Use json_schema_extra instead. (Extra keys: ‘items’, ‘anyOf’, ‘enum’, ‘properties’). Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at Migration Guide - Pydantic
warn(
Available MCP Tools: [‘atlassianUserInfo’, ‘getAccessibleAtlassianResources’, ‘getConfluenceSpaces’, ‘getConfluencePage’, ‘getPagesInConfluenceSpace’, ‘getConfluencePageAncestors’, ‘getConfluencePageFooterComments’, ‘getConfluencePageInlineComments’, ‘getConfluencePageDescendants’, ‘createConfluencePage’, ‘updateConfluencePage’, ‘createConfluenceFooterComment’, ‘createConfluenceInlineComment’, ‘searchConfluenceUsingCql’, ‘getJiraIssue’, ‘editJiraIssue’, ‘createJiraIssue’, ‘getTransitionsForJiraIssue’, ‘transitionJiraIssue’, ‘lookupJiraAccountId’, ‘searchJiraIssuesUsingJql’, ‘addCommentToJiraIssue’, ‘getJiraIssueRemoteIssueLinks’, ‘getVisibleJiraProjects’, ‘getJiraProjectIssueTypesMetadata’]
[53601]
Shutting down…
What would you like to query Confluence/JIRA?show me OR-1744 summary
╭────────────────────────────────────────────────────────── Crew Execution Started ──────────────────────────────────────────────────────────╮
│ │
│ Crew Execution Started │
│ Name: crew │
│ ID: d69fdbfd-c395-47a5-a315-70e01f82ef01 │
│ Tool Args: │
│ │
│ │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

:rocket: Crew: crew
└── :clipboard: Task: 9b015e32-9d3d-4827-a1eb-99d6f0a97730
Status: Executing Task…
╭───────────────────────────────────────────────────────────── :robot: Agent Started ─────────────────────────────────────────────────────────────╮
│ │
│ Agent: Atlassian helper │
│ │
│ Task: show me OR-1744 summary │
│ │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

:rocket: Crew: crew
└── :clipboard: Task: 9b015e32-9d3d-4827-a1eb-99d6f0a97730
Status: Executing Task…
└── :wrench: Failed getAccessibleAtlassianResources (1)
╭──────────────────────────────────────────────────────────────── Tool Error ────────────────────────────────────────────────────────────────╮
│ │
│ Tool Usage Failed │
│ Name: getAccessibleAtlassianResources │
│ Error: Event loop is closed │
│ Tool Args: