CrewAI - Barndoor Documentation

Running a CrewAI Agent with Barndoor

This guide walks you through how to run a CrewAI task using the Barndoor SDK to connect to an MCP server (like Notion), fetch connection parameters, and use the MCP tools within a CrewAI agent. Feel free to check out the repo here and also run the app with Streamlit for a browser UI demo.

πŸ“Ή Demo: Running CrewAI with Barndoor MCP

How To Integrate Barndoor AI's SDK into CrewAI Agent from Barndoor AI on Vimeo

Watch on Vimeo

Prerequisites

Source

Show Code Example

import streamlit as st
from datetime import datetime
from pathlib import Path
from dotenv import load_dotenv
import barndoor.sdk as bd
import asyncio
from crewai import Agent, Task, Crew
from crewai_tools import MCPServerAdapter

# ─────────────────────────────────────────────
# Core async function (DO NOT use asyncio.run!)
# ─────────────────────────────────────────────
async def run_crewai_task(server_slug: str, user_query: str, log):
    load_dotenv(Path(__file__).parent / ".env")
    sdk = None

try:
        log("Logging in to Barndoor...")
        sdk = await bd.login_interactive()
        log("Logged in!")

servers = await sdk.list_servers()
        server = next((s for s in servers if s.slug == server_slug), None)
        if not server:
            raise ValueError(f"Server '{server_slug}' not found.")

display_name = (
            server.name
            or getattr(server.mcp_server_directory, "name", None)
            or server_slug.replace("-", " ").title()
        )
        log(f"Using: **{display_name}**")

await bd.ensure_server_connected(sdk, server_slug)
        params, public_url = await bd.make_mcp_connection_params(sdk, server_slug)

# Fix token β†’ authorization (handles both formats)
        if "token" in params:
            params["authorization"] = f"Bearer {params.pop('token')}"
        elif "authorization" in params and not params["authorization"].startswith("Bearer "):
            params["authorization"] = f"Bearer {params['authorization']}"

log("Connected! Loading tools...")

with MCPServerAdapter(params) as tools:
            log(f"Loaded **{len(tools)} tools**")

agent = Agent(
                role=f"{display_name} Expert",
                goal=f"Complete any task in the user's {display_name} account using real data.",
                backstory=f"You are a master of {display_name} with full access via Barndoor MCP.",
                tools=tools,
                verbose=True,
                allow_delegation=False,
            )

task = Task(
                description=user_query,
                expected_output="Clear, accurate, well-formatted answer. Use tables/lists when helpful.",
                agent=agent,
            )

crew = Crew(agents=[agent], tasks=[task], verbose=True)
            log("Running task...")
            result = await crew.kickoff_async()

log("Done!")
        return str(result), display_name

except Exception as e:
        error_msg = f"Error: {type(e).__name__}: {e}"
        log(error_msg)
        return error_msg, "Error"
    finally:
        if sdk:
            await sdk.aclose()

# ─────────────────────────────────────────────
# Load servers once at startup
# ─────────────────────────────────────────────
@st.cache_data(ttl=300)  # Refresh every 5 minutes

def load_servers():
    import asyncio
    load_dotenv()
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        sdk = loop.run_until_complete(bd.login_interactive())
        servers = loop.run_until_complete(sdk.list_servers())
        loop.run_until_complete(sdk.aclose())

options = {}
        for s in servers:
            if s.connection_status in ("connected", "available"):
                name = (
                    s.name
                    or getattr(s.mcp_server_directory, "name", None)
                    or s.slug.replace("-", " ").title()
                )
                options[f"{name} β€’ {s.slug}"] = s.slug
        return options or {"No servers found": None}
    finally:
        loop.close()

# ─────────────────────────────────────────────
# Main UI
# ─────────────────────────────────────────────
servers = load_servers()

if not servers or list(servers.values())[0] is None:
    st.error("No connected MCP servers found. Go to https://app.barndoor.ai and connect an app.")
    st.stop()

server_choice = st.selectbox("Choose your app:", options=list(servers.keys()))
selected_slug = servers[server_choice]

query = st.text_area(
    "What do you want to do?",
    placeholder="Examples:\nβ€’ List my recent Salesforce opportunities\nβ€’ Summarize Notion pages tagged 'Q4'\nβ€’ Show unread Gmail from last 3 days",
    height=140,
)

if st.button("Run Agent", type="primary", use_container_width=True):
    if not query.strip():
        st.warning("Please enter a task.")
        st.stop()

log_placeholder = st.empty()
    log_lines = []

def log(msg):
        ts = datetime.now().strftime("%H:%M:%S")
        log_lines.append(f"<small>{ts}</small> {msg}")
        log_placeholder.markdown("\n".join(log_lines), unsafe_allow_html=True)

with st.spinner("Working..."):  
        result, app_name = asyncio.run(run_crewai_task(selected_slug, query, log))

st.markdown("---")
    st.subheader(f"Result from {app_name}")

if result.startswith("Error:"):
        st.error(result)
    else:
        st.markdown(result)

st.caption(f"Completed β€’ {datetime.now():%Y-%m-%d %I:%M %p}")

1. Install Dependencies

uv pip install -r requirements.txt

2. Create a .env File

This script expects a .env file in the same directory as main.py. Add the following environment variables:

# Replace with your agent's client ID and secret from Barndoor
# See: https://app.barndoor.ai/agents
AGENT_CLIENT_ID={{barndoor-agent-client-id}}
AGENT_CLIENT_SECRET={{barndoor-agent-client-secret}}

# Replace with your tenant hostname
BARNDOOR_API=https://{{your-tenant}}.platform.barndoor.ai
BARNDOOR_URL=https://{{your-tenant}}.platform.barndoor.ai

# Valid OpenAI API Key
# see: https://platform.openai.com/api-keys
OPENAI_API_KEY={{your-openapi-key}}

# Default values, no changes required
AUTH_DOMAIN=auth.barndoor.ai
API_AUDIENCE=https://barndoor.ai/
MODE=production

Replace the placeholders with real values from your Barndoor project.

3. Run either Crew CLI or UI (browser) version:

uv run crew-cli.py

or

uv run streamlit run crew-ui.py

πŸ› οΈ Troubleshooting