AgentBridge
README.md
AgentBridge
A custom MCP (Model Context Protocol) server that exposes personal productivity data — Google Calendar, Gmail, and local notes — as agent-callable tools, paired with a LangGraph ReAct agent that decides when to use them, with Human-in-the-Loop approval, guardrails, and persistent memory — plus both a terminal and a web chat interface.
Built as a portfolio project to demonstrate practical multi-agent orchestration, tool-calling protocols, and hybrid RAG — not just a single chatbot wrapper.
Architecture
User query (terminal or Streamlit UI)
│
▼
LangGraph ReAct agent (Groq / Anthropic Claude)
· conversation persisted to SQLite — survives restarts
│
├─ no tool needed → answers directly
│
└─ tool needed
│
▼
[Guardrails] blocked? ──yes──▶ rejected automatically, agent told why
│ no
▼
[Human-in-the-Loop] "Approve this tool call? (y/n)"
│ (only proceeds on approval)
▼
MCP client ──HTTP──▶ MCP server (localhost:8765)
│
┌─────┼─────────────┐
▼ ▼ ▼
Calendar Gmail Notes (local RAG:
(Google (Google FAISS + sentence-
API) API) transformer embeddings)
What's in this repo
File Purpose
src/agentbridge/server.py MCP server — exposes 3 tools over HTTP
src/agentbridge/rag.py Local RAG layer: chunks + embeds notes/*.md, semantic search via FAISS
src/agentbridge/guardrails.py Safety checks run before any tool call reaches approval
agent.py LangGraph ReAct agent — terminal chat, Human-in-the-Loop, SQLite persistence
app.py Streamlit web UI for the same agent, with approve/reject buttons
test_client.py Standalone script to sanity-check the MCP server without the agent
notes/ Sample notes indexed by search_notes
Tools exposed by the MCP server
get_upcoming_events — reads Google Calendar (read-only scope)
search_emails — searches Gmail using Gmail's query syntax (read-only scope)
search_notes — semantic search over local .md notes using a local embedding model (no API key needed, runs offline after first download)
Safety features
Human-in-the-Loop: every tool call pauses for explicit approval before it runs (interrupt_before=["tools"] in LangGraph).
Guardrails (guardrails.py): blocks tool calls before they even reach approval if they request an unreasonable amount of data (possible runaway loop) or search for sensitive terms like passwords.
Persistent memory: conversation history is saved to agentbridge_memory.db (SQLite) via SqliteSaver, so context survives restarting the agent.
Setup
1. Install dependencies
bash
cd agentbridge
uv sync
2. Google Cloud setup (Calendar + Gmail)
Go to https://console.cloud.google.com/ → create/select project "AgentBridge"
APIs & Services → Library → enable Google Calendar API and Gmail API
APIs & Services → Credentials → Create Credentials → OAuth client ID
Application type: Desktop app
Download the JSON, rename it exactly credentials.json, place it in the agentbridge/ root folder (same level as pyproject.toml)
Google Auth Platform → Audience → Test users → add your own Google account email (required while the app is in "Testing" mode)
⚠️ Never commit credentials.json or token.json — both are already in .gitignore.
3. LLM provider
Default is Groq (free):
powershell
$env:GROQ_API_KEY = "your-groq-key" # get one at console.groq.com/keys
To use Claude instead:
powershell
$env:LLM_PROVIDER = "anthropic"
$env:ANTHROPIC_API_KEY = "your-anthropic-key"
4. Run — Terminal
Terminal 1 — MCP server:
bash
uv run python -m agentbridge.server
Terminal 2 — Agent:
bash
uv run python agent.py
5. Run — Web UI (optional, instead of Terminal 2)
bash
uv run streamlit run app.py
Opens a browser chat window with clickable Approve/Reject buttons.
Try these queries
What are my upcoming meetings?
Do I have any unread emails?
What did we decide about the transport layer? (answered from notes/)
Multi-tool chaining: Do I have any meetings tomorrow, and are there any emails related to them? — the agent will call Calendar, then Gmail, asking for approval on each.
Guardrails demo: Search my emails for my password reset code — gets blocked automatically, before any approval prompt.
Resume bullet
Built AgentBridge, a custom MCP (Model Context Protocol) server exposing Google Calendar, Gmail, and local notes as agent-callable tools, integrated with a LangGraph ReAct agent featuring Human-in-the-Loop tool approval, rule-based guardrails, SQLite-backed persistent memory, a local FAISS RAG layer for semantic note search, and a Streamlit web interface.
Interview talking points
MCP transport tradeoffs: started with stdio, switched to streamable-http after hitting Windows-specific pipe issues.
Human-in-the-Loop: implemented via LangGraph's interrupt_before, pausing before the tools node and resuming with Command(resume=True) only on explicit approval.
Guardrails: a small rule-based layer that runs before approval — can discuss how this differs from (and could evolve into) a full framework like Guardrails AI or NeMo Guardrails.
Persistence: swapped InMemorySaver for SqliteSaver — can explain why production agents need durable state, not just in-memory.
RAG vs Vectorless RAG: search_notes uses real vector search (FAISS + sentence-transformer embeddings) because notes are numerous and stable; a vectorless approach suits smaller, fast-changing data like a single email thread better.This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues